From ddb192543e76d2d0e1ca9f0eb77000c220ad2f0c Mon Sep 17 00:00:00 2001 From: Kim Gustyr Date: Tue, 8 Oct 2024 15:17:39 +0100 Subject: [PATCH 1/7] ci: Trivy enhancements - Don't pull Trivy databases for PR worklow - Add Trivy scan cron workflow --- .github/actions/trivy-scan-image/action.yml | 74 +++++++++++++ .github/workflows/.reusable-docker-build.yml | 70 +++--------- .../workflows/platform-docker-trivy-scan.yml | 102 ++++++++++++++++++ trivy.yaml | 2 +- 4 files changed, 192 insertions(+), 56 deletions(-) create mode 100644 .github/actions/trivy-scan-image/action.yml create mode 100644 .github/workflows/platform-docker-trivy-scan.yml diff --git a/.github/actions/trivy-scan-image/action.yml b/.github/actions/trivy-scan-image/action.yml new file mode 100644 index 000000000000..65514a1af98a --- /dev/null +++ b/.github/actions/trivy-scan-image/action.yml @@ -0,0 +1,74 @@ +# Required permissions: +# contents: read +# security-events: write + +name: Run Trivy vulnerability scanner +description: Run Trivy vulnerability scanner on an image and upload the results + +inputs: + image-tag: + description: Full image ref (e.g. `ghcr.io/flagsmith/flagsmith:main`). + required: true + category: + description: CodeQL category (usually image name, e.g. `flagsmith-api`). + required: true + query: + description: CodeQL query (used for report URLs). + required: false + trivy-username: + description: TRIVY_USERNAME value. + required: false + trivy-password: + description: TRIVY_PASSWORD value. + required: false + trivy-db-repository: + description: TRIVY_DB_REPOSITORY value. + required: false + trivy-java-db-repository: + description: TRIVY_JAVA_DB_REPOSITORY value. + required: false + +outputs: + scan-results-url: + description: URL to scan results in Github Security tab + value: ${{ steps.scan-results-url.outputs.scan-results-url }} + scan-outcome: + description: Scan outcome + value: ${{ steps.trivy.outcome }} + +runs: + using: composite + + steps: + - name: Checkout trivy.yaml + uses: actions/checkout@v4 + with: + sparse-checkout: trivy.yaml + sparse-checkout-cone-mode: false + + - name: Run Trivy on ${{ inputs.image-tag }} + id: trivy + uses: aquasecurity/trivy-action@master + with: + image-ref: ${{ inputs.image-tag }} + format: sarif + output: trivy-results.sarif + env: + TRIVY_USERNAME: ${{ inputs.trivy-username }} + TRIVY_PASSWORD: ${{ inputs.trivy-password }} + TRIVY_DB_REPOSITORY: ${{ inputs.trivy-db-repository }} + TRIVY_JAVA_DB_REPOSITORY: ${{ inputs.trivy-java-db-repository }} + + - name: Upload Trivy scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v3 + if: success() || failure() + with: + category: ${{ inputs.category }} + sarif_file: trivy-results.sarif + + - name: Render scan results URL + id: scan-results-url + run: > + echo scan-results-url=${{ format('{0}/{1}/security/code-scanning?query=is:open+tool:Trivy+{2}', + github.server_url, github.repository, inputs.query }} >> $GITHUB_OUTPUT + shell: bash diff --git a/.github/workflows/.reusable-docker-build.yml b/.github/workflows/.reusable-docker-build.yml index b8dfd4b3d0c3..558afee50bd6 100644 --- a/.github/workflows/.reusable-docker-build.yml +++ b/.github/workflows/.reusable-docker-build.yml @@ -50,24 +50,14 @@ on: description: Whether to update the build status in a PR comment required: false default: false - trivy-db-repository-source: - type: string - description: Souce repository to pull Trivy database from - required: false - default: ghcr.io/aquasecurity/trivy-db:latest - trivy-java-db-repository-source: - type: string - description: Source repository to pull Trivy Java database from - required: false - default: ghcr.io/aquasecurity/trivy-java-db:1 trivy-db-repository: type: string - description: Destination repository to store Trivy database in + description: Trivy Database OCI specifier required: false default: ghcr.io/flagsmith/trivy-db:latest trivy-java-db-repository: type: string - description: Destination repository to store Trivy Java database in + description: Trivy Java Database OCI specifier default: ghcr.io/flagsmith/trivy-java-db:latest outputs: image: @@ -156,51 +146,20 @@ jobs: build-status: 'Finished :white_check_mark:' security-report-status: 'Skipped' - - uses: oras-project/setup-oras@v1 - - - name: Pull and republish Trivy databases - uses: nick-fields/retry@v3 - with: - shell: bash - command: | - oras pull --no-tty ${{ inputs.trivy-db-repository-source }} - oras pull --no-tty ${{ inputs.trivy-java-db-repository-source }} - oras push ${{ inputs.trivy-db-repository }} db.tar.gz:$MIME_TYPE+gzip --artifact-type $MIME_TYPE+json - oras push ${{ inputs.trivy-java-db-repository }} javadb.tar.gz:$MIME_TYPE+gzip --artifact-type $MIME_TYPE+json - max_attempts: 5 - retry_on: error - timeout_minutes: 20 - env: - MIME_TYPE: application/vnd.aquasec.trivy.db.layer.v1.tar - - - name: Run Trivy vulnerability scanner + - name: Scan ${{ steps.image-tag.outputs.image-tag }} image id: trivy - if: inputs.scan - uses: aquasecurity/trivy-action@master - with: - image-ref: ${{ steps.image-tag.outputs.image-tag }} - format: sarif - output: trivy-results.sarif - env: - TRIVY_USERNAME: ${{ inputs.ephemeral && 'x-token' || github.actor }} - TRIVY_PASSWORD: ${{ inputs.ephemeral && steps.depot-token.outputs.depot-token || secrets.GITHUB_TOKEN }} - TRIVY_DB_REPOSITORY: ${{ inputs.trivy-db-repository }} - TRIVY_JAVA_DB_REPOSITORY: ${{ inputs.trivy-java-db-repository }} - - - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@v2 - if: inputs.scan && (success() || failure()) + uses: ./.github/actions/trivy-scan-image with: + image-tag: ${{ steps.image-tag.outputs.image-tag }} category: ${{ inputs.image-name }} - sarif_file: trivy-results.sarif - - - name: Render scan results URL - id: scan-results-url - if: inputs.scan - run: > - echo scan-results-url=${{ format('{0}/{1}/security/code-scanning?query=pr%3A{2}+path%3Aflagsmith%2F{3}', - github.server_url, github.repository, github.event.pull_request.number, inputs.image-name) }} >> - $GITHUB_OUTPUT + # `query` value contained path:{image_name} before but not all Trivy findings + # conform to that. There's no category filter at the moment; for the time being, + # produce a shared report URL for all images. + query: ${{ format('pr:{0}', github.event.pull_request.number) }} + trivy-username: ${{ inputs.ephemeral && 'x-token' || github.actor }} + trivy-password: ${{ inputs.ephemeral && steps.depot-token.outputs.depot-token || secrets.GITHUB_TOKEN }} + trivy-db-repository: ${{ inputs.trivy-db-repository }} + trivy-java-db-repository: ${{ inputs.trivy-java-db-repository }} - name: Report scan results URL uses: ./.github/actions/docker-build-report-to-pr @@ -209,4 +168,5 @@ jobs: image-tag: ${{ steps.image-tag.outputs.image-tag }} build-status: 'Finished :white_check_mark:' security-report-status: - "${{ format('[Results]({0}) :white_check_mark:', steps.scan-results-url.outputs.scan-results-url) }}" + "${{ format('[Results]({0}) {1}', steps.trivy.outputs.scan-results-url, steps.trivy.outputs.scan-outcome == + 'success' && ':white_check_mark:' || ':heavy_exclamation_mark:') }}" diff --git a/.github/workflows/platform-docker-trivy-scan.yml b/.github/workflows/platform-docker-trivy-scan.yml new file mode 100644 index 000000000000..afde53db8c35 --- /dev/null +++ b/.github/workflows/platform-docker-trivy-scan.yml @@ -0,0 +1,102 @@ +name: Update Trivy Database and Scan + +on: + workflow_dispatch: + inputs: + registry-url: + type: string + description: Github Container Registry base URL + required: false + default: ghcr.io + trivy-db-repository-source: + type: string + description: Souce repository to pull Trivy database from + required: false + default: ghcr.io/aquasecurity/trivy-db:latest + trivy-java-db-repository-source: + type: string + description: Source repository to pull Trivy Java database from + required: false + default: ghcr.io/aquasecurity/trivy-java-db:1 + trivy-db-repository: + type: string + description: Destination repository to store Trivy database in + required: false + default: ghcr.io/flagsmith/trivy-db:latest + trivy-java-db-repository: + type: string + description: Destination repository to store Trivy Java database in + default: ghcr.io/flagsmith/trivy-java-db:latest + + schedule: + - cron: 11 */3 * * * # Runs at 11 minutes past the hour, every 3 hours + +# Inputs don't work for cron runs, define defaults as env +env: + TRIVY_DB_REPOSITORY_SOURCE: + ${{ github.event.inputs.trivy-db-repository-source || 'ghcr.io/aquasecurity/trivy-db:latest' }} + TRIVY_JAVA_DB_REPOSITORY_SOURCE: + ${{ github.event.inputs.trivy-java-db-repository-source || 'ghcr.io/aquasecurity/trivy-java-db:1' }} + TRIVY_DB_REPOSITORY: ${{ github.event.inputs.trivy-db-repository || 'ghcr.io/flagsmith/trivy-db:latest' }} + TRIVY_JAVA_DB_REPOSITORY: + ${{ github.event.inputs.trivy-java-db-repository || 'ghcr.io/aquasecurity/trivy-java-db:latest' }} + +jobs: + pull-trivy-db: + name: Pull and republish Trivy databases + runs-on: ubuntu-latest + + permissions: + packages: write + + steps: + - name: Prepare oras CLI + uses: oras-project/setup-oras@v1 + + - name: Pull and republish Trivy databases + uses: nick-fields/retry@v3 + with: + shell: bash + command: | + oras pull --no-tty $TRIVY_DB_REPOSITORY_SOURCE + oras pull --no-tty $TRIVY_JAVA_DB_REPOSITORY_SOURCE + oras push $TRIVY_DB_REPOSITORY db.tar.gz:$MIME_TYPE+gzip --artifact-type $MIME_TYPE+json + oras push $TRIVY_JAVA_DB_REPOSITORY javadb.tar.gz:$MIME_TYPE+gzip --artifact-type $MIME_TYPE+json + max_attempts: 5 + retry_on: error + timeout_minutes: 20 + env: + MIME_TYPE: application/vnd.aquasec.trivy.db.layer.v1.tar + + scan-images: + name: Pull and republish Trivy databases + runs-on: ubuntu-latest + needs: pull-trivy-db + + permissions: + contents: read + security-events: write + + strategy: + max-parallel: 5 + matrix: + image-name: + - flagsmith + - flagsmith-api + - flagsmith-frontend + - flagsmith-private-cloud + - flagsmith-private-cloud-api + + steps: + - name: Scan ${{ matrix.image-name }}:main image + id: trivy + uses: ./.github/actions/trivy-scan-image + with: + image-name: ${{ matrix.image-name }} + image-tag: main + query: branch:main + image-ref: ${{ inputs.registry-url }}/flagsmith/${{ matrix.image-name }}:main + trivy-username: ${{ github.actor }} + trivy-password: ${{ secrets.GITHUB_TOKEN }} + trivy-db-repository: ${{ env.TRIVY_DB_REPOSITORY }} + trivy-java-db-repository: ${{ env.TRIVY_JAVA_DB_REPOSITORY }} diff --git a/trivy.yaml b/trivy.yaml index 3d69c3ef41b5..9265e5ba43f9 100644 --- a/trivy.yaml +++ b/trivy.yaml @@ -1,4 +1,4 @@ format: json -exit-code: 0 +exit-code: 1 severity: CRITICAL,HIGH vuln-type: os,library From 5338aa5fe1372654a476c273a96411f3b08b16c2 Mon Sep 17 00:00:00 2001 From: Kim Gustyr Date: Tue, 8 Oct 2024 15:21:57 +0100 Subject: [PATCH 2/7] fix expression --- .github/actions/trivy-scan-image/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/trivy-scan-image/action.yml b/.github/actions/trivy-scan-image/action.yml index 65514a1af98a..2b8a58ceafe1 100644 --- a/.github/actions/trivy-scan-image/action.yml +++ b/.github/actions/trivy-scan-image/action.yml @@ -70,5 +70,5 @@ runs: id: scan-results-url run: > echo scan-results-url=${{ format('{0}/{1}/security/code-scanning?query=is:open+tool:Trivy+{2}', - github.server_url, github.repository, inputs.query }} >> $GITHUB_OUTPUT + github.server_url, github.repository, inputs.query) }} >> $GITHUB_OUTPUT shell: bash From bbc355378ef84dd153e6ef8bec8bd514d43f2e0e Mon Sep 17 00:00:00 2001 From: Kim Gustyr Date: Tue, 8 Oct 2024 15:26:53 +0100 Subject: [PATCH 3/7] add github to sparse-checkout --- .github/actions/trivy-scan-image/action.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/actions/trivy-scan-image/action.yml b/.github/actions/trivy-scan-image/action.yml index 2b8a58ceafe1..2eb02c2acfa1 100644 --- a/.github/actions/trivy-scan-image/action.yml +++ b/.github/actions/trivy-scan-image/action.yml @@ -43,7 +43,9 @@ runs: - name: Checkout trivy.yaml uses: actions/checkout@v4 with: - sparse-checkout: trivy.yaml + sparse-checkout: | + trivy.yaml + .github* sparse-checkout-cone-mode: false - name: Run Trivy on ${{ inputs.image-tag }} From 75f7529cf33878cd1e8950c40d9d732b078d0604 Mon Sep 17 00:00:00 2001 From: Kim Gustyr Date: Tue, 8 Oct 2024 15:33:43 +0100 Subject: [PATCH 4/7] rescue action on red scan --- .github/actions/trivy-scan-image/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/trivy-scan-image/action.yml b/.github/actions/trivy-scan-image/action.yml index 2eb02c2acfa1..81c7fae5ca55 100644 --- a/.github/actions/trivy-scan-image/action.yml +++ b/.github/actions/trivy-scan-image/action.yml @@ -69,6 +69,7 @@ runs: sarif_file: trivy-results.sarif - name: Render scan results URL + if: success() || failure() id: scan-results-url run: > echo scan-results-url=${{ format('{0}/{1}/security/code-scanning?query=is:open+tool:Trivy+{2}', From 0836de741ad3f8b6752cfb95051fd0a7e7a749a7 Mon Sep 17 00:00:00 2001 From: Kim Gustyr Date: Tue, 8 Oct 2024 15:39:57 +0100 Subject: [PATCH 5/7] avoid failing trivy action --- trivy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trivy.yaml b/trivy.yaml index 9265e5ba43f9..3d69c3ef41b5 100644 --- a/trivy.yaml +++ b/trivy.yaml @@ -1,4 +1,4 @@ format: json -exit-code: 1 +exit-code: 0 severity: CRITICAL,HIGH vuln-type: os,library From ae1f9a02d5d9ad2c393338e5d072e2918aa20040 Mon Sep 17 00:00:00 2001 From: Kim Gustyr Date: Tue, 8 Oct 2024 15:45:39 +0100 Subject: [PATCH 6/7] fix job name --- .github/workflows/platform-docker-trivy-scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/platform-docker-trivy-scan.yml b/.github/workflows/platform-docker-trivy-scan.yml index afde53db8c35..e48f6d8f6825 100644 --- a/.github/workflows/platform-docker-trivy-scan.yml +++ b/.github/workflows/platform-docker-trivy-scan.yml @@ -69,7 +69,7 @@ jobs: MIME_TYPE: application/vnd.aquasec.trivy.db.layer.v1.tar scan-images: - name: Pull and republish Trivy databases + name: Scan image runs-on: ubuntu-latest needs: pull-trivy-db From e10b52d5214f3246a47f539ab3a9de330872032e Mon Sep 17 00:00:00 2001 From: Kim Gustyr Date: Tue, 8 Oct 2024 15:47:38 +0100 Subject: [PATCH 7/7] fix input values --- .github/workflows/platform-docker-trivy-scan.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/platform-docker-trivy-scan.yml b/.github/workflows/platform-docker-trivy-scan.yml index e48f6d8f6825..a7ea47d796c7 100644 --- a/.github/workflows/platform-docker-trivy-scan.yml +++ b/.github/workflows/platform-docker-trivy-scan.yml @@ -92,10 +92,9 @@ jobs: id: trivy uses: ./.github/actions/trivy-scan-image with: - image-name: ${{ matrix.image-name }} - image-tag: main + image-tag: ${{ inputs.registry-url }}/flagsmith/${{ matrix.image-name }}:main + category: ${{ matrix.image-name }} query: branch:main - image-ref: ${{ inputs.registry-url }}/flagsmith/${{ matrix.image-name }}:main trivy-username: ${{ github.actor }} trivy-password: ${{ secrets.GITHUB_TOKEN }} trivy-db-repository: ${{ env.TRIVY_DB_REPOSITORY }}