Tornando o Acesso Cross-Account Mais Seguro e Gerenciável com ABAC
Já faz algum tempo que eu tirei a minha certificação AWS Security Specialty. Naquela época, aprofundando nos estudos para a prova, conheci uma excelente estratégia para gerenciar acessos na AWS de uma maneira bem simples, o Attribute-Based Access Control (ABAC).
Como Funciona
Como o nome diz, ele se baseia em controlar acessos utilizando-se de atributos da entidade que tenta acessar aquele recurso.
Na AWS, esse conceito de atributo é materializado através das tags, que são os metadados de um recurso, em formato chave-valor. A tag Name, por exemplo, é o que define o que vai ser exibido como o nome do recurso no Console.
No que diz respeito a controle de acesso, as tags serão usadas para estabelecer a condição que garante o acesso do usuário ao recurso.
Vejamos abaixo uma representação visual, onde temos 3 tipos de usuários de diferentes equipes, cada um possuindo acesso a recursos que competem a sua jurisdição:
- Infraestrutura
Team=Infrastructure(Tag Vermelha)- Acesso a instâncias EC2 e gerenciamento de políticas.
- Dados
Team=Data(Tag Azul)- Acesso aos buckets S3 da conta e painéis analíticos.
- Desenvolvedor
Team=Dev(Tag Verde)- Acesso à sua aplicação, rodando no ECS e ao File System por ela utilizado.

Créditos da Imagem: https://aws.amazon.com/blogs/security/control-access-to-amazon-elastic-container-service-resources-by-using-abac-policies/
Apesar de simples, as tags são extremamente úteis para gerenciar recursos na nuvem, estabelecer a relação semântica entre eles e até filtrar custos, utilizando a feature de Cost Allocation Tags.
Minha Aplicação Prática do ABAC
Assim que tive conhecimento desta estratégia, vi que ela encaixava muito bem no dia a dia do meu ambiente de trabalho, onde costumávamos lidar com a necessidade da edição manual da Trust Relationship da role de acesso dos clientes (sim, diversos clientes).
Funcionava da seguinte forma:
- Tínhamos uma role
solution-provider-infra-accessna conta do cliente. - Essa role continha uma Trust Relationship que seguia o seguinte exemplo, listando todos os usuários da equipe de infraestrutura que precisavam assumir aquela role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::123456789012:user/fulano",
"arn:aws:iam::123456789012:user/cicrano",
"arn:aws:iam::123456789012:user/beltrano"
]
},
"Action": "sts:AssumeRole"
}
]
}
-
O problema é que, se a equipe tivesse um novo membro, essa política precisava ser atualizada... Nos cento e tantos clientes que possuíam essa mesma policy.
-
Tínhamos aí um problema grave de inconsistência, com a necessidade da policy ser atualizada conforme o novo membro acessava as contas.
Para destravar esse processo, desenhei uma nova versão, pensada da seguinte forma:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAssumptionByInfrastructureTaggedPrincipals",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true"
},
"StringEquals": {
"aws:PrincipalTag/Team": "Infrastructure"
}
}
}
]
}
A definição acima permite que qualquer Principal (entidade) da conta de ID 123456789012 tenha acesso, desde que ambas condições sejam verdadeiras:
- Tenha a tag
Teamcom o valorInfrastructure. - Tenha se autenticado com MFA na sessão atual.
Ao apresentar minha ideia para a gestão, houve uma certa dúvida inicial quanto a questões de auditoria, sendo solicitados alguns testes iniciais para comprovar a segurança e a confiabilidade desta solução.
Após comprovar, em uma conta de teste, que o acesso era mais prático e não prejudicava a auditoria (todas as ações continuavam registradas no CloudTrail), adotamos a estratégia e atualizamos as Trust Relationships pela última vez.
Controlando a Escalação de Privilégios
Mesmo com essa solução, ainda existe um risco: um usuário, em tese, poderia escalar privilégios se conseguisse adicionar a tag Team com o valor Infrastructure à sua própria entidade.
Para mitigar esse risco, é importante garantir que apenas administradores possam adicionar ou modificar tags sensíveis.
Isso pode ser feito com uma SCP (Service Control Policy), um recurso do AWS Organizations que limita o que as identidades de uma conta podem fazer, mesmo as administrativas. Essa é uma política aplicada a partir da conta gerenciadora do Organizations, ou seja, ninguém consegue remover a política tendo apenas acesso à conta onde o usuário está. Use uma política que negue explicitamente a alteração da tag Team, como no exemplo abaixo:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyTeamTagChangesExceptAdmins",
"Effect": "Deny",
"Action": [
"iam:TagUser",
"iam:TagRole",
"iam:UntagUser",
"iam:UntagRole",
"sts:TagSession"
],
"Resource": "*",
"Condition": {
"ForAnyValue:StringEquals": {
"aws:TagKeys": ["Team"]
},
"ArnNotLike": {
"aws:PrincipalARN": "arn:aws:iam::*:role/iam-admin"
}
}
}
]
}
A política acima nega qualquer tentativa de alteração da tag
Teampor qualquer entidade que não seja a role administradora do IAM (nesse exemplo, a roleiam-admin).
Para quem achou interessante e quer aplicar de sua própria maneira, recomendo a leitura da documentação oficial da AWS sobre o ABAC, disponível aqui.