Compliance as Code: Bloqueando Deploys Inseguros com OPA (Open Policy Agent) e Terraform
Introdução
A escalabilidade de adoção de Infraestrutura como Código (IaC) expõe um gargalo estrutural na esteira de deploy: a validação de compliance de segurança. Quando múltiplos engenheiros submetem Pull Requests com código Terraform diariamente, a auditoria manual via Code Review torna-se uma abordagem insuficiente propensa a omissões críticas como Security Groups com ingress irrestrito (0.0.0.0/0) ou recursos provisionados sem as tags de governança obrigatórias.
O paradigma de Compliance as Code resolve esse problema ao substituir revisões humanas por políticas declarativas, executáveis e determinísticas, acopladas diretamente à esteira de CI/CD. A ferramenta padrão da indústria para essa abordagem é o OPA (Open Policy Agent), um motor de políticas de propósito geral graduado pela CNCF.
O Que é o OPA e o conceito de “Shift-Left”
O Open Policy Agent (OPA) é um motor de políticas de propósito geral. Ele desacopla a tomada de decisão da execução. Em vez de escrever regras de segurança hardcoded nos seus scripts de CI/CD, você escreve políticas declarativas usando uma linguagem própria do OPA chamada Rego.
Aplicar o OPA no pipeline do Terraform significa trazer a validação de segurança para a esquerda (Shift-Left). Em vez de esperar o recurso ser criado na AWS para o AWS Security Hub apitar um alerta de vulnerabilidade, o OPA avalia o “plano de voo” e bloqueia o pipeline antes mesmo do recurso existir.
Como o OPA funciona com o Terraform?
O Terraform não interage nativamente com o OPA na sua execução padrão. A integração é viabilizada pelo formato JSON. O fluxo arquitetural é:
- O Terraform analisa o código e o estado, gerando um plano binário (
terraform plan -out=tfplan). - Convertamos esse plano para uma representação estruturada em JSON (
terraform show -json tfplan > plan.json). - Injetamos o JSON no OPA como Input.
- O OPA cruza o JSON com as Políticas (Rego) e emite uma decisão: Permitir ou Negar.
Bloqueando Configurações de Rede Inseguras
Para demonstrar a implementação prática, utilizaremos uma diretriz de segurança comum como caso de uso: nenhum Security Group da AWS pode permitir tráfego de entrada (ingress) irrestrito de qualquer origem (0.0.0.0/0).
1. Escrevendo a Política em Rego (policy.rego)
Rego é uma linguagem baseada em consultas (query language). A lógica de um bloco deny é: se as condições dentro das chaves forem verdadeiras, a regra foi violada e a mensagem é adicionada à lista de negações.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package terraform.policies
# Define a regra de negação
deny[msg] {
# 1. Itera sobre todas as mudanças de recursos no plano do Terraform
resource := input.resource_changes[_]
# 2. Filtra apenas os recursos que são do tipo 'aws_security_group_rule'
resource.type == "aws_security_group_rule"
# 3. Filtra apenas ações de criação ou atualização
resource.change.actions[_] == "create"
# 4. Verifica se o tipo da regra é 'ingress' (entrada)
resource.change.after.type == "ingress"
# 5. Verifica se algum dos blocos CIDR é '0.0.0.0/0'
resource.change.after.cidr_blocks[_] == "0.0.0.0/0"
# Se todas as linhas acima forem verdadeiras, formata a mensagem de erro:
msg := sprintf("VIOLAÇÃO DE SEGURANÇA: A regra '%s' permite tráfego de entrada irrestrito (0.0.0.0/0).", [resource.address])
}
2. Avaliando o Código (O Pipeline de CI/CD)
No seu pipeline do GitHub Actions, GitLab CI ou Jenkins, o fluxo executado será:
1
2
3
4
5
6
7
8
# 1. Gera o plano do Terraform
terraform plan -out=tfplan
# 2. Converte o plano para JSON
terraform show -json tfplan > plan.json
# 3. Avalia o plano contra a política Rego usando o binário do OPA
opa eval --format pretty --data policy.rego --input plan.json "data.terraform.policies.deny"
3. O Resultado
Dado um recurso aws_security_group_rule com ingress aberto para 0.0.0.0/0, a saída do OPA será:
1
2
3
[
"VIOLAÇÃO DE SEGURANÇA: A regra 'aws_security_group_rule.web_ingress' permite tráfego de entrada irrestrito (0.0.0.0/0)."
]
No pipeline, basta adicionar um script simples para checar se o array de resposta está vazio. Se não estiver, o CI falha com exit 1 e o terraform apply nunca chega a ser executado.
Conftest: A Ferramenta do Desenvolvedor
Escrever e rodar comandos opa eval nativos pode ser um pouco árduo. Para pipelines de IaC, o ecossistema criou o Conftest (que roda o motor do OPA por baixo dos panos).
Com o Conftest, a experiência de validação fica tão simples quanto rodar um linter:
1
conftest test plan.json -p policy.rego
Saída do Conftest:
1
2
FAIL - plan.json - main - VIOLAÇÃO DE SEGURANÇA: A regra 'aws_security_group_rule.web_ingress' permite tráfego...
1 test, 1 passed, 0 warnings, 1 failure, 0 exceptions
OPA vs. HashiCorp Sentinel
Se você utiliza o Terraform Cloud/Enterprise, já possui o HashiCorp Sentinel, que resolve exatamente o mesmo problema. A desvantagem do Sentinel é o vendor lock-in e o licenciamento pago.
O OPA, por outro lado, é open source e universal. Você pode usar a mesma linguagem Rego para validar não apenas o Terraform, mas também manifestos do Kubernetes, permissões de APIs, configurações do Envoy/Consul e arquivos Docker. Isso unifica a linguagem de Governança da empresa inteira.
Conclusão
Delegar a responsabilidade da auditoria de segurança à memória ou à atenção de alguém durante um Code Review é uma receita para o desastre (e vazamentos de dados).
Ao implementar o Open Policy Agent, transformamos os manuais de segurança em formato PDF em código executável e determinístico. O Compliance as Code não apenas protege a empresa contra configurações equivocadas de infraestrutura, como dá aos desenvolvedores um feedback imediato (e seguro) para corrigirem seus erros antes mesmo de envolverem a equipe de Segurança.