trivy scanned severity fixed #33
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: DevSecOps CI/CD Pipeline | |
| permissions: | |
| contents: write | |
| actions: write | |
| packages: write | |
| pull-requests: write | |
| issues: write | |
| on: | |
| push: | |
| branches: [ main ] | |
| paths-ignore: | |
| - 'kubernetes/deployment.yaml' | |
| pull_request: | |
| branches: [ main ] | |
| jobs: | |
| test: | |
| name: Unit Testing | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.9' | |
| - name: Install dependencies | |
| run: | | |
| pip install --upgrade pip | |
| pip install -r app/requirements.txt | |
| pip install pytest | |
| - name: Run tests | |
| run: pytest tests/ || echo "No tests yet" | |
| lint: | |
| name: SAST & Secrets Scan | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: TruffleHog Secret Scan | |
| uses: trufflesecurity/trufflehog@main | |
| with: | |
| path: ./ | |
| extra_args: --debug --only-verified | |
| build: | |
| name: Build Application | |
| runs-on: ubuntu-latest | |
| needs: [test, lint] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Create build artifact | |
| run: | | |
| mkdir build | |
| cp -r app/requirements.txt build/ | |
| - name: Upload build artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: app-build | |
| path: build/ | |
| docker: | |
| name: Docker Build, Scan & Push | |
| runs-on: ubuntu-latest | |
| needs: [build] | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository }} | |
| outputs: | |
| image_tag: ${{ steps.set_output.outputs.image_tag }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: app-build | |
| path: . | |
| - name: Setup Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Login to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Docker metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| tags: | | |
| type=sha,format=long | |
| type=ref,event=branch | |
| latest | |
| # 🔧 FIX 1: Build LOCAL image | |
| - name: Build Docker image | |
| run: docker build -t flask-app:local . | |
| # 🔧 FIX 2: Trivy scans LOCAL image | |
| - name: Trivy Image Scan | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| image-ref: flask-app:local | |
| exit-code: 1 | |
| ignore-unfixed: true | |
| severity: CRITICAL,HIGH | |
| # 🔧 FIX 3: Create Docker network for ZAP | |
| - name: Create Docker network | |
| run: docker network create zap-net | |
| # 🔧 FIX 4: Run App Container on network (no host port exposure) | |
| - name: Run App Container | |
| run: | | |
| docker run -d --network zap-net --name zap-test flask-app:local | |
| sleep 15 | |
| # 🔧 FIX 5: ZAP runs on network, targets container by name | |
| - name: OWASP ZAP Baseline Scan | |
| run: | | |
| mkdir -p zap-reports | |
| chmod 777 zap-reports | |
| docker run --network zap-net -v $(pwd)/zap-reports:/zap/wrk/:rw -t ghcr.io/zaproxy/zaproxy:stable /zap/zap.sh -cmd -quickurl http://zap-test:5000 -quickprogress -quickout /zap/wrk/report.html | |
| - name: Upload ZAP Reports | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: zap-reports | |
| path: zap-reports/ | |
| # 🔧 FIX 6: Stop Container and remove network | |
| - name: Stop Container and Cleanup | |
| run: | | |
| docker stop zap-test && docker rm zap-test | |
| docker network rm zap-net | |
| # Push ONLY after security scans pass | |
| - name: Push Docker image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| - name: Set image tag output | |
| id: set_output | |
| run: echo "image_tag=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT | |
| update-k8s: | |
| name: Update Kubernetes Deployment | |
| runs-on: ubuntu-latest | |
| needs: [docker] | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| token: ${{ secrets.TOKEN }} | |
| - name: Setup Git config | |
| run: | | |
| git config user.name "GitHub Actions" | |
| git config user.email "actions@github.com" | |
| - name: Update Kubernetes deployment file | |
| env: | |
| IMAGE_TAG: sha-${{ github.sha }} | |
| GITHUB_REPOSITORY: ${{ github.repository }} | |
| REGISTRY: ghcr.io | |
| run: | | |
| NEW_IMAGE="${REGISTRY}/${GITHUB_REPOSITORY}:${IMAGE_TAG}" | |
| sed -i "s|image: ${REGISTRY}/.*|image: ${NEW_IMAGE}|g" kubernetes/deployment.yaml | |
| echo "Updated deployment to use image: ${NEW_IMAGE}" | |
| grep -A 1 "image:" kubernetes/deployment.yaml | |
| - name: Commit and push changes | |
| run: | | |
| git add kubernetes/deployment.yaml | |
| git commit -m "Update Kubernetes deployment with new image tag: ${{ needs.docker.outputs.image_tag }} [skip ci]" || echo "No changes" | |
| git push |