O vocabulário à volta dos artefactos de build cresceu mais depressa do que a maioria das equipas consegue acompanhar. SBOMs, attestations, provenance, assinaturas, níveis SLSA. Soam a um grande projeto de compliance. Na prática, são três respostas pequenas e separadas a três perguntas que já faz durante um incidente.
Este guia explica cada um em palavras simples e mostra os comandos para os produzir e verificar numa imagem de container.
Três perguntas
| Artefacto | Pergunta a que responde | Ferramenta open source |
|---|---|---|
| SBOM | O que está dentro desta imagem? | Syft |
| Assinatura | É exatamente isto que publicámos? | cosign |
| Proveniência | Que origem, workflow e builder o produziram? | Geradores SLSA, cosign, GitHub attestations |
Funcionam melhor juntos, ligados à imagem por digest para não se desencontrarem. Uma tag como :latest pode mudar; um digest é um hash do conteúdo e não pode.
SBOM: a lista de ingredientes
Uma software bill of materials lista os pacotes e versões dentro de um artefacto. É útil no dia em que surge uma nova vulnerabilidade e alguém pergunta que serviços incluem a biblioteca afetada. Sem SBOMs, é uma semana de grep. Com eles, é uma consulta.
syft ghcr.io/acme/api@sha256:<digest> -o spdx-json > sbom.spdx.json
# scan the SBOM instead of the image
grype sbom:./sbom.spdx.json
Gere o SBOM no mesmo pipeline que constrói a imagem, não mais tarde a partir de uma cópia tirada de produção. SPDX e CycloneDX servem ambos; escolha um e mantenha-o.
Há dois limites que vale a pena conhecer. Um SBOM só é tão bom quanto a visão que a ferramenta tem da imagem: binários copiados à mão, ou código vendored sem manifest, podem não aparecer. E um SBOM é um snapshot. Diz o que estava lá dentro quando foi construído, que é exatamente o que quer, mas não se atualiza sozinho, por isso guarde-o junto à imagem em vez de o regenerar mais tarde a partir de algo que pode ter mudado.
Assinaturas: o selo de inviolabilidade
Uma assinatura prova que um digest específico foi assinado por uma identidade específica. Com o modo keyless do Sigstore, essa identidade é o seu workflow de CI, provada via OIDC, por isso não há nenhuma chave privada de longa duração para roubar ou rodar.
# in CI, with id-token: write
cosign sign --yes ghcr.io/acme/api@sha256:<digest>
# anywhere else
cosign verify ghcr.io/acme/api@sha256:<digest> \
--certificate-identity-regexp '^https://github.com/acme/api/' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
O passo de verificação é a metade importante. Verificar apenas que existe uma assinatura prova pouco; verifique que veio do seu repositório e do seu workflow.
Proveniência: o recibo do build
A proveniência é uma declaração assinada que descreve como um artefacto foi construído: o repositório e o commit de origem, o workflow, o builder e os inputs. É o que permite dizer que a imagem em produção veio da branch main do repositório certo, construída pela CI e não no portátil de alguém.
Pode associar o SBOM e a provenance como attestations, assinadas da mesma forma que a imagem:
cosign attest --yes --type spdxjson \
--predicate sbom.spdx.json \
ghcr.io/acme/api@sha256:<digest>
# GitHub-native provenance, verified with the gh CLI
gh attestation verify oci://ghcr.io/acme/api@sha256:<digest> --repo acme/api
Níveis SLSA, em resumo
O SLSA é um framework para quanto pode confiar na proveniência. O build track tem níveis que se constroem uns sobre os outros:
- Nível 1. A provenance existe e descreve como o artefacto foi construído. Apanha erros, mas é fácil de falsificar.
- Nível 2. O build corre numa plataforma alojada que gera e assina a própria provenance.
- Nível 3. A plataforma de build tem hardening: os builds estão isolados entre si e o material de assinatura está fora do alcance dos passos de build.
Os níveis descrevem o build, não o código. Um artefacto de Nível 3 pode ainda conter uma biblioteca vulnerável ou um bug; o que o nível diz é que o artefacto veio realmente da origem e do processo que a provenance afirma. É por isso que se combina com o SBOM em vez de o substituir.
A maioria das equipas num serviço de CI alojado consegue chegar ao Nível 2 depressa. O Nível 3 depende sobretudo de como a plataforma de build está configurada, e os reusable workflows do projeto SLSA existem para o facilitar.
Por onde começar
- Escolha um serviço com uma imagem de container e um pipeline de CI.
- Faça o build, o push e capture o digest no passo de push.
- Gere o SBOM com o Syft e anexe-o como attestation.
- Assine o digest keyless com cosign.
- Adicione um passo de verificação antes do deploy, fixado à identidade do seu repositório. Comece em modo de aviso e depois faça-o bloquear.
Quando um serviço funciona, o resto é copiar um reusable workflow. O valor aparece na primeira vez que alguém pergunta o que está a correr e de onde veio, e a resposta demora um minuto em vez de uma reunião.