fleet/.github/workflows/trivy-scan.yml

134 lines
5.5 KiB
YAML

name: Trivy vulnerability scan
on:
push:
branches:
- main
paths:
- "**.tf"
pull_request:
paths:
- "**.tf"
workflow_dispatch:
schedule:
- cron: "0 4 * * *" # Nightly 4AM UTC
# This allows a subsequently queued workflow run to interrupt previous runs
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id}}
cancel-in-progress: true
defaults:
run:
# fail-fast using bash -eo pipefail. See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
shell: bash
env:
AWS_REGION: us-east-2
AWS_IAM_ROLE: arn:aws:iam::160035666661:role/github-actions-role
permissions:
contents: read
jobs:
discover:
# Only the nightly/manual runs scan extra branches; push/PR keep their
# single-ref behavior and skip this job.
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
outputs:
branches: ${{ steps.set.outputs.branches }}
steps:
- name: Determine branches to scan
id: set
env:
GH_TOKEN: ${{ github.token }}
run: |
# Resolve the most recent published (non-draft, non-prerelease) Fleet
# release tag, e.g. "fleet-v4.84.0", and strip the prefix so we end
# up with a bare semver like "4.84.0" for comparison.
latest=$(gh release view --repo "${{ github.repository }}" --json tagName -q .tagName)
latest_ver=${latest#fleet-v}
# List every branch on the repo and keep only those that strictly
# match the canonical RC naming pattern. The anchors filter out
# cherry-pick branches and "-suffix" variants (e.g.
# rc-minor-fleet-v4.65.0-cherry-helm), leaving just the real RCs.
# `|| true` keeps the step from failing when grep finds no matches.
candidates=$(gh api "repos/${{ github.repository }}/branches" --paginate --jq '.[].name' \
| grep -E '^rc-(minor|patch)-fleet-v[0-9]+\.[0-9]+\.[0-9]+$' || true)
# Keep only the RC branches whose version is strictly greater than
# the latest released version (i.e. an in-flight release). `sort -V`
# gives semver-aware ordering; if the branch's version sorts last
# and isn't equal to the released version, it's still active.
active=()
for b in $candidates; do
v=$(echo "$b" | sed -E 's/^rc-(minor|patch)-fleet-v//')
top=$(printf '%s\n%s\n' "$v" "$latest_ver" | sort -V | tail -n1)
if [ "$top" = "$v" ] && [ "$v" != "$latest_ver" ]; then
active+=("$b")
fi
done
# Emit a JSON array (e.g. ["main","rc-minor-fleet-v4.85.0"]) for
# the downstream matrix to consume via fromJSON.
branches=$(printf '%s\n' "main" "${active[@]}" | jq -Rnc '[inputs]')
echo "branches=$branches" >> "$GITHUB_OUTPUT"
echo "Will scan: $branches"
trivy:
needs: [discover]
# Run when discover succeeds (nightly/manual) or is skipped (push/PR).
if: always() && (needs.discover.result == 'success' || needs.discover.result == 'skipped')
permissions:
id-token: write # for aws-actions/configure-aws-credentials
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
name: Trivy sarif report
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# When discover is skipped, fall back to a single empty entry so we
# scan the triggering ref (push/PR default checkout behavior).
branch: ${{ fromJSON(needs.discover.outputs.branches || '[""]') }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0
with:
egress-policy: audit
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ matrix.branch || github.ref }}
- uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
with:
role-to-assume: ${{env.AWS_IAM_ROLE}}
aws-region: ${{ env.AWS_REGION }}
- name: Run Trivy vulnerability scanner in repo mode
uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # 0.35.0
env:
TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db
TRIVY_JAVA_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-java-db
with:
scan-type: "fs"
ignore-unfixed: false
format: "sarif"
output: "trivy-results.sarif"
severity: "CRITICAL,HIGH,MEDIUM,LOW"
trivyignores: "./security/code/.trivyignore"
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@8a470fddafa5cbb6266ee11b37ef4d8aae19c571 # v3.24.6
with:
sarif_file: "trivy-results.sarif"
# On nightly/manual runs the matrix scans multiple branches, so use a
# distinct category per branch to keep results separate. On push/PR
# there's only one matrix run, so leave category empty and let
# upload-sarif use its default — avoids slashes in github.ref_name
# (e.g. "123/merge" on pull_request) leaking into the category.
category: ${{ matrix.branch && format('trivy-{0}', matrix.branch) || '' }}