Policy as code com OPA: governança de infraestrutura como código versionado
1. Introdução ao Policy as Code e OPA
A governança de infraestrutura tradicionalmente dependia de checklists manuais, revisões em planilhas e auditorias pós-implantação. Esse modelo mostrou-se frágil em ambientes cloud-native, onde mudanças acontecem dezenas de vezes ao dia. O Policy as Code (PaC) surge como resposta: trata-se da prática de definir regras de conformidade, segurança e autorização como artefatos de software — versionados, testáveis e automatizados.
O Open Policy Agent (OPA) é o motor de políticas open-source mais adotado nesse contexto. Mantido pela CNCF, o OPA é agnóstico a stack: funciona com Kubernetes, Terraform, APIs REST, Docker, Envoy e praticamente qualquer sistema que precise tomar decisões baseadas em políticas. Seu diferencial está na linguagem declarativa Rego, que permite expressar regras complexas de forma concisa.
Os benefícios são diretos: políticas versionadas em Git permitem rastreabilidade total, revisão via Pull Requests, testes automatizados e consistência entre ambientes de desenvolvimento, staging e produção.
2. Conceitos Fundamentais do OPA
No OPA, toda decisão é modelada como uma consulta a um conjunto de regras escritas em Rego. O fluxo básico é:
- input: dados da requisição (ex.: um JSON com recurso e ação)
- data: dados externos carregados (ex.: listas de usuários, configurações de rede)
- output: resultado booleano (allow/deny) ou estruturado
A estrutura mínima de uma política em Rego:
package example.authz
default allow = false
allow {
input.method == "GET"
input.path == "/public"
}
allow {
input.method == "POST"
input.user.role == "admin"
}
A diferença entre tipos de políticas é sutil mas importante:
- Autorização: decide se uma ação é permitida (quem pode fazer o quê)
- Validação: verifica se um recurso está em conformidade (ex.: tags obrigatórias)
- Conformidade: checa aderência a regulamentações (ex.: dados não podem sair de região específica)
3. Integração com Infraestrutura como Código (IaC)
Uma das aplicações mais imediatas do OPA é validar planos do Terraform antes do apply. Usando a ferramenta Conftest, podemos escrever políticas que inspecionam o HCL gerado.
Exemplo de política que bloqueia buckets S3 públicos:
package main
deny[msg] {
input.kind == "aws_s3_bucket"
input.value.acl == "public-read"
msg = sprintf("Bucket %s não pode ter ACL pública", [input.value.name])
}
Para executar:
conftest test --policy policy/ terraform/plan.json
Em pipelines CI/CD, essa validação funciona como gatekeeping automático:
# .github/workflows/terraform.yml
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: terraform plan -out=plan.tfplan
- run: terraform show -json plan.tfplan > plan.json
- run: conftest test --policy policy/ plan.json
Se a política falhar, o pipeline para e o engenheiro precisa corrigir antes de prosseguir.
4. Versionamento e Ciclo de Vida das Políticas
Políticas OPA devem ser tratadas como código de primeira classe. A prática recomendada é:
- Armazenar em repositório Git dedicado ou em diretório
policy/no mesmo repositório do IaC - Usar versionamento semântico nos bundles (ex.:
v1.2.3) - Escrever testes unitários em Rego
Exemplo de teste para a política de buckets:
package main
test_bucket_public {
deny with input as {"kind": "aws_s3_bucket", "value": {"name": "test", "acl": "public-read"}}
}
test_bucket_private {
not deny with input as {"kind": "aws_s3_bucket", "value": {"name": "test", "acl": "private"}}
}
Execução dos testes:
opa test ./policy/ -v
Pull Requests para políticas devem incluir:
- Descrição clara da regra
- Casos de teste cobrindo cenários positivos e negativos
- Impacto estimado (quantos recursos existentes seriam afetados)
5. Casos de Uso Práticos em Microsserviços e Kubernetes
No ecossistema Kubernetes, o Gatekeeper atua como um Admission Controller baseado em OPA. Ele intercepta requisições à API e aplica políticas antes que os recursos sejam persistidos.
Política que exige label app em todos os Pods:
package k8s.requiredlabels
violation[{"msg": msg}] {
input.request.kind.kind == "Pod"
not input.request.object.metadata.labels.app
msg = "Pod deve ter label 'app' definida"
}
Para aplicar no cluster:
kubectl apply -f constraint-template.yaml
kubectl apply -f constraint.yaml
Outro caso comum é o controle de registros de imagens:
package k8s.allowedregistries
violation[{"msg": msg}] {
container := input.request.object.spec.containers[_]
not startswith(container.image, "registry.empresa.com/")
msg = sprintf("Imagem %s não é de registro autorizado", [container.image])
}
6. Operacionalização: Deploy, Monitoramento e Escalabilidade
Para ambientes de produção, o OPA pode rodar como servidor HTTP standalone, recebendo requisições e respondendo decisões em milissegundos.
Configuração básica do servidor:
opa run --server --set=decision_logs.console=true --bundle policy/
A distribuição de bundles pode ser feita via:
- HTTP: OPA faz polling periódico em um endpoint que serve o bundle
- Sistemas de arquivos: montagem de volume com as políticas
- Styra DAS: plataforma gerenciada que oferece UI, versionamento e auditoria
Métricas importantes para monitoramento:
opa_http_request_duration_seconds: latência das avaliaçõesopa_evaluator_count: número de avaliações por segundoopa_cache_hit_ratio: eficiência do cache de decisões
Para bundles grandes, recomenda-se warm-up: carregar políticas antes de aceitar tráfego real.
7. Desafios e Boas Práticas
A linguagem Rego tem curva de aprendizado íngreme. Dicas para mitigar:
- Usar
opa eval --format prettypara depurar expressões isoladas - Habilitar
--log-level debugdurante desenvolvimento - Dividir políticas complexas em pacotes menores e reutilizáveis
Gerenciamento de dependências entre políticas e dados externos:
# Carregar dados de times autorizados
data_teams := data.external.teams
allow {
input.team == data_teams[_]
}
Boas práticas essenciais:
- Simplicidade: uma política deve fazer uma coisa bem feita
- Cobertura de testes: pelo menos 80% de cobertura nas regras críticas
- Documentação: cada política deve ter comentário explicando o objetivo e o contexto
- Revisão: nunca mergear políticas sem aprovação de pelo menos dois pares
8. Conclusão e Tendências Futuras
Adotar Policy as Code com OPA transforma a governança de infraestrutura de um processo reativo e manual para algo proativo, automatizado e auditável. Cada política se torna um artefato versionado, testado e revisado como qualquer outro código. Os ganhos incluem redução de incidentes de segurança, conformidade contínua com regulamentações e rastreabilidade completa de decisões.
O ecossistema evolui rapidamente: OPA já está sendo usado no edge computing, em políticas orientadas a eventos com Kafka e em service meshes como Istio para autorização granular. Ferramentas como Conftest e Styra DAS ampliam o alcance para IaC e gerenciamento centralizado.
Para começar: escolha uma política simples (ex.: "proibir buckets públicos"), escreva em Rego, integre ao pipeline de CI/CD e expanda gradualmente. A jornada de governança como código começa com o primeiro teste passando.
Referências
- Open Policy Agent - Documentação Oficial — Guia completo sobre instalação, linguagem Rego, integrações e operação do OPA
- Conftest - Teste de Configurações com OPA — Ferramenta para validar arquivos de configuração (Terraform, Docker, Kubernetes) usando políticas OPA
- Gatekeeper - Admission Controller para Kubernetes — Documentação do projeto que integra OPA como controlador de admissão no Kubernetes
- Rego Playground — Ambiente interativo para aprender e testar políticas Rego diretamente no navegador
- Styra DAS - Gerenciamento Centralizado de Políticas — Plataforma comercial para gerenciar, versionar e auditar políticas OPA em escala empresarial
- Policy as Code: OPA in Practice - CNCF Webinar — Webinar técnico da CNCF com exemplos práticos de adoção de OPA em ambientes cloud-native