Homework — Security Scanning & Image Signing
Lesson 05 · Cloud Infrastructure & DevOps · 3 tasks
Task 1 — Add a .trivyignore for an unavoidable CVE
Imagine python:3.11-slim ships with a CVE that has no upstream fix yet. Rather than blocking the entire team from merging, you want to acknowledge the CVE and suppress its build failure while keeping it visible in the log.
Create a .trivyignore file in the repository root containing a single CVE ID (use CVE-2024-12345 as a placeholder if no real CVE presents itself in your local scan). Commit it.
# .trivyignore
# CVE in libc6 — no fix available upstream as of 2024-12
CVE-2024-12345
To tell Trivy to use this file, pass the path in the workflow step:
- name: Trivy scan
uses: aquasecurity/trivy-action@0.24.0
with:
image-ref: ${{ matrix.service }}:ci-${{ github.sha }}
severity: HIGH,CRITICAL
exit-code: 1
ignore-unfixed: true
trivyignores: .trivyignore
Self-check: Trivy still reports the CVE in its output log, but the job no longer fails because of it. All other HIGH/CRITICAL findings (if any) still cause a failure.
Task 2 — Sign on tag pushes as well as main
The current security.yml only triggers on push: branches: [main]. Modify it so it also triggers on semver tag pushes (v*), and use the git tag as the image tag so the published image is labelled v1.2.3 instead of just the SHA.
Hints:
- Add
tags: ['v*']under thepush:trigger. - The image tag should be
ghcr.io/${{ github.repository }}/${{ matrix.service }}:${{ github.ref_name }}for the human-readable version, in addition to the SHA tag.
Self-check: Run:
git tag v0.1.0
git push --tags
The Security & Sign workflow should run. After it completes, navigate to the Packages tab. The image should appear tagged v0.1.0 and be signed (verifiable with cosign verify).
Task 3 — Add a signature verification job to security.yml
Signing is only useful if someone verifies. Add a verify job to security.yml that runs after the sign job completes, pulls each signed image, and runs cosign verify. If verification fails, the workflow fails — a corrupted or unsigned image will not silently pass.
The verify job should:
- Declare
needs: [sign] - Use the same matrix (
service: [api, worker]) - Install cosign (
sigstore/cosign-installer@v3) - Run
cosign verifywith--certificate-identity-regexppinned to your repository and--certificate-oidc-issuerset to GitHub’s OIDC endpoint
Self-check: The verify job turns green after a successful signing run. To test the failure path: push an unsigned image to the same tag in GHCR (manually via docker push with a local build), then trigger the workflow and confirm the verify job fails.