-
Notifications
You must be signed in to change notification settings - Fork 74
[SYNPY-1764] Add Trivy container vulnerability scanning #1346
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: add-claude-md
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| --- | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This reusable workflow exists specifically for the periodic scan's auto-remediation path. It's a self-contained build-scan-push pipeline that the Unlike the The Note: This comment was drafted with AI assistance and reviewed by me for accuracy. |
||
| # | ||
| # Reusable workflow to build, scan, and push a Docker image. | ||
| # Called by the periodic scan workflow to rebuild images | ||
| # when new vulnerabilities are found. | ||
| # | ||
| name: Build and publish a Docker image | ||
|
|
||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| REF_TO_CHECKOUT: | ||
| required: false | ||
| type: string | ||
| description: "Reference to checkout, e.g. a tag like v1.0.1. Defaults to the branch/tag of the current event." | ||
| IMAGE_REFERENCES: | ||
| required: true | ||
| type: string | ||
| description: "Comma-separated image references, e.g., ghcr.io/sage-bionetworks/synapsepythonclient:1.0.1" | ||
|
|
||
| env: | ||
| TARFILE_NAME: image.tar | ||
| LOCAL_IMAGE_TAG: rebuild-image:local | ||
|
|
||
| jobs: | ||
| build: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| ref: ${{ inputs.REF_TO_CHECKOUT }} | ||
|
|
||
| - name: Set up Docker Buildx | ||
| uses: docker/setup-buildx-action@v2 | ||
|
|
||
| - name: Build Docker image | ||
| uses: docker/build-push-action@v5 | ||
| with: | ||
| context: . | ||
| push: false | ||
| load: true | ||
| tags: rebuild-image:local | ||
| file: ./Dockerfile | ||
| platforms: linux/amd64 | ||
|
|
||
| - name: Save Docker image to tar | ||
| run: docker save rebuild-image:local -o ${{ env.TARFILE_NAME }} | ||
|
|
||
| - name: Upload tarball for use by Trivy job | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: ${{ env.TARFILE_NAME }} | ||
| path: ${{ env.TARFILE_NAME }} | ||
| retention-days: 1 | ||
|
|
||
| outputs: | ||
| tarfile_artifact: ${{ env.TARFILE_NAME }} | ||
|
|
||
| trivy-scan: | ||
| needs: build | ||
| uses: "./.github/workflows/trivy.yml" | ||
| with: | ||
| SOURCE_TYPE: tar | ||
| IMAGE_NAME: rebuild-image:local | ||
| TARFILE_NAME: ${{ needs.build.outputs.tarfile_artifact }} | ||
| EXIT_CODE: 1 | ||
| permissions: | ||
| contents: read | ||
| security-events: write | ||
| actions: read | ||
|
|
||
| push-image: | ||
| needs: [build, trivy-scan] | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
| packages: write | ||
| steps: | ||
| - name: Download tar artifact | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| name: ${{ needs.build.outputs.tarfile_artifact }} | ||
| path: /tmp | ||
|
|
||
| - name: Load Docker image from tar | ||
| run: docker load -i /tmp/${{ needs.build.outputs.tarfile_artifact }} | ||
|
|
||
| - name: Login to GitHub Container Registry | ||
| uses: docker/login-action@v2 | ||
| with: | ||
| registry: ghcr.io | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Tag and push Docker image | ||
| shell: bash | ||
| run: | | ||
| IFS=',' read -ra TAGS <<< "${{ inputs.IMAGE_REFERENCES }}" | ||
| for TAG in "${TAGS[@]}"; do | ||
| docker tag rebuild-image:local "$TAG" | ||
| docker push "$TAG" | ||
| done | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,91 @@ | ||||||||||||||
| --- | ||||||||||||||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the central reusable scanning workflow — called from both
The The alternate Trivy DB repos ( SARIF results are uploaded even when Trivy finds vulnerabilities (the Note: This comment was drafted with AI assistance and reviewed by me for accuracy. |
||||||||||||||
| # | ||||||||||||||
| # This workflow runs Trivy on a Docker image | ||||||||||||||
| # It can pull the image from a container registry | ||||||||||||||
| # or download a tar file. The latter is used | ||||||||||||||
| # to check a container image prior to publishing | ||||||||||||||
| # to the registry. | ||||||||||||||
|
|
||||||||||||||
| name: Run Trivy on a Docker image and push results to GitHub | ||||||||||||||
|
|
||||||||||||||
| on: | ||||||||||||||
| workflow_call: | ||||||||||||||
| inputs: | ||||||||||||||
| SOURCE_TYPE: # 'tar' or 'image' | ||||||||||||||
| required: true | ||||||||||||||
| type: string | ||||||||||||||
| TARFILE_NAME: # only used if SOURCE_TYPE=='tar' | ||||||||||||||
| required: false | ||||||||||||||
| type: string | ||||||||||||||
| IMAGE_NAME: | ||||||||||||||
| required: true | ||||||||||||||
| type: string | ||||||||||||||
| EXIT_CODE: # return code for failed scan. 0 means OK. Non-zero will fail the build when there are findings. | ||||||||||||||
| required: false | ||||||||||||||
| type: number | ||||||||||||||
| default: 0 | ||||||||||||||
| outputs: | ||||||||||||||
| trivy_conclusion: | ||||||||||||||
| description: "The pass/fail status from Trivy" | ||||||||||||||
| value: ${{ jobs.trivy.outputs.trivy_conclusion }} | ||||||||||||||
|
|
||||||||||||||
| env: | ||||||||||||||
| sarif_file_name: trivy-results.sarif | ||||||||||||||
| # downloading the trivy-db from its default GitHub location fails because | ||||||||||||||
| # the site experiences too many downloads. The fix is to pull from this | ||||||||||||||
| # alternate location. | ||||||||||||||
| TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db:2 | ||||||||||||||
| TRIVY_JAVA_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-java-db:1 | ||||||||||||||
|
|
||||||||||||||
| jobs: | ||||||||||||||
| trivy: | ||||||||||||||
| name: Trivy | ||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||
| permissions: | ||||||||||||||
| contents: read | ||||||||||||||
| security-events: write | ||||||||||||||
|
|
||||||||||||||
| steps: | ||||||||||||||
| - name: Checkout repository | ||||||||||||||
| uses: actions/checkout@v4 | ||||||||||||||
|
|
||||||||||||||
| - name: Download tar file | ||||||||||||||
| id: tar-download | ||||||||||||||
| uses: actions/download-artifact@v4 | ||||||||||||||
| if: ${{ inputs.SOURCE_TYPE == 'tar' }} | ||||||||||||||
| with: | ||||||||||||||
| name: ${{ inputs.TARFILE_NAME }} | ||||||||||||||
| path: /tmp | ||||||||||||||
|
|
||||||||||||||
| - name: Load docker image from tar file | ||||||||||||||
| if: ${{ inputs.SOURCE_TYPE == 'tar' }} | ||||||||||||||
| run: docker load -i ${{ steps.tar-download.outputs.download-path }}/${{ inputs.TARFILE_NAME }} | ||||||||||||||
|
|
||||||||||||||
| - name: Run Trivy vulnerability scanner for any major issues | ||||||||||||||
| uses: aquasecurity/trivy-action@0.32.0 | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Due to try scan attack: https://sagebionetworks.jira.com/browse/SMR-703, we should also update the trivy version like this PR here: https://github.com/Sage-Bionetworks/sage-monorepo/pull/3951/changes |
||||||||||||||
| id: trivy | ||||||||||||||
| with: | ||||||||||||||
| image-ref: ${{ inputs.IMAGE_NAME }} | ||||||||||||||
| ignore-unfixed: true # skip vulnerabilities for which there is no fix | ||||||||||||||
| severity: 'CRITICAL,HIGH' | ||||||||||||||
| format: 'sarif' | ||||||||||||||
| limit-severities-for-sarif: true | ||||||||||||||
| output: ${{ env.sarif_file_name }} | ||||||||||||||
| exit-code: ${{ inputs.EXIT_CODE }} | ||||||||||||||
|
|
||||||||||||||
| - name: Upload Trivy scan results to GitHub Security tab | ||||||||||||||
| uses: github/codeql-action/upload-sarif@v3.25.12 | ||||||||||||||
| if: ${{ success() || steps.trivy.conclusion == 'failure' }} | ||||||||||||||
| with: | ||||||||||||||
| sarif_file: ${{ env.sarif_file_name }} | ||||||||||||||
| wait-for-processing: true | ||||||||||||||
|
|
||||||||||||||
| - name: Upload Trivy output | ||||||||||||||
| uses: actions/upload-artifact@v4 | ||||||||||||||
| if: ${{ success() || steps.trivy.conclusion == 'failure' }} | ||||||||||||||
| with: | ||||||||||||||
| name: ${{ env.sarif_file_name }} | ||||||||||||||
| path: ${{ env.sarif_file_name }} | ||||||||||||||
|
|
||||||||||||||
| outputs: | ||||||||||||||
| trivy_conclusion: ${{ steps.trivy.conclusion }} | ||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the core architectural change — the old single
ghcr-build-and-push-on-releasejob has been split into a 3-job pipeline that gates image publication on a Trivy vulnerability scan.graph LR A[ghcr-build-on-release] -->|tar artifact| B[trivy-scan-release] B -->|pass| C[ghcr-push-on-release] B -->|fail: CRITICAL/HIGH found| D[Build stops — image NOT pushed]One thing worth noting: the push job (
ghcr-push-on-release) rebuilds the image from source rather than loading the tar artifact. This is becausedocker/build-push-actionwithload: true(used in the build job) is incompatible withcache-to: type=registry— they require different buildx drivers. The rebuild should be near-instant thanks tocache-from, and this lets us keep populating the registry build cache.The tag computation moved from inline
if:conditionals on two separate build steps into a singleset-tagsstep that outputs the tag string, which the push job reads vianeeds.ghcr-build-on-release.outputs.image-tags.Note: This comment was drafted with AI assistance and reviewed by me for accuracy.