Pular para o conteúdo

Política como código

Avançado16 min de leituradevsecops

“Todo bucket precisa ser privado” escrito em uma página de wiki é uma intenção. A mesma frase como código executável é uma garantia: ela roda no pull request, roda na admissão do cluster e diz exatamente qual recurso está fora da regra e por quê.

Política como código também resolve o problema humano de segurança: ninguém precisa lembrar de tudo, e a revisão deixa de ser o gargalo.

O mesmo requisito costuma precisar de dois pontos de aplicação:

  • No CI, sobre o plano ou o manifest — feedback rápido, antes do merge, com a pessoa que pode corrigir.
  • Na admissão, no cluster ou na nuvem — barreira final, que pega o que não passou pelo pipeline (aplicação manual, controlador, operador).

Só CI é contornável; só admissão é frustrante, porque o erro aparece tarde. Use os dois, com a mesma regra versionada.

Kyverno expressa políticas em YAML, o que reduz muito a barreira de entrada em ambiente Kubernetes. Ele valida, muta (corrige o recurso na admissão) e gera recursos.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata: { name: exigir-limites-e-nao-root }
spec:
validationFailureAction: Audit # comece aqui; troque para Enforce depois
background: true # avalia também o que já existe
rules:
- name: limites-obrigatorios
match: { any: [{ resources: { kinds: [Pod] } }] }
exclude: { any: [{ resources: { namespaces: [kube-system] } }] }
validate:
message: "Todo container precisa declarar requests e limits de memória."
pattern:
spec:
containers:
- resources:
requests: { memory: "?*" }
limits: { memory: "?*" }
- name: sem-root
match: { any: [{ resources: { kinds: [Pod] } }] }
validate:
message: "Containers não podem rodar como root."
pattern:
spec:
=(securityContext):
=(runAsNonRoot): true
Janela do terminal
kubectl kyverno apply politicas/ --resource manifests/ # no CI, antes do merge
kubectl get policyreport -A # o que já está fora, em Audit

Quando a política precisa valer para Terraform, para o pipeline ou para uma API própria, OPA com Rego é a escolha — a mesma engine avalia qualquer JSON.

package terraform.s3
# Nenhum bucket novo pode ser público.
deny contains msg if {
recurso := input.resource_changes[_]
recurso.type == "aws_s3_bucket_public_access_block"
recurso.change.after.block_public_acls == false
msg := sprintf("bucket %s permite ACL pública", [recurso.address])
}
Janela do terminal
terraform plan -out=plano.bin
terraform show -json plano.bin > plano.json
conftest test plano.json --policy politicas/ # falha o PR com a mensagem acima

Rego tem curva de aprendizado real. Comece por poucas regras de alto valor e escreva teste para cada política — política errada bloqueia entrega legítima e queima a confiança na prática inteira.

test_bucket_publico_e_negado if {
count(deny) == 1 with input as {"resource_changes": [...]}
}

A sequência que funciona, sempre nesta ordem:

  1. Escreva a regra e rode em modo auditoria, sem bloquear nada.
  2. Meça quantos recursos existentes violam. Quase sempre é mais do que se imagina.
  3. Corrija o acervo, ou registre exceção com dono e prazo.
  4. Bloqueie para recursos novos primeiro.
  5. Só então bloqueie para tudo.

Ligar Enforce no primeiro dia derruba deploy legítimo, gera um incidente e faz a política ser desativada “temporariamente” — estado em que ela costuma ficar para sempre.

Toda política precisa de uma porta de saída documentada, ou as pessoas vão contornar por fora:

apiVersion: kyverno.io/v2
kind: PolicyException
metadata: { name: legado-pagamentos, namespace: pagamentos }
spec:
exceptions:
- policyName: exigir-limites-e-nao-root
ruleNames: [sem-root]
match: { any: [{ resources: { namespaces: [pagamentos], names: [legado-*] } }] }
# Registre no PR: dono @carla, motivo (imagem legada), revisão em 2026-12-01

Exceção sem prazo é a política revogada em silêncio. Revise a lista por trimestre — a lista encolhendo é a melhor métrica de que a prática está funcionando.

A mensagem de erro é a documentação que a pessoa realmente lê. Diga o que está errado, por que a regra existe e como corrigir, com link para o guia interno. “Policy violation: require-non-root” custa quinze minutos de alguém; a mesma regra com uma frase útil custa zero.

Próximo passo: aplique essas regras à superfície de host, container e cluster em Hardening.