mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
134 lines
5.5 KiB
YAML
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) || '' }}
|