-
Notifications
You must be signed in to change notification settings - Fork 0
ci: harden release workflow — gate on vulnerabilities, enforce egress #5
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
base: update/upstream-sync
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| # Fieldnote-Echo/Kokoro-FastAPI — Hardened GHCR Release | ||
| # Replaces upstream's multi-arch bake workflow with a GPU-only, amd64-only | ||
| # build that includes supply-chain hardening (pinned actions, Sigstore | ||
| # attestation, Trivy scan, CycloneDX SBOM). | ||
| # build that includes supply-chain hardening (pinned actions, egress | ||
| # enforcement, Sigstore attestation, gating Trivy scan, attested SBOM). | ||
| # | ||
| # Incorporates from upstream's reworked release workflow: concurrency group, | ||
| # duplicate-release guard, ubuntu-24.04 runner, and the new multi-stage | ||
|
|
@@ -22,7 +22,7 @@ permissions: | |
| packages: write # GHCR push | ||
| id-token: write # Sigstore OIDC | ||
| security-events: write # SARIF upload | ||
| attestations: write # Build provenance | ||
| attestations: write # Build provenance + SBOM attestation | ||
|
|
||
| concurrency: | ||
| group: release-${{ github.ref_name }} | ||
|
|
@@ -33,16 +33,48 @@ jobs: | |
| runs-on: ubuntu-24.04 | ||
| env: | ||
| IMAGE: ghcr.io/fieldnote-echo/kokoro-fastapi-gpu | ||
| SCAN_TAG: ghcr.io/fieldnote-echo/kokoro-fastapi-gpu:ci-scan # local-only, never pushed | ||
| steps: | ||
| # ── Runner hardening ────────────────────────────────────────────── | ||
| # egress-policy: block — the runner may only reach the endpoints below. | ||
| # Derived from this workflow's known egress (GitHub/GHCR, PyPI, PyTorch, | ||
| # NVIDIA NGC, Hugging Face model download, Sigstore, Trivy DB). If a | ||
| # release fails with a "Blocked" egress line, add the reported host here; | ||
| # harden-runner fails closed and names the exact host. | ||
| - name: Harden runner | ||
| uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 | ||
| with: | ||
| egress-policy: audit | ||
| egress-policy: block | ||
| allowed-endpoints: > | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Even after the previously reported apt and Astral hosts are allowed, the image build still fails under this allow-list when Useful? React with 👍 / 👎. |
||
| github.com:443 | ||
| api.github.com:443 | ||
| objects.githubusercontent.com:443 | ||
| codeload.github.com:443 | ||
| release-assets.githubusercontent.com:443 | ||
| ghcr.io:443 | ||
| pkg-containers.githubusercontent.com:443 | ||
| actions-results-receiver-production.githubapp.com:443 | ||
| productionresultssa0.blob.core.windows.net:443 | ||
| pypi.org:443 | ||
| files.pythonhosted.org:443 | ||
| download.pytorch.org:443 | ||
| nvcr.io:443 | ||
| huggingface.co:443 | ||
| cdn-lfs.huggingface.co:443 | ||
| cdn-lfs-us-1.hf.co:443 | ||
| fulcio.sigstore.dev:443 | ||
| rekor.sigstore.dev:443 | ||
| tuf-repo-cdn.sigstore.dev:443 | ||
| mirror.gcr.io:443 | ||
| registry-1.docker.io:443 | ||
| auth.docker.io:443 | ||
| production.cloudflare.docker.com:443 | ||
|
Comment on lines
+47
to
+71
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1. Egress block breaks build The release workflow enables egress-policy: block but the allow-list omits endpoints required by docker/gpu/Dockerfile.optimized (Ubuntu APT repositories and astral.sh), so the Docker build will be network-blocked and the job will fail before Trivy gating/push when layers aren’t already satisfied by cache. Agent Prompt
|
||
|
|
||
| # ── Checkout ────────────────────────────────────────────────────── | ||
| - name: Checkout | ||
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | ||
| with: | ||
| persist-credentials: false # don't leave the token in .git/config for later steps | ||
|
|
||
| # ── Guard: don't re-publish an existing release ─────────────────── | ||
| - name: Check release does not exist | ||
|
|
@@ -84,10 +116,60 @@ jobs: | |
| type=semver,pattern={{major}}.{{minor}} | ||
| type=sha,prefix= | ||
|
|
||
| # ── Build & push ────────────────────────────────────────────────── | ||
| # ── Build for scanning (load locally, DO NOT push yet) ──────────── | ||
| # CUDA base images are pinned by digest, mirroring docker-bake.hcl's | ||
| # gpu-amd64 target (CUDA 12.6.3). Keep these in sync with the bake file; | ||
| # refresh with: docker buildx imagetools inspect nvcr.io/nvidia/cuda:<tag> | ||
| - name: Build image (load for scan) | ||
| id: build_scan | ||
| uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 | ||
| with: | ||
| context: . | ||
| file: docker/gpu/Dockerfile.optimized | ||
| platforms: linux/amd64 | ||
| load: true | ||
| push: false | ||
| build-args: | | ||
| CUDA_VERSION=12.6.3 | ||
| CUDA_BUILDER_IMAGE=nvcr.io/nvidia/cuda:12.6.3-cudnn-devel-ubuntu24.04@sha256:50efab398f76258daa91ceebb33b6467e40217c67ea44fb5a2cebc6be7d9cce3 | ||
| CUDA_RUNTIME_IMAGE=nvcr.io/nvidia/cuda:12.6.3-cudnn-runtime-ubuntu24.04@sha256:8aef630a54bc5c5146ae5ce68e6af5caa3df0fb690bb91544175c91f307e4356 | ||
| tags: ${{ env.SCAN_TAG }} | ||
| cache-from: type=gha | ||
| cache-to: type=gha,mode=max | ||
|
|
||
| # ── Trivy: GATE the release (fail on fixable CRITICAL) ──────────── | ||
| # Runs BEFORE push so a vulnerable image is never published. ignore-unfixed | ||
| # avoids blocking on CVEs in the CUDA/OS base that have no available fix; | ||
| # gate on CRITICAL only (HIGH is reported below but non-blocking, since | ||
| # CUDA base layers routinely carry unactionable HIGH advisories). | ||
| - name: Trivy scan (gate) | ||
| uses: aquasecurity/trivy-action@c1824fd6edce30d7ab345a9989de00bbd46ef284 # 0.34.0 | ||
| with: | ||
| image-ref: ${{ env.SCAN_TAG }} | ||
| format: table | ||
| severity: CRITICAL | ||
| ignore-unfixed: true | ||
| exit-code: "1" | ||
|
|
||
| # ── Trivy: full report to the Security tab (non-blocking) ───────── | ||
| - name: Trivy scan (SARIF report) | ||
| if: always() && steps.build_scan.outcome == 'success' | ||
|
Comment on lines
+155
to
+156
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When either this second Trivy invocation or the following SARIF upload fails because of a transient tool, database, or code-scanning ingestion error, the step still marks the job failed; the later Useful? React with 👍 / 👎. |
||
| uses: aquasecurity/trivy-action@c1824fd6edce30d7ab345a9989de00bbd46ef284 # 0.34.0 | ||
| with: | ||
| image-ref: ${{ env.SCAN_TAG }} | ||
| format: sarif | ||
| output: trivy-results.sarif | ||
| severity: CRITICAL,HIGH | ||
|
|
||
| - name: Upload Trivy SARIF | ||
| if: always() && hashFiles('trivy-results.sarif') != '' | ||
| uses: github/codeql-action/upload-sarif@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 | ||
| with: | ||
| sarif_file: trivy-results.sarif | ||
|
|
||
| # ── Push (only reached if the gate scan passed) ─────────────────── | ||
| # Reuses the layers built above via the GHA cache, so this is a fast | ||
| # cache hit rather than a second full build. | ||
| - name: Build and push | ||
| id: build | ||
| uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 | ||
|
|
@@ -113,20 +195,6 @@ jobs: | |
| subject-digest: ${{ steps.build.outputs.digest }} | ||
| push-to-registry: true | ||
|
|
||
| # ── Trivy container scan ────────────────────────────────────────── | ||
| - name: Trivy vulnerability scan | ||
| uses: aquasecurity/trivy-action@c1824fd6edce30d7ab345a9989de00bbd46ef284 # 0.34.0 | ||
| with: | ||
| image-ref: ${{ env.IMAGE }}@${{ steps.build.outputs.digest }} | ||
| format: sarif | ||
| output: trivy-results.sarif | ||
| severity: CRITICAL,HIGH | ||
|
|
||
| - name: Upload Trivy SARIF | ||
| uses: github/codeql-action/upload-sarif@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 | ||
| with: | ||
| sarif_file: trivy-results.sarif | ||
|
|
||
| # ── CycloneDX SBOM ─────────────────────────────────────────────── | ||
| - name: Generate SBOM | ||
| uses: anchore/sbom-action@28d71544de8eaf1b958d335707167c5f783590ad # v0.22.2 | ||
|
|
@@ -135,6 +203,15 @@ jobs: | |
| format: cyclonedx-json | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Useful? React with 👍 / 👎. |
||
| output-file: sbom.cdx.json | ||
|
|
||
| # ── Attest the SBOM to the registry (verifiable, like provenance) ── | ||
| - name: Attest SBOM | ||
| uses: actions/attest-sbom@4651f806c01d8637787e274ac3bdf724ef169f34 # v3.0.0 | ||
| with: | ||
| subject-name: ${{ env.IMAGE }} | ||
| subject-digest: ${{ steps.build.outputs.digest }} | ||
| sbom-path: sbom.cdx.json | ||
| push-to-registry: true | ||
|
|
||
| # ── GitHub Release ──────────────────────────────────────────────── | ||
| - name: Create GitHub Release | ||
| if: startsWith(github.ref, 'refs/tags/') | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When this workflow runs the Buildx steps under
egress-policy: block, the Dockerfile still performs outboundapt-get updateandcurl https://astral.sh/uv/install.shduring the image build (docker/gpu/Dockerfile.optimizedlines 15-18 and 45-47). This allow-list does not include the Ubuntu/NVIDIA apt hosts orastral.sh, so those deterministic build-time requests are denied before the Trivy gate or push step and the release job cannot publish an image.Useful? React with 👍 / 👎.