| |
| |
| |
| |
| |
|
|
| name: DevSecOps Pipeline |
|
|
| on: |
| push: |
| branches: [main] |
| pull_request: |
| branches: [main] |
|
|
| env: |
| REGISTRY: ecr.aws/devsecops |
| IMAGE_NAME: ${{ github.repository }} |
|
|
| permissions: |
| id-token: write |
| contents: read |
| security-events: write |
|
|
| jobs: |
| |
| |
| |
| sast: |
| name: SAST & Secret Scan |
| runs-on: ubuntu-latest |
| steps: |
| - uses: actions/checkout@v4 |
|
|
| - name: Semgrep SAST |
| uses: semgrep/semgrep-action@v1 |
| with: |
| config: >- |
| p/security-audit |
| p/secrets |
| p/owasp-top-ten |
| publishToken: ${{ secrets.SEMGREP_TOKEN }} |
|
|
| - name: Trivy Secret Scan |
| uses: aquasecurity/trivy-action@master |
| with: |
| scan-type: fs |
| scanners: secret |
| exit-code: 1 |
| severity: CRITICAL,HIGH |
|
|
| - name: Checkov IaC Scan |
| uses: bridgecrewio/checkov-action@master |
| with: |
| directory: terraform/ |
| framework: terraform |
| output_format: sarif |
| output_file: checkov.sarif |
| soft_fail: false |
|
|
| - name: Upload SARIF |
| uses: github/codeql-action/upload-sarif@v3 |
| if: always() |
| with: |
| sarif_file: . |
|
|
| |
| |
| |
| build: |
| name: Build & Push |
| needs: sast |
| runs-on: ubuntu-latest |
| outputs: |
| image_tag: ${{ steps.meta.outputs.tags }} |
| image_digest: ${{ steps.build.outputs.digest }} |
| steps: |
| - uses: actions/checkout@v4 |
|
|
| - name: Configure AWS Credentials |
| uses: aws-actions/configure-aws-credentials@v4 |
| with: |
| role-to-assume: ${{ secrets.AWS_ROLE_ARN }} |
| role-session-name: github-actions |
| aws-region: us-east-1 |
|
|
| - name: Login to ECR |
| uses: aws-actions/amazon-ecr-login@v2 |
|
|
| - name: Docker Meta |
| id: meta |
| uses: docker/metadata-action@v5 |
| with: |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} |
| tags: | |
| type=sha,prefix= |
| type=ref,event=branch |
| type=semver,pattern={{version}} |
| |
| - name: Build |
| id: build |
| uses: docker/build-push-action@v5 |
| with: |
| context: . |
| push: true |
| tags: ${{ steps.meta.outputs.tags }} |
| labels: ${{ steps.meta.outputs.labels }} |
| cache-from: type=gha |
| cache-to: type=gha,mode=max |
| build-args: | |
| BUILD_DATE=${{ github.event.head_commit.timestamp }} |
| |
| |
| |
| |
| scan: |
| name: Container Security Scan |
| needs: build |
| runs-on: ubuntu-latest |
| steps: |
| - name: Trivy Vulnerability Scan |
| uses: aquasecurity/trivy-action@master |
| with: |
| image-ref: ${{ needs.build.outputs.image_tag }} |
| format: sarif |
| output: trivy.sarif |
| exit-code: 1 |
| severity: CRITICAL,HIGH |
| ignore-unfixed: true |
|
|
| - name: Generate SBOM |
| uses: anchore/sbom-action@v0 |
| with: |
| image: ${{ needs.build.outputs.image_tag }} |
| format: spdx-json |
| output-file: sbom.spdx.json |
|
|
| - name: Upload SBOM |
| uses: actions/upload-artifact@v4 |
| with: |
| name: sbom |
| path: sbom.spdx.json |
|
|
| |
| |
| |
| test: |
| name: Integration Test & DAST |
| needs: build |
| runs-on: ubuntu-latest |
| steps: |
| - uses: actions/checkout@v4 |
|
|
| - name: Run Integration Tests |
| run: | |
| docker compose -f docker-compose.test.yml up --abort-on-container-exit |
| |
| - name: OWASP ZAP Full Scan |
| uses: zaproxy/action-full-scan@v0.10.0 |
| with: |
| target: https://staging.platform.internal |
| rules_file_name: zap-rules.tsv |
| cmd_options: '-a -j' |
| fail_action: true |
|
|
| |
| |
| |
| sign: |
| name: Sign & Attest |
| needs: [build, scan] |
| runs-on: ubuntu-latest |
| steps: |
| - name: Cosign Install |
| uses: sigstore/cosign-installer@v3 |
|
|
| - name: Sign Image |
| run: | |
| cosign sign --yes ${{ needs.build.outputs.image_tag }}@${{ needs.build.outputs.image_digest }} |
| |
| - name: Attest SBOM |
| run: | |
| cosign attest --yes \ |
| --predicate sbom.spdx.json \ |
| --type spdxjson \ |
| ${{ needs.build.outputs.image_tag }}@${{ needs.build.outputs.image_digest }} |
| |
| |
| |
| |
| deploy-staging: |
| name: Deploy → Staging |
| needs: [sign, test] |
| runs-on: ubuntu-latest |
| environment: staging |
| steps: |
| - name: Update Kustomize Image Tag |
| run: | |
| git config user.name "github-actions[bot]" |
| git config user.email "github-actions[bot]@users.noreply.github.com" |
| cd k8s/workloads/${{ matrix.workload }} |
| kustomize edit set image ${{ env.IMAGE_NAME }}=${{ needs.build.outputs.image_tag }} |
| git commit -am "chore: update image tag for staging" |
| git push |
| |
| - name: ArgoCD Sync |
| run: | |
| argocd app sync staging-app --grpc-web |
| |
| deploy-prod: |
| name: Deploy → Production |
| needs: deploy-staging |
| runs-on: ubuntu-latest |
| environment: production |
| steps: |
| - name: ArgoCD Sync |
| run: | |
| argocd app sync prod-app --grpc-web |
| |
| - name: Smoke Test |
| run: | |
| curl -sf https://platform.internal/healthz || exit 1 |
| |