A definição NIST: f(S, R, A, E)
ABAC (Attribute-Based Access Control) foi formalizado pelo NIST em SP 800-162 (Guide to Attribute Based Access Control Definition and Considerations, 2014). O modelo é uma generalização: access = function(attributes), onde os atributos se distribuem em quatro categorias canônicas.
AWS IAM já é ABAC desde o dia zero. Os blocos em IAM policies (, , ) são atributos de S/R/E avaliados em runtime.
Arquitetura PEP/PDP/PIP/PAP
XACML: o padrão verboso (e por que ninguém usa em greenfield)
XACML 3.0 (OASIS, 2013) é o padrão formal de ABAC. Define linguagem XML para policies, request/response, combining algorithms (deny-overrides, permit-overrides, first-applicable). É excelente teoricamente — péssimo na prática.
<!-- Policy XACML: "permitir leitura se department == owner.department" -->
<Policy PolicyId="dept-match"
RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:permit-overrides">
<Target>
<AnyOf>
<AllOf>
<Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">read</AttributeValue>
<AttributeDesignator
Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action"
AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id"
DataType="http://www.w3.org/2001/XMLSchema#string"
MustBePresent="true"/>
</Match>
</AllOf>
</AnyOf>
</Target>
<Rule RuleId="dept-equal" Effect="Permit">
<Condition>
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<AttributeDesignator Category=".../subject" AttributeId="department"
DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"/>
<AttributeDesignator Category=".../resource" AttributeId="owner-department"
DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"/>
</Apply>
</Condition>
</Rule>
</Policy>Essa policy de 25 linhas resolve uma regra ("department match"). Em Rego, são 2 linhas. Em Cedar, 1. Por isso XACML caiu — não pela teoria, pela ergonomia.
# Mesma regra em Rego (OPA) — 2 linhas reais
package authz
allow {
input.action == "read"
input.subject.department == input.resource.owner.department
}Atributos: estáticos, dinâmicos, derivados
| Tipo | Fonte | Exemplo | Cuidado |
|---|---|---|---|
| Estático | cadastro (LDAP, DB) | department, clearance | invalidação ao mudar — sincronização cara |
| Dinâmico (env) | request context | IP, time, geo, channel | spoofable se vindo do client — valide no edge |
| Derivado (PIP) | computado em runtime | is_oncall, project_member | latência adicional — cachear com TTL curto |
| Reivindicado (JWT) | claims no token | mfa_amr, groups | só vale se token assinado e fresh; cuidado com rotação |
ABAC na prática com AWS IAM (você já usa)
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucket/*",
"Condition": {
"StringEquals": {
"aws:PrincipalTag/Department": "${s3:ResourceTag/Department}"
},
"Bool": { "aws:MultiFactorAuthPresent": "true" },
"DateGreaterThan": { "aws:CurrentTime": "2026-01-01T00:00:00Z" },
"IpAddress": { "aws:SourceIp": "10.0.0.0/8" }
}
}]
} Note os quatro atributos NIST em ação: Subject (aws:PrincipalTag), Resource (s3:ResourceTag), Action (s3:GetObject), Environment (MFA, CurrentTime, SourceIp). É ABAC textbook, escondido sob JSON da AWS.
Combining algorithms
Quando múltiplas policies se aplicam, qual vence? Algoritmos canônicos:
Default deny é regra: na ausência de policy que permita, negue. Implícito em AWS IAM, OPA (com ), Cedar. Nunca confie em "permit-overrides com fallback".
Onde ABAC brilha vs onde falha
📋 Política: 'engineer pode acessar logs de produção fora do horário comercial APENAS com MFA fresca'
RBAC não tem como expressar 'fora do horário' nem 'MFA fresca' — seria role para cada combinação. ReBAC modela relações, não condições. ABAC com 3 linhas de Rego resolve.
Alt: RBAC —
Alt: ABAC —
Alt: ReBAC —
ABAC falha em outro cenário: "quem tem acesso a este documento?". Em RBAC/ReBAC isso é uma query enumerável. Em ABAC, exige simular a policy contra todos os usuários (caro, não escalável). É o "reverse query problem" — solucionado em ferramentas como OpenFGA (que combina ReBAC + ABAC) ou IAM Access Analyzer (AWS).
Modelo híbrido: RBAC + ABAC (o que produção real faz)
package authz
# Default deny
default allow := false
# Camada RBAC: role admin tem acesso total
allow {
"admin" in input.subject.roles
}
# Camada ABAC: editor pode editar se for owner do recurso
allow {
"editor" in input.subject.roles
input.action == "update"
input.resource.owner_id == input.subject.id
}
# Camada ABAC: viewer só lê e só dentro do horário comercial
allow {
"viewer" in input.subject.roles
input.action == "read"
business_hours
}
business_hours {
hour := time.clock(time.now_ns())[0]
hour >= 9
hour < 18
} Padrão maduro: RBAC para o "quem é" coarse (role:admin/editor/viewer), ABAC para condições refinadas. Implementado em OPA, mantido como código em git, testado com opa test.
Auditoria: o calcanhar de Aquiles do ABAC
Compliance pergunta: "Liste todos os usuários que poderiam ter acessado este recurso entre 2026-01 e 2026-02". Em RBAC isso é JOIN. Em ABAC, depende do estado dos atributos naquele intervalo — historicidade obrigatória.
- Log all decisions: cada decisão PDP em append-only log (S3 + Athena, Loki). Inclua a versão da policy.
- Versione policies em Git: cada alteração com PR + review. AWS Verified Permissions e OPA bundle suportam isso nativamente.
- Snapshot de atributos: ao logar a decisão, gravar os atributos avaliados (não só permit/deny). Sem isso, replay é impossível.
- Static analysis: ferramentas como em batch, Cedar policy analyzer, IAM Access Analyzer simulam "reverse queries".
Resumo executivo
- ABAC = NIST SP 800-162. Decisão = função sobre atributos de (Subject, Resource, Action, Environment).
- XACML é o padrão formal — verboso e fora de moda. Substituído por DSLs modernas: Rego, Cedar.
- PEP/PDP/PIP/PAP é a arquitetura canônica. Em produção: middleware + OPA sidecar + LDAP/DB + git.
- AWS IAM com já é ABAC clássico — você usa há anos sem dar nome.
- ABAC vence em condições dinâmicas (hora, MFA, cross-attribute match) e perde em sharing resource-level e reverse queries ("quem tem acesso?").
- Produção real usa híbrido: RBAC coarse + ABAC para refinamentos contextuais.