wlls / devsecops / cosign-sigstore
devsecops

Assinando imagens de container com Cosign e Sigstore

wander·18 de set.·3 min de leitura

Objetivo

Sem assinatura, qualquer imagem que chega no seu cluster é confiança cega — não tem como distinguir uma imagem que saiu do seu pipeline de CI de uma publicada por qualquer pessoa com push access no registry. Cosign, do projeto Sigstore, assina imagens de container e permite verificar essa assinatura antes do deploy.

Este guia cobre o modo keyless: a identidade OIDC do runner de CI substitui a necessidade de gerenciar e rotacionar chaves privadas. Não cobre assinatura com chave estática (cosign generate-key-pair) nem verificação de SBOM/attestations — isso fica para um próximo artigo.

Premissas

  • Pipeline de CI com identidade OIDC configurada (GitHub Actions e GitLab CI oferecem isso nativamente via OIDC token do próprio runner).
  • Cosign na versão 3.x — a v3 mudou o formato de bundle padrão de assinatura em relação à v2; se você tiver scripts ou automações escritos para a v2, confira o changelog antes de atualizar.
  • Os comandos abaixo seguem a documentação oficial do Sigstore, mas não foram executados neste ambiente — o formato de flags do cosign muda entre versões, confirme na sua antes de aplicar.

Implementação

Instalar o Cosign

Evite fixar uma versão específica no comando de instalação — ela fica desatualizada rápido. Prefira um gerenciador de pacote ou o instalador via Go, que sempre resolvem para a versão mais recente:

brew install cosign
# ou, com Go 1.20+:
go install github.com/sigstore/cosign/v3/cmd/cosign@latest

Assinar no CI (keyless)

Com o modo keyless, a identidade OIDC do runner substitui a chave privada — cada assinatura fica registrada no log de transparência público do Sigstore (Rekor), auditável a qualquer momento:

cosign sign --yes registry.example.com/api@sha256:<digest-da-imagem>

Substitua registry.example.com/api e <digest-da-imagem> pelos valores reais do seu pipeline — use o digest (sha256:...), não a tag, para não assinar um alvo que pode mudar depois.

Verificar antes do deploy

Assinar sem verificar não trava nada. A verificação confirma que a assinatura veio do workflow de CI esperado, não de qualquer identidade OIDC:

cosign verify \
  --certificate-identity-regexp="https://github.com/<sua-org>/<seu-repo>/.github/workflows/.*" \
  --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
  registry.example.com/api@sha256:<digest-da-imagem>

O --certificate-identity-regexp é o controle que importa aqui: se ficar genérico demais (por exemplo, aceitando qualquer identidade do seu provedor OIDC), a verificação passa a aceitar assinaturas de qualquer repositório da sua organização, não só do pipeline que deveria assinar essa imagem.

Validação

A forma mais direta de confirmar que a cadeia está funcionando é tentar subir uma imagem sem assinatura válida num cluster que já tenha a verificação aplicada no admission controller — como no guia de OPA Gatekeeper, uma constraint pode rejeitar qualquer imagem sem assinatura antes do pod ser aceito. Comece em modo de auditoria (sem bloquear) para medir quantas imagens hoje não passariam, antes de aplicar bloqueio de verdade.

Limitações relevantes

  • Depende do Rekor estar disponível. Assinatura keyless registra no log de transparência público; se o Rekor estiver fora do ar no momento do CI, a assinatura falha. Isso é intencional (evita assinatura sem registro auditável), mas pode gerar falso alarme se você não souber disso.
  • Regex de identidade genérico demais anula o controle. Vale repetir: um --certificate-identity-regexp amplo demais verifica a origem "de algum lugar da sua org", não "do pipeline certo".
  • Assinar não é escanear. Cosign garante proveniência (quem assinou, quando, com qual workflow) — não garante que a imagem esteja livre de dependências vulneráveis. Isso é um controle complementar a scanners como Trivy ou Grype, não um substituto.

Próximo passo

Depois de assinar e verificar imagens, o próximo controle costuma ser anexar e verificar um SBOM (cosign attest) — assim a verificação cobre não só quem publicou a imagem, mas o que está dentro dela.

#cosign#supply-chain#kubernetes