O Que é Compliance como Código
Compliance como Código é um paradigma que transforma políticas e padrões de conformidade em código executável, permitindo que sistemas sejam validados automaticamente contra regras de negócio, segurança e governança. Em vez de manuais em PDF ou checklists manuais, você define suas políticas em linguagens de programação específicas e as aplica de forma contínua no seu pipeline de infraestrutura.
No contexto de Kubernetes, isso significa garantir que seus manifestos YAML, configurações de rede, permissões RBAC e deployments estejam sempre em conformidade com os padrões corporativos antes mesmo de serem deployados. Essa abordagem reduz riscos de segurança, evita configurações incorretas e torna a auditoria muito mais simples, já que tudo fica rastreável e versionado no seu repositório Git.
OPA (Open Policy Agent): Fundamentos e Arquitetura
OPA é um mecanismo de decisão de políticas agnóstico de domínio desenvolvido pela CNCF. Ele usa uma linguagem declarativa chamada Rego para expressar políticas complexas de uma forma legível e testável. OPA funciona como um servidor que recebe dados em JSON, avalia-os contra suas políticas e retorna decisões estruturadas.
Como OPA Funciona
OPA recebe uma requisição contendo um JSON com o contexto que deve ser validado. Você define regras em Rego que analisam esse JSON e produzem uma decisão booleana ou estruturada. A força do OPA está na sua capacidade de trabalhar com qualquer tipo de dado: configurações Kubernetes, requisições HTTP, eventos de auditoria ou até artefatos de container.
Um exemplo simples de política em Rego que garante que todo Pod tenha um securityContext definido:
package kubernetes.admission
deny[msg] {
input.request.kind.kind == "Pod"
not input.request.object.spec.securityContext
msg := "Pods devem ter securityContext definido"
}
Neste código, a regra deny é ativada quando o objeto sendo avaliado é um Pod e ele não possui securityContext. Se a condição for verdadeira, a política retorna uma mensagem de negação.
Instalando e Configurando OPA
Para instalar OPA em seu ambiente local, você pode usar o gerenciador de pacotes ou baixar o binário diretamente:
# macOS usando Homebrew
brew install opa
# Linux - fazer download do binário
curl -L -o opa https://openpolicyagent.org/downloads/latest/opa_linux_x86_64
chmod +x opa
sudo mv opa /usr/local/bin/
Para testar uma política rapidamente, você pode usar o REPL do OPA:
opa run --server
Isso inicia um servidor OPA na porta 8181. Você pode então fazer requisições POST para /v1/data/<seu-pacote>/<sua-regra> com um JSON contendo seus dados.
Exemplo Prático: Política de Imagens
Uma política comum é garantir que todas as imagens de container tenham tags explícitas e venham de registries autorizados:
package kubernetes.admission
import data.lib.utils
deny[msg] {
input.request.kind.kind == "Pod"
container := input.request.object.spec.containers[_]
# Verifica se a imagem possui tag
not contains(container.image, ":")
msg := sprintf("Container %v deve ter tag explícita (não use 'latest')", [container.name])
}
deny[msg] {
input.request.kind.kind == "Pod"
container := input.request.object.spec.containers[_]
# Verifica registries autorizados
allowed_registries := ["docker.io", "gcr.io", "registry.empresa.com"]
registry := split(container.image, "/")[0]
not utils.contains_array(registry, allowed_registries)
msg := sprintf("Registry %v não é autorizado", [registry])
}
Conftest: Integrando OPA com Seu Pipeline
Conftest é uma ferramenta de linha de comando que simplifica o teste de configurações contra políticas OPA. Ele recebe arquivos YAML, JSON, Terraform, Dockerfile e outros formatos, valida-os contra suas regras Rego e retorna os resultados de forma clara. Conftest é perfeito para executar validações em seu CI/CD antes que qualquer mudança chegue ao Kubernetes.
Instalando Conftest
# macOS
brew install conftest
# Linux usando curl
curl -JLO https://github.com/open-policy-agent/conftest/releases/download/v0.46.0/conftest_0.46.0_Linux_x86_64.tar.gz
tar xf conftest_0.46.0_Linux_x86_64.tar.gz
sudo mv conftest /usr/local/bin/
Estrutura de Projeto com Conftest
Uma estrutura típica para organizar suas políticas:
projeto-kubernetes/
├── policies/
│ ├── security/
│ │ ├── pod_security.rego
│ │ ├── network_policy.rego
│ │ └── rbac.rego
│ ├── compliance/
│ │ ├── labels_obrigatorios.rego
│ │ └── resource_limits.rego
│ └── utils.rego
├── manifests/
│ ├── deployment.yaml
│ ├── service.yaml
│ └── ingress.yaml
└── tests/
└── policies_test.rego
Exemplo: Política de Labels Obrigatórios
Crie o arquivo policies/compliance/labels_obrigatorios.rego:
package main
# Labels obrigatórios em todos os recursos
required_labels := ["app", "version", "owner"]
deny[msg] {
# Verifica todos os tipos de recursos
resource_type := input.kind
resource_type != "Namespace" # Namespaces têm suas próprias regras
# Obtém os labels do metadata
labels := object.get(input.metadata, "labels", {})
# Verifica se cada label obrigatório existe
missing := [label |
label := required_labels[_]
not labels[label]
]
count(missing) > 0
msg := sprintf(
"Resource %v/%v está faltando labels: %v",
[input.kind, input.metadata.name, missing]
)
}
Agora crie um manifesto para testar:
# manifests/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: minha-app
labels:
app: minha-app
version: "1.0"
owner: devops-team
spec:
replicas: 3
selector:
matchLabels:
app: minha-app
template:
metadata:
labels:
app: minha-app
version: "1.0"
owner: devops-team
spec:
containers:
- name: app
image: myapp:1.2.3
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"
Execute a validação:
conftest test manifests/deployment.yaml -p policies/
Se algum label obrigatório estivesse faltando, Conftest retornaria um erro claro indicando exatamente qual label está ausente e em qual recurso.
Integrando Conftest no Pipeline GitHub Actions
name: Validate Kubernetes Manifests
on:
pull_request:
paths:
- 'manifests/**'
- 'policies/**'
jobs:
conftest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: instrumenta/conftest-action@master
with:
files: manifests/
policy: policies/
options: -o json
Este workflow executa Conftest automaticamente toda vez que alguém abre um PR com mudanças em manifestos ou políticas, garantindo conformidade antes do merge.
Policy Enforcement em Kubernetes: Admission Controllers
Enquanto Conftest valida manifestos em tempo de build, você também precisa enforçar políticas em tempo de runtime. Kubernetes oferece dois mecanismos: Validating Admission Webhooks e Mutating Admission Webhooks. OPA integra-se perfeitamente nesse ecossistema através do Gatekeeper, um controlador específico para Kubernetes que executa políticas OPA.
O Que é Gatekeeper
Gatekeeper é um Kubernetes Admission Controller que intercepta requisições para criar ou modificar recursos e valida-as contra suas políticas OPA antes de permitir que a operação prossiga. Se uma política é violada, a requisição é rejeitada e o usuário recebe uma mensagem de erro clara.
Instalando Gatekeeper
# Adicione o repositório Helm
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
# Instale o Gatekeeper
helm install gatekeeper/gatekeeper \
--namespace gatekeeper-system \
--create-namespace \
--set enableExternalData=true \
--set enableGeneratorResourceExpansion=true
Exemplo: Implementando uma Restrição de CPU e Memória
No Gatekeeper, você define ConstraintTemplates (templates de restrição) e depois cria instâncias delas (Constraints). A ConstraintTemplate define a lógica em Rego, e a Constraint especifica os parâmetros e objetivos.
Crie um arquivo constraint-template.yaml:
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredresources
spec:
crd:
spec:
names:
kind: K8sRequiredResources
validation:
openAPIV3Schema:
properties:
exemptNamespaces:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredresources
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not container.resources.requests
msg := sprintf("Container %v deve ter requests definidos", [container.name])
}
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not container.resources.limits
msg := sprintf("Container %v deve ter limits definidos", [container.name])
}
Agora crie a Constraint que aplica essa restrição:
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredResources
metadata:
name: require-resources-all-pods
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
excludedNamespaces: ["kube-system", "kube-public"]
Quando você tentar criar um Pod sem resources definidos, Gatekeeper o rejeitará automaticamente:
$ kubectl apply -f pod-sem-resources.yaml
Error from server ([denied by require-resources-all-pods]
Container nginx deve ter requests definidos):
error when creating "pod-sem-resources.yaml": admission webhook
"validation.gatekeeper.sh" denied the request
Auditoria sem Rejeição
Às vezes você quer monitorar violações sem bloquear deployments imediatamente. Configure o Gatekeeper em modo auditoria:
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredResources
metadata:
name: require-resources-all-pods
spec:
enforcementAction: audit # ao invés de "deny"
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
Com enforcementAction: audit, violações são registradas mas não bloqueiam operações. Isso é útil para um período de transição antes de ativar enforcement total.
Conclusão
Compliance como Código transforma governança de infraestrutura de um processo manual e propenso a erros em uma prática automatizada e auditável. Os três aprendizados principais são: (1) OPA e Rego fornecem a camada de decisão declarativa, permitindo expressar políticas complexas em código legível e testável; (2) Conftest integra validação de políticas no seu pipeline de CI/CD, capturando problemas antes do deployment; (3) Gatekeeper enforce políticas em runtime no Kubernetes, servindo como última linha de defesa contra configurações não-conformes.
Implementar essa stack não é apenas sobre segurança — é sobre confiabilidade. Quando suas políticas estão codificadas, versionadas e testadas, você elimina configurações manuais inconsistentes e cria um ambiente onde conformidade é a regra, não a exceção.