Scan Docker images #1199
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
| # Snyk scanning steps are marked continue-on-error because Snyk exits with a | |
| # non-zero code whenever it finds vulnerabilities, and there are often | |
| # vulnerabilities that have no possible remediation (e.g. glibc | |
| # vulnerabilities in the Debian base). We want to be *informed* about the | |
| # vulns via GitHub code scanning, but we cannot have them be blockers to | |
| # releasing images. A genuine scan failure leaves no SARIF file behind, which | |
| # fails the "Merge SARIF runs" step so breakage is still surfaced. | |
| # | |
| # Each image is uploaded under a stable per-image category so that GitHub can | |
| # track alerts across scans and automatically close alerts that no longer | |
| # appear in the image's latest scan. | |
| name: Scan Docker images | |
| on: | |
| workflow_dispatch: {} | |
| schedule: | |
| - cron: "0 0 * * *" | |
| permissions: | |
| contents: read # for checkout | |
| security-events: write # to upload SARIF results and dismiss stale alerts | |
| id-token: write # to fetch secrets from Pulumi ESC via OIDC | |
| env: | |
| DOCKER_ORG: pulumi | |
| DOCKER_USERNAME: pulumibot | |
| DISPATCH_REF: ${{ github.event.client_payload.ref }} | |
| ESC_ACTION_OIDC_AUTH: true | |
| ESC_ACTION_OIDC_ORGANIZATION: pulumi | |
| ESC_ACTION_OIDC_REQUESTED_TOKEN_TYPE: urn:pulumi:token-type:access_token:organization | |
| ESC_ACTION_ENVIRONMENT: imports/github-secrets | |
| ESC_ACTION_EXPORT_ENVIRONMENT_VARIABLES: false | |
| jobs: | |
| kitchen-sink: | |
| name: All SDKs images | |
| runs-on: ubuntu-latest | |
| strategy: | |
| # Try to complete the scan for all images, even if one fails. | |
| fail-fast: false | |
| matrix: | |
| suffix: ["", "-nonroot"] | |
| arch: ["amd64", "arm64"] | |
| steps: | |
| - name: Fetch secrets from ESC | |
| id: esc-secrets | |
| uses: pulumi/esc-action@3af4859af8a73a362fb599b944124097d4bb80c5 # v3 | |
| - uses: actions/checkout@master | |
| - name: Free Disk Space (Ubuntu) | |
| uses: jlumbroso/free-disk-space@main | |
| with: | |
| tool-cache: false | |
| - name: Login to Docker Hub | |
| uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3 | |
| with: | |
| username: ${{ env.DOCKER_USERNAME }} | |
| password: ${{ steps.esc-secrets.outputs.DOCKER_HUB_PASSWORD }} | |
| - name: Set version | |
| run: | | |
| [ -z "${{ env.DISPATCH_REF }}" ] && echo "PULUMI_VERSION=$(curl https://www.pulumi.com/latest-version)" >> $GITHUB_ENV || echo "PULUMI_VERSION=${{ env.DISPATCH_REF }}" >> $GITHUB_ENV | |
| - name: Snyk scan | |
| continue-on-error: true | |
| uses: snyk/actions/docker@master | |
| env: | |
| SNYK_TOKEN: ${{ steps.esc-secrets.outputs.SNYK_TOKEN }} | |
| with: | |
| image: ${{ env.DOCKER_ORG }}/pulumi:${{ env.PULUMI_VERSION }}${{ matrix.suffix }}-${{ matrix.arch }} | |
| args: --severity-threshold=high --file=docker/pulumi/Dockerfile | |
| - name: Merge SARIF runs | |
| run: python ./.github/scripts/merge-sarif.py | |
| - name: Upload result to GitHub Code Scanning | |
| uses: github/codeql-action/upload-sarif@bffd034ab1518ad839a542b8a7356e13a240e076 # v3 | |
| with: | |
| sarif_file: out.sarif | |
| category: pulumi${{ matrix.suffix }}-${{ matrix.arch }} | |
| provider-build-environment: | |
| name: Provider Build Environment | |
| runs-on: ubuntu-latest | |
| strategy: | |
| # Try to complete the scan for all images, even if one fails. | |
| fail-fast: false | |
| matrix: | |
| arch: ["amd64", "arm64"] | |
| steps: | |
| - name: Fetch secrets from ESC | |
| id: esc-secrets | |
| uses: pulumi/esc-action@3af4859af8a73a362fb599b944124097d4bb80c5 # v3 | |
| - uses: actions/checkout@master | |
| - name: Free Disk Space (Ubuntu) | |
| uses: jlumbroso/free-disk-space@main | |
| with: | |
| tool-cache: false | |
| - name: Login to Docker Hub | |
| uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3 | |
| with: | |
| username: ${{ env.DOCKER_USERNAME }} | |
| password: ${{ steps.esc-secrets.outputs.DOCKER_HUB_PASSWORD }} | |
| - name: Set version | |
| run: | | |
| [ -z "${{ env.DISPATCH_REF }}" ] && echo "PULUMI_VERSION=$(curl https://www.pulumi.com/latest-version)" >> $GITHUB_ENV || echo "PULUMI_VERSION=${{ env.DISPATCH_REF }}" >> $GITHUB_ENV | |
| - name: Snyk scan | |
| continue-on-error: true | |
| uses: snyk/actions/docker@master | |
| env: | |
| SNYK_TOKEN: ${{ steps.esc-secrets.outputs.SNYK_TOKEN }} | |
| with: | |
| image: ${{ env.DOCKER_ORG }}/pulumi-provider-build-environment:${{ env.PULUMI_VERSION }}-${{ matrix.arch }} | |
| args: --severity-threshold=high --file=docker/pulumi/Dockerfile | |
| - name: Merge SARIF runs | |
| run: python ./.github/scripts/merge-sarif.py | |
| - name: Upload result to GitHub Code Scanning | |
| uses: github/codeql-action/upload-sarif@bffd034ab1518ad839a542b8a7356e13a240e076 # v3 | |
| with: | |
| sarif_file: out.sarif | |
| category: pulumi-provider-build-environment-${{ matrix.arch }} | |
| base: | |
| name: Base image | |
| runs-on: ubuntu-latest | |
| strategy: | |
| # Try to complete the scan for all images, even if one fails. | |
| fail-fast: false | |
| matrix: | |
| os: ["debian", "ubi"] | |
| arch: ["arm64", "amd64"] | |
| steps: | |
| - name: Fetch secrets from ESC | |
| id: esc-secrets | |
| uses: pulumi/esc-action@3af4859af8a73a362fb599b944124097d4bb80c5 # v3 | |
| - uses: actions/checkout@master | |
| - name: Login to Docker Hub | |
| uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3 | |
| with: | |
| username: ${{ env.DOCKER_USERNAME }} | |
| password: ${{ steps.esc-secrets.outputs.DOCKER_HUB_PASSWORD }} | |
| - name: Set version | |
| run: | | |
| [ -z "${{ env.DISPATCH_REF }}" ] && echo "PULUMI_VERSION=$(curl https://www.pulumi.com/latest-version)" >> $GITHUB_ENV || echo "PULUMI_VERSION=${{ env.DISPATCH_REF }}" >> $GITHUB_ENV | |
| - name: Snyk scan | |
| continue-on-error: true | |
| uses: snyk/actions/docker@master | |
| env: | |
| SNYK_TOKEN: ${{ steps.esc-secrets.outputs.SNYK_TOKEN }} | |
| with: | |
| image: ${{ env.DOCKER_ORG }}/pulumi-base:${{ env.PULUMI_VERSION }}-${{ matrix.os }}-${{ matrix.arch }} | |
| args: --severity-threshold=high --file=docker/base/Dockerfile.${{ matrix.os }} --platform=linux/${{ matrix.arch }} | |
| - name: Merge SARIF runs | |
| run: python ./.github/scripts/merge-sarif.py | |
| - name: Upload result to GitHub Code Scanning | |
| uses: github/codeql-action/upload-sarif@bffd034ab1518ad839a542b8a7356e13a240e076 # v3 | |
| with: | |
| sarif_file: out.sarif | |
| category: pulumi-base-${{ matrix.os }}-${{ matrix.arch }} | |
| define-debian-matrix: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| matrix: ${{ steps.define-matrix.outputs.matrix }} | |
| steps: | |
| - uses: actions/checkout@master | |
| - name: Define Matrix | |
| id: define-matrix | |
| # To avoid pulling the snyk image too often due to a very large matrix, | |
| # we generate a matrix without architecure, and run the scan twice | |
| # in each job, once for amd64 and once for arm64. | |
| run: | | |
| echo matrix=$(python ./.github/scripts/matrix/gen-matrix.py --no-arch) >> "$GITHUB_OUTPUT" | |
| debian-sdk: | |
| name: Debian SDK images | |
| runs-on: ubuntu-latest | |
| needs: define-debian-matrix | |
| strategy: | |
| # Try to complete the scan for all images, even if one fails. | |
| fail-fast: false | |
| matrix: ${{ fromJSON(needs.define-debian-matrix.outputs.matrix) }} | |
| steps: | |
| - name: Fetch secrets from ESC | |
| id: esc-secrets | |
| uses: pulumi/esc-action@3af4859af8a73a362fb599b944124097d4bb80c5 # v3 | |
| - uses: actions/checkout@master | |
| - name: Login to Docker Hub | |
| uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3 | |
| with: | |
| username: ${{ env.DOCKER_USERNAME }} | |
| password: ${{ steps.esc-secrets.outputs.DOCKER_HUB_PASSWORD }} | |
| - name: Set version | |
| run: | | |
| [ -z "${{ env.DISPATCH_REF }}" ] && echo "PULUMI_VERSION=$(curl https://www.pulumi.com/latest-version)" >> $GITHUB_ENV || echo "PULUMI_VERSION=${{ env.DISPATCH_REF }}" >> $GITHUB_ENV | |
| - name: Snyk scan - amd64 | |
| continue-on-error: true | |
| uses: snyk/actions/docker@master | |
| env: | |
| SNYK_TOKEN: ${{ steps.esc-secrets.outputs.SNYK_TOKEN }} | |
| with: | |
| image: ${{ env.DOCKER_ORG }}/pulumi-${{ matrix.sdk }}${{ matrix.suffix }}:${{ env.PULUMI_VERSION }}-debian-amd64 | |
| args: --severity-threshold=high --file=docker/${{ matrix.sdk }}/Dockerfile.debian --platform=linux/amd64 | |
| - name: Merge SARIF runs - amd64 | |
| run: python ./.github/scripts/merge-sarif.py | |
| - name: Upload result to GitHub Code Scanning - amd64 | |
| uses: github/codeql-action/upload-sarif@bffd034ab1518ad839a542b8a7356e13a240e076 # v3 | |
| with: | |
| sarif_file: out.sarif | |
| category: pulumi-${{ matrix.sdk }}${{ matrix.suffix }}-debian-amd64 | |
| - name: Snyk scan - arm64 | |
| continue-on-error: true | |
| uses: snyk/actions/docker@master | |
| env: | |
| SNYK_TOKEN: ${{ steps.esc-secrets.outputs.SNYK_TOKEN }} | |
| with: | |
| image: ${{ env.DOCKER_ORG }}/pulumi-${{ matrix.sdk }}${{ matrix.suffix }}:${{ env.PULUMI_VERSION }}-debian-arm64 | |
| args: --severity-threshold=high --file=docker/${{ matrix.sdk }}/Dockerfile.debian --platform=linux/arm64 | |
| - name: Merge SARIF runs - arm64 | |
| run: python ./.github/scripts/merge-sarif.py | |
| - name: Upload result to GitHub Code Scanning - arm64 | |
| uses: github/codeql-action/upload-sarif@bffd034ab1518ad839a542b8a7356e13a240e076 # v3 | |
| with: | |
| sarif_file: out.sarif | |
| category: pulumi-${{ matrix.sdk }}${{ matrix.suffix }}-debian-arm64 | |
| ubi-sdk: | |
| name: UBI SDK images | |
| runs-on: ubuntu-latest | |
| strategy: | |
| # Try to complete the scan for all images, even if one fails. | |
| fail-fast: false | |
| matrix: | |
| sdk: ["nodejs", "python", "dotnet", "go"] | |
| steps: | |
| - name: Fetch secrets from ESC | |
| id: esc-secrets | |
| uses: pulumi/esc-action@3af4859af8a73a362fb599b944124097d4bb80c5 # v3 | |
| - uses: actions/checkout@master | |
| - name: Login to Docker Hub | |
| uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3 | |
| with: | |
| username: ${{ env.DOCKER_USERNAME }} | |
| password: ${{ steps.esc-secrets.outputs.DOCKER_HUB_PASSWORD }} | |
| - name: Set version | |
| run: | | |
| [ -z "${{ env.DISPATCH_REF }}" ] && echo "PULUMI_VERSION=$(curl https://www.pulumi.com/latest-version)" >> $GITHUB_ENV || echo "PULUMI_VERSION=${{ env.DISPATCH_REF }}" >> $GITHUB_ENV | |
| - name: Snyk scan | |
| continue-on-error: true | |
| uses: snyk/actions/docker@master | |
| env: | |
| SNYK_TOKEN: ${{ steps.esc-secrets.outputs.SNYK_TOKEN }} | |
| with: | |
| image: ${{ env.DOCKER_ORG }}/pulumi-${{ matrix.sdk }}:${{ env.PULUMI_VERSION }}-ubi | |
| args: --severity-threshold=high --file=docker/${{ matrix.sdk }}/Dockerfile.ubi --platform=linux/amd64 | |
| - name: Merge SARIF runs | |
| run: python ./.github/scripts/merge-sarif.py | |
| - name: Upload result to GitHub Code Scanning | |
| uses: github/codeql-action/upload-sarif@bffd034ab1518ad839a542b8a7356e13a240e076 # v3 | |
| with: | |
| sarif_file: out.sarif | |
| category: pulumi-${{ matrix.sdk }}-ubi | |
| cleanup-stale-alerts: | |
| name: Dismiss alerts from stale categories | |
| runs-on: ubuntu-latest | |
| needs: [kitchen-sink, provider-build-environment, base, debian-sdk, ubi-sdk] | |
| # Run even if some scan jobs failed: the script only dismisses alerts in | |
| # categories that are not part of the current scan matrix, so alerts of | |
| # images whose scan failed are left untouched. | |
| # | |
| # Only run on main: SARIF uploads are scoped to the ref, so a run from | |
| # another branch doesn't refresh the alerts on main, and the script would | |
| # see them all as stale and dismiss them. Dismissals are sticky, a | |
| # dismissed alert is not reopened when a later scan finds it again. | |
| if: always() && github.ref == 'refs/heads/main' | |
| steps: | |
| - uses: actions/checkout@master | |
| - name: Dismiss alerts in categories no longer scanned | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: python ./.github/scripts/dismiss-stale-alerts.py |