ci-container-security-scan #67
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
| # Copyright AGNTCY Contributors (https://github.com/agntcy) | |
| # SPDX-License-Identifier: Apache-2.0 | |
| --- | |
| name: ci-container-security-scan | |
| on: | |
| # Nightly scan on main branch only; manual dispatch allowed. | |
| schedule: | |
| - cron: '0 3 * * *' # Daily at 03:00 UTC (runs on default branch context: main) | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| actions: read | |
| jobs: | |
| trivy-scan: | |
| name: Trivy Image Scan (Pull from GHCR) | |
| permissions: | |
| contents: read | |
| security-events: write # for uploading SARIF | |
| issues: write # create issues for critical CVEs | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - image: slim-node | |
| repo: ghcr.io/${{ github.repository_owner }}/slim | |
| version: latest | |
| - image: slim-controller | |
| repo: ghcr.io/${{ github.repository_owner }}/slim/control-plane | |
| version: latest | |
| - image: spire-server | |
| repo: ghcr.io/spiffe/spire-server | |
| version: 1.14.5 | |
| - image: spire-agent | |
| repo: ghcr.io/spiffe/spire-agent | |
| version: 1.14.5 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| with: | |
| persist-credentials: false | |
| - name: Log in to GHCR | |
| uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.repository_owner }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Pull image (explicit version) | |
| env: | |
| IMAGE_REPO: ${{ matrix.repo }} | |
| IMAGE_VERSION: ${{ matrix.version }} | |
| run: | | |
| set -euo pipefail | |
| IMAGE_REF="${IMAGE_REPO}:${IMAGE_VERSION}" | |
| echo "Pulling $IMAGE_REF" | |
| docker pull "$IMAGE_REF" | |
| docker image inspect "$IMAGE_REF" >/dev/null 2>&1 | |
| - name: Install Trivy | |
| env: | |
| TRIVY_VERSION: "0.71.1" | |
| run: | | |
| curl -fsSL "https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/trivy_${TRIVY_VERSION}_Linux-64bit.deb" -o trivy.deb | |
| sudo dpkg -i trivy.deb | |
| rm trivy.deb | |
| - name: Run Trivy vulnerability scan (image) | |
| env: | |
| IMAGE_REPO: ${{ matrix.repo }} | |
| IMAGE_VERSION: ${{ matrix.version }} | |
| IMAGE_NAME: ${{ matrix.image }} | |
| run: | | |
| trivy image \ | |
| --format sarif \ | |
| --output "trivy-${IMAGE_NAME}.sarif" \ | |
| --vuln-type os,library \ | |
| --severity CRITICAL,HIGH,MEDIUM \ | |
| --ignore-unfixed \ | |
| "${IMAGE_REPO}:${IMAGE_VERSION}" | |
| - name: Export image metadata | |
| env: | |
| IMAGE_REPO: ${{ matrix.repo }} | |
| IMAGE_VERSION: ${{ matrix.version }} | |
| IMAGE_NAME: ${{ matrix.image }} | |
| run: echo "${IMAGE_REPO}:${IMAGE_VERSION}" > "trivy-${IMAGE_NAME}.meta" | |
| - name: Upload SARIF | |
| uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 | |
| with: | |
| sarif_file: trivy-${{ matrix.image }}.sarif | |
| # Distinguish reports per container image in Code Scanning UI | |
| category: trivy-${{ matrix.image }} | |
| - name: Upload report artifacts | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: trivy-report-${{ matrix.image }} | |
| path: | | |
| trivy-${{ matrix.image }}.sarif | |
| trivy-${{ matrix.image }}.meta | |
| retention-days: 7 | |
| summarize: | |
| name: Summarize Results | |
| permissions: | |
| contents: read | |
| issues: write # create issues for critical CVEs | |
| needs: [trivy-scan] | |
| runs-on: ubuntu-latest | |
| if: always() | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| with: | |
| persist-credentials: false | |
| - name: Download artifacts | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| pattern: trivy-report-* | |
| path: trivy-artifacts | |
| - name: Debug artifact contents | |
| run: | | |
| echo "Downloaded artifact directory tree:" >> "$GITHUB_STEP_SUMMARY" | |
| echo '```' >> "$GITHUB_STEP_SUMMARY" | |
| find trivy-artifacts -maxdepth 3 -type f -print >> "$GITHUB_STEP_SUMMARY" || true | |
| echo '```' >> "$GITHUB_STEP_SUMMARY" | |
| echo "" >> "$GITHUB_STEP_SUMMARY" | |
| - name: Generate summary | |
| run: | | |
| chmod +x .github/workflows/scripts/security/generate_trivy_summary.sh | |
| .github/workflows/scripts/security/generate_trivy_summary.sh | |
| - name: Fail if critical vulns found (optional gate) | |
| if: ${{ github.event_name != 'pull_request' }} | |
| run: | | |
| set -e | |
| found=$(grep -R "CRITICAL" -c trivy-artifacts || true) | |
| if [ "${found}" != "0" ]; then | |
| echo "Critical vulnerabilities detected. (Gate currently informational.)" >&2 | |
| fi | |
| - name: Create GitHub issues for critical CVEs | |
| if: ${{ github.event_name != 'pull_request' }} | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GITHUB_REPOSITORY: ${{ github.repository }} | |
| run: | | |
| set -euo pipefail | |
| echo "Installing dependencies for issue creation script"; | |
| npm init -y >/dev/null 2>&1 || true | |
| npm install @octokit/rest@21 glob >/dev/null 2>&1 | |
| node .github/workflows/scripts/security/create_critical_cve_issues.js |