Como projetar sistemas de autorização baseados em políticas
1. Fundamentos da Autorização Baseada em Políticas (PBA)
1.1. Definição e diferenças entre RBAC, ABAC e PBA
A autorização baseada em políticas (PBA) representa uma evolução em relação aos modelos tradicionais de controle de acesso. Enquanto o RBAC (Role-Based Access Control) gerencia permissões através de papéis predefinidos e o ABAC (Attribute-Based Access Control) utiliza atributos do usuário, recurso e ambiente, o PBA combina o melhor de ambos ao permitir que decisões sejam tomadas com base em políticas declarativas e flexíveis.
No RBAC, um gerente sempre pode acessar relatórios financeiros. No ABAC, um gerente pode acessar relatórios apenas durante o horário comercial. No PBA, a política pode ser: "Permitir acesso a relatórios financeiros se o usuário for gerente E o horário for comercial E o dispositivo for corporativo E a localização for a sede da empresa". A diferença fundamental é que o PBA externaliza completamente a lógica de decisão da aplicação.
1.2. Componentes essenciais
Um sistema PBA maduro é composto por quatro componentes arquiteturais principais:
- Policy Enforcement Point (PEP): Intercepta requisições na aplicação e delega a decisão ao PDP.
- Policy Decision Point (PDP): Motor de decisão que avalia políticas e retorna permit/deny.
- Policy Information Point (PIP): Fornece atributos contextuais (localização, horário, nível de risco).
- Policy Administration Point (PAP): Interface para gerenciamento e versionamento de políticas.
1.3. Vantagens da separação entre lógica de decisão e lógica de aplicação
Ao externalizar a autorização, ganhamos:
- Auditabilidade centralizada: Todas as decisões são registradas em um único ponto.
- Atualização sem deploy: Políticas podem ser alteradas sem reimplantar microsserviços.
- Consistência entre serviços: A mesma política vale para APIs, filas e bancos de dados.
2. Modelagem de Políticas: Estrutura e Linguagens
2.1. Estrutura típica de uma política
Toda política PBA segue o padrão: Sujeito + Recurso + Ação + Condição. Exemplo:
Permitir que [usuário: admin] [ação: deletar] [recurso: usuários] se [condição: departamento == "TI"]
2.2. Linguagens de definição de políticas
As principais linguagens são:
- XACML: Padrão OASIS, verboso mas completo.
- Rego (OPA): Declarativa, amplamente adotada em cloud-native.
- ALFA: Abstração sobre XACML, mais legível.
Exemplo em Rego:
package authz
default allow = false
allow {
input.method == "GET"
input.path == "/api/users"
input.user.role == "admin"
}
2.3. Hierarquia e combinação de políticas
Algoritmos de combinação definem o resultado quando múltiplas políticas se aplicam:
- Deny-overrides: Se qualquer política negar, a decisão final é negar.
- Permit-overrides: Se qualquer política permitir, a decisão final é permitir.
- First-applicable: A primeira política que corresponder define a decisão.
3. Arquitetura de um Sistema de Autorização Baseado em Políticas
3.1. Fluxo de requisição
O fluxo típico é:
- Cliente faz requisição ao serviço A.
- PEP no serviço A intercepta e monta o contexto (usuário, ação, recurso).
- PEP envia requisição de decisão ao PDP.
- PDP consulta PIP para atributos adicionais (ex: score de confiança).
- PDP avalia políticas e retorna
allowoudeny. - PEP executa ou bloqueia a ação original.
3.2. Armazenamento e distribuição de políticas
Políticas podem ser armazenadas em:
- Bundles estáticos: Arquivos locais versionados no deploy.
- Serviços centralizados: OPA como servidor com APIs de gerenciamento.
- Bancos de dados: Para políticas dinâmicas em tempo real.
3.3. Cache de decisões e estratégias de invalidação
Cache é crítico para desempenho. Estratégias comuns:
- TTL fixo: Decisões expiram após N segundos.
- Invalidation por evento: Quando uma política muda, caches são limpos.
- Cache por chave composta: (usuário + recurso + ação) como chave.
4. Implementação com Open Policy Agent (OPA)
4.1. Instalação e configuração básica do OPA como PDP
# Baixar e iniciar OPA como servidor
wget https://openpolicyagent.org/downloads/v0.58.0/opa_linux_amd64
chmod +x opa_linux_amd64
./opa_linux_amd64 run --server --addr :8181
4.2. Exemplo de política em Rego
Política para controle de acesso a endpoints de API:
package api.authz
# Regra padrão: negar acesso
default allow = false
# Permitir acesso GET a /public para qualquer usuário autenticado
allow {
input.method == "GET"
input.path == "/api/public"
input.user.authenticated == true
}
# Permitir acesso POST a /admin apenas para admins
allow {
input.method == "POST"
startswith(input.path, "/api/admin")
input.user.role == "admin"
}
# Permitir acesso ao próprio perfil
allow {
input.method == "GET"
input.path == "/api/users/" + input.user.id
}
Testando a política via API:
# Requisição de decisão
curl -X POST http://localhost:8181/v1/data/api/authz/allow \
-d '{
"input": {
"method": "GET",
"path": "/api/admin/config",
"user": {
"id": "123",
"role": "admin",
"authenticated": true
}
}
}'
# Resposta: {"result": true}
4.3. Integração do OPA com aplicações via sidecar ou API REST
Em Kubernetes, o OPA pode rodar como sidecar no mesmo pod da aplicação:
# Configuração de sidecar no deployment
containers:
- name: app
image: minha-app:latest
- name: opa
image: openpolicyagent/opa:latest
args:
- "run"
- "--server"
- "--addr=:8181"
- "/policies/authz.rego"
A aplicação consulta o sidecar via localhost:8181.
5. Considerações de Desempenho e Escalabilidade
5.1. Otimização de consultas ao PDP
- Pré-calcular decisões: Para fluxos conhecidos, cacheie resultados.
- Reduzir atributos: Envie apenas atributos relevantes ao PDP.
- Usar índices: OPA suporta índices em regras para busca mais rápida.
5.2. Particionamento de políticas por domínio ou tenant
Para sistemas multi-tenant, cada inquilino pode ter seu próprio pacote de políticas:
package tenant_a.authz
package tenant_b.authz
O PDP decide qual pacote consultar baseado no tenant do usuário.
5.3. Monitoramento e logging de decisões
Habilite logs estruturados no OPA:
./opa run --server --addr :8181 --log-level debug --log-format json
Cada decisão gera um log com input, resultado e tempo de avaliação.
6. Segurança e Boas Práticas na Definição de Políticas
6.1. Prevenção de vazamento de informações
Evite expor dados sensíveis em mensagens de erro:
# Ruim: retorna motivo detalhado
deny["Usuário não tem cargo de gerente"] { ... }
# Bom: retorna negação genérica
default deny = false
6.2. Versionamento e testes de políticas
Testes unitários em Rego são essenciais:
package test.authz
test_admin_access {
allow with input as {"method": "GET", "path": "/api/admin", "user": {"role": "admin"}}
}
test_deny_regular_user {
not allow with input as {"method": "GET", "path": "/api/admin", "user": {"role": "user"}}
}
Execute com: opa test ./policies/
6.3. Controle de acesso ao próprio sistema de políticas
O PAP (Policy Administration Point) deve ser protegido com autenticação forte. Apenas administradores de segurança devem poder alterar políticas.
7. Casos de Uso e Exemplos Práticos
7.1. Autorização em microsserviços
Política centralizada para múltiplos serviços:
package gateway.authz
# Serviço de pedidos: apenas usuários com conta ativa
allow {
input.service == "orders"
input.user.status == "active"
}
# Serviço de pagamentos: apenas financeiro
allow {
input.service == "payments"
input.user.department == "finance"
}
7.2. Controle de acesso a dados sensíveis baseado em atributos contextuais
package data.access
allow {
input.action == "read_pii"
input.user.clearance >= 3
input.location.country == "BR"
time.clock(input.timestamp).hour >= 8
time.clock(input.timestamp).hour <= 18
}
7.3. Políticas dinâmicas para ambientes multi-tenant
package tenants
# Cada tenant tem regras próprias
allow {
input.tenant_id == "acme_corp"
input.user.role == "manager"
input.resource.type == "reports"
}
allow {
input.tenant_id == "startup_inc"
input.user.role == "developer"
input.resource.type == "logs"
}
Referências
- Open Policy Agent - Documentação Oficial — Guia completo de instalação, políticas em Rego e integração com Kubernetes.
- XACML 3.0 - OASIS Standard — Especificação formal do padrão XACML para autorização baseada em atributos.
- ALFA - Abbreviated Language for Authorization — Linguagem simplificada para escrever políticas XACML de forma legível.
- Policy-Based Access Control (PBAC) - NIST — Publicação do NIST sobre fundamentos e melhores práticas em PBAC.
- Rego Style Guide - OPA Community — Guia de estilo e boas práticas para escrever políticas em Rego.
- Implementing Authorization in Microservices - Styra — Artigo prático sobre como integrar OPA em arquiteturas de microsserviços.
- OPA Performance Tuning - CNCF — Dicas de otimização de desempenho para sistemas de autorização baseados em OPA.