<h2>O Que é Compliance como Código</h2>
<p>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.</p>
<p>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.</p>
<h2>OPA (Open Policy Agent): Fundamentos e Arquitetura</h2>
<p>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.</p>
<h3>Como OPA Funciona</h3>
<p>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.</p>
<p>Um exemplo simples de política em Rego que garante que todo Pod tenha um <code>securityContext</code> definido:</p>
<pre><code class="language-rego">package kubernetes.admission
deny[msg] {
input.request.kind.kind == "Pod"
not input.request.object.spec.securityContext
msg := "Pods devem ter securityContext definido"
}</code></pre>
<p>Neste código, a regra <code>deny</code> é ativada quando o objeto sendo avaliado é um Pod e ele não possui <code>securityContext</code>. Se a condição for verdadeira, a política retorna uma mensagem de negação.</p>
<h3>Instalando e Configurando OPA</h3>
<p>Para instalar OPA em seu ambiente local, você pode usar o gerenciador de pacotes ou baixar o binário diretamente:</p>
<pre><code class="language-bash"># 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/</code></pre>
<p>Para testar uma política rapidamente, você pode usar o REPL do OPA:</p>
<pre><code class="language-bash">opa run --server</code></pre>
<p>Isso inicia um servidor OPA na porta 8181. Você pode então fazer requisições POST para <code>/v1/data/<seu-pacote>/<sua-regra></code> com um JSON contendo seus dados.</p>
<h3>Exemplo Prático: Política de Imagens</h3>
<p>Uma política comum é garantir que todas as imagens de container tenham tags explícitas e venham de registries autorizados:</p>
<pre><code class="language-rego">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])
}</code></pre>
<h2>Conftest: Integrando OPA com Seu Pipeline</h2>
<p>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.</p>
<h3>Instalando Conftest</h3>
<pre><code class="language-bash"># 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/</code></pre>
<h3>Estrutura de Projeto com Conftest</h3>
<p>Uma estrutura típica para organizar suas políticas:</p>
<pre><code>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</code></pre>
<h3>Exemplo: Política de Labels Obrigatórios</h3>
<p>Crie o arquivo <code>policies/compliance/labels_obrigatorios.rego</code>:</p>
<pre><code class="language-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]
)
}</code></pre>
<p>Agora crie um manifesto para testar:</p>
<pre><code class="language-yaml"># 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"</code></pre>
<p>Execute a validação:</p>
<pre><code class="language-bash">conftest test manifests/deployment.yaml -p policies/</code></pre>
<p>Se algum label obrigatório estivesse faltando, Conftest retornaria um erro claro indicando exatamente qual label está ausente e em qual recurso.</p>
<h3>Integrando Conftest no Pipeline GitHub Actions</h3>
<pre><code class="language-yaml">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</code></pre>
<p>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.</p>
<h2>Policy Enforcement em Kubernetes: Admission Controllers</h2>
<p>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.</p>
<h3>O Que é Gatekeeper</h3>
<p>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.</p>
<h3>Instalando Gatekeeper</h3>
<pre><code class="language-bash"># 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</code></pre>
<h3>Exemplo: Implementando uma Restrição de CPU e Memória</h3>
<p>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.</p>
<p>Crie um arquivo <code>constraint-template.yaml</code>:</p>
<pre><code class="language-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])
}</code></pre>
<p>Agora crie a Constraint que aplica essa restrição:</p>
<pre><code class="language-yaml">apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredResources
metadata:
name: require-resources-all-pods
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
excludedNamespaces: ["kube-system", "kube-public"]</code></pre>
<p>Quando você tentar criar um Pod sem resources definidos, Gatekeeper o rejeitará automaticamente:</p>
<pre><code class="language-bash">$ 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</code></pre>
<h3>Auditoria sem Rejeição</h3>
<p>Às vezes você quer monitorar violações sem bloquear deployments imediatamente. Configure o Gatekeeper em modo auditoria:</p>
<pre><code class="language-yaml">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"]</code></pre>
<p>Com <code>enforcementAction: audit</code>, 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.</p>
<h2>Conclusão</h2>
<p>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) <strong>OPA e Rego</strong> fornecem a camada de decisão declarativa, permitindo expressar políticas complexas em código legível e testável; (2) <strong>Conftest</strong> integra validação de políticas no seu pipeline de CI/CD, capturando problemas antes do deployment; (3) <strong>Gatekeeper</strong> enforce políticas em runtime no Kubernetes, servindo como última linha de defesa contra configurações não-conformes.</p>
<p>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.</p>
<h2>Referências</h2>
<ol>
<li><a href="https://www.openpolicyagent.org/docs/latest/" target="_blank" rel="noopener noreferrer">Open Policy Agent Official Documentation</a></li>
<li><a href="https://github.com/open-policy-agent/conftest" target="_blank" rel="noopener noreferrer">Conftest GitHub Repository</a></li>
<li><a href="https://open-policy-agent.org/docs/latest/kubernetes-introduction/" target="_blank" rel="noopener noreferrer">Gatekeeper: Policy Controller for Kubernetes</a></li>
<li><a href="https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/" target="_blank" rel="noopener noreferrer">Kubernetes Admission Controllers Documentation</a></li>
<li><a href="https://www.cncf.io/blog/2021/12/01/policy-as-code-the-api-gateway-use-case/" target="_blank" rel="noopener noreferrer">CNCF Policy as Code Whitepaper</a></li>
</ol>
<p><!-- FIM --></p>