2. Imagem e Cadeia de Suprimentos
O seu código é uma parte pequena do que roda em produção: a imagem também contém uma distribuição Linux, um JRE e cerca de cem bibliotecas. A segurança da cadeia de suprimentos faz três perguntas sobre toda imagem antes que ela rode: o que há dentro dela? (um SBOM), ela contém vulnerabilidades conhecidas? (um scan) e ela foi mesmo construída pelo nosso pipeline, a partir deste commit? (proveniência). O job image do ci.yaml responde às três, nesta ordem:
flowchart LR
build["build (carregada localmente)"] --> sarif["relatório do Trivy -> aba Security"]
sarif --> gate{"portão do Trivy: CRITICAL com correção?"}
gate -->|sim| fail[job falha, nada é publicado]
gate -->|não| sbom["SBOM (Syft, SPDX)"]
sbom --> push["push para ghcr.io (sha-<commit>, main)"]
push --> prov["atesta a proveniência (Sigstore)"]
prov --> attsbom["atesta o SBOM"] O job está em .github/workflows/ci.yaml (mostrado completo no passo 1); esta página explica os seus steps.
Build, depois scan, depois push
| Step | Action | Observações |
|---|---|---|
| nome da imagem | shell | ghcr.io/<owner>/boxoffice-catalog, em minúsculas (o GHCR rejeita maiúsculas; ${VAR,,} converte para minúsculas no Bash) |
docker/setup-buildx-action (v4.4.1), docker/login-action (v4.6.0) | BuildKit, e um login no registry do GitHub com o próprio GITHUB_TOKEN do job (packages: write) | |
docker/metadata-action (v6.2.0) | tags sha-<sha completo do commit> (imutável, o que vai para o deploy) e main (móvel, para humanos) | |
build com load: true | docker/build-push-action (v7.4.0) | a imagem vai para o Docker do runner, ainda não para o registry; camadas em cache no cache do GitHub (type=gha) |
| relatório do Trivy | aquasecurity/trivy-action | SARIF enviado para Security → Code scanning, nunca falha |
| portão do Trivy | aquasecurity/trivy-action | falha numa vulnerabilidade CRITICAL que tem correção (ignore-unfixed): algo sobre o que você pode agir agora |
| SBOM | anchore/sbom-action (Syft) | sbom.spdx.json: todo pacote e versão na imagem |
| push | docker/build-push-action (v7.4.0) | as mesmas camadas (cache hit), agora enviadas com as tags |
| atestações | actions/attest-build-provenance (v4.2.2), actions/attest-sbom (v4.1.0) | declarações assinadas ligadas ao digest da imagem, guardadas junto dela no GHCR |
Escanear antes do push significa que uma imagem vulnerável nunca é publicada. O portão é estreito de propósito: falhar em todo HIGH sem correção bloquearia todo o trabalho por problemas que ninguém consegue resolver hoje, e times aprendem a ignorar um portão que está sempre vermelho. O relatório completo continua listando essas vulnerabilidades.
Fixe actions de terceiros num commit
Uma action é código que roda com o seu token. Uma tag como @v0.36.0 pode ser movida por quem controla o repositório da action — o sequestro de tags já foi usado em ataques reais à cadeia de suprimentos contra pipelines de CI. Toda action em ci.yaml e deploy.yaml — incluindo as do GitHub e as do Docker — está fixada num SHA completo de commit, com a versão num comentário (actions/checkout@3d3c42e… # v7.0.1). O Dependabot (abaixo) propõe as atualizações como pull requests, e o lab 13 confere as fixações com o zizmor.
Mantenha as dependências em dia
# Lab 11: keep dependencies and pinned actions up to date with reviewed pull requests.
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
- package-ecosystem: maven
directories: ["/services/*"]
schedule:
interval: weekly
- package-ecosystem: docker
directories: ["/services/*"]
schedule:
interval: weekly
O Dependabot abre um pull request quando uma action fixada, uma dependência Maven ou uma imagem base tem uma nova versão; o seu CI então testa a atualização como qualquer outra mudança.
Veja funcionar
Depois de um push para a main, abra Actions → CI → image (catalog). Você deve ver todos os steps verdes e, no fim, dois links de atestação. Depois:
- Packages (a página do seu perfil ou do repositório):
boxoffice-catalogcom as tagsmainesha-…. Pacotes novos são privados; para o cluster local do passo 4, torne-o público (pacote → Package settings → Change visibility) ou crie um pull secret (o passo 4 mostra como). - Security → Code scanning: os achados do Trivy, um alerta por vulnerabilidade.
-
Verifique a proveniência a partir da sua máquina com a GitHub CLI:
Você deve ver
✓ Verification succeeded!e o workflow, o commit e o runner que construíram a imagem. Qualquer mudança na imagem — mesmo de um byte — muda o seu digest, e a verificação falha.
O que o SBOM lhe dá no dia em que uma nova vulnerabilidade é publicada?
A lista de toda imagem que contém a biblioteca e a versão afetadas — sem refazer o build nem escanear nada de novo. No dia em que o Log4Shell foi divulgado, times com SBOMs responderam "quais dos nossos serviços são afetados?" em minutos; os outros levaram dias.