Skip to content
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

ci: Trivy enhancements #4703

Merged
merged 7 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions .github/actions/trivy-scan-image/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# 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
.github*
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
if: success() || failure()
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
70 changes: 15 additions & 55 deletions .github/workflows/.reusable-docker-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand All @@ -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:') }}"
101 changes: 101 additions & 0 deletions .github/workflows/platform-docker-trivy-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
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: Scan image
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-tag: ${{ inputs.registry-url }}/flagsmith/${{ matrix.image-name }}:main
category: ${{ matrix.image-name }}
query: branch: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 }}
Loading