IAM Role cross-account no AWS: configuração passo a passo
Como configurar uma IAM Role cross-account com External ID para permitir que uma ferramenta externa faça análise read-only da sua conta AWS, sem entregar chave privada.
Compartilhar chave de acesso (AKIA...) com uma ferramenta externa é uma das práticas mais perigosas que ainda sobrevive em cloud. A chave vale pra sempre até ser rotacionada. Vaza em log, em variável de ambiente, chega no Git por acidente. A AWS tem uma resposta pra isso há mais de 15 anos: IAM Role cross-account.
A ideia é simples. Em vez de copiar uma credencial permanente pra fora, você cria uma Role na sua conta e autoriza outra conta (a da ferramenta) a assumi-la temporariamente. Quem usa a Role pega um token que expira em minutos, opera com as permissões mínimas que você definiu, e nunca toca em uma chave privada sua.
O guia abaixo é o passo a passo completo. O exemplo usa WiserOps como a ferramenta externa, mas a mecânica é idêntica pra qualquer SaaS que peça acesso à sua AWS.
O que você vai criar
Na sua conta AWS:
- Uma IAM Role chamada
WiserOpsReadOnly(nome livre). - Uma Trust Policy que autoriza a conta da WiserOps (
833073837959) a assumir a Role, exigindo um External ID único. - Uma ou duas managed policies anexadas:
ReadOnlyAccesse, se quiser cobertura completa de cost,job-function/Billing.
Depois você passa o ARN da Role e o External ID pra ferramenta, e acabou. Sem chave, sem secret, sem rotação manual.
Passo 1: gerar o External ID
O External ID é um segredo compartilhado entre você e a ferramenta. Protege contra o problema do confused deputy: mesmo que alguém descubra o ARN da sua Role, sem o External ID correto o sts:AssumeRole falha.
No WiserOps, quando você clica em "Conectar AWS", o painel gera um External ID único por organização. Copie o valor (algo como wops-a3f9b2...). Você vai usar na Trust Policy.
Um detalhe de segurança que vale a pena checar: External IDs devem ser únicos por cliente ou por contexto. Se uma ferramenta te der o mesmo External ID usado em 300 outros clientes, não é seguro. Peça um único pra sua organização.
Passo 2: criar a Role via CloudFormation (recomendado)
A forma mais rápida é CloudFormation Quick-Create, um link que já vem com o template pronto. Você preenche o External ID, clica "Create stack", acabou. Dois minutos.
O template cria exatamente três recursos:
Resources:
WiserOpsReadOnlyRole:
Type: AWS::IAM::Role
Properties:
RoleName: WiserOpsReadOnly
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
AWS: "arn:aws:iam::833073837959:root"
Action: "sts:AssumeRole"
Condition:
StringEquals:
"sts:ExternalId": !Ref ExternalId
ManagedPolicyArns:
- arn:aws:iam::aws:policy/ReadOnlyAccess
- arn:aws:iam::aws:policy/job-function/Billing
A Trust Policy é o coração da configuração. Ela permite apenas a conta WiserOps, apenas se o External ID bater. Qualquer outra tentativa falha com AccessDenied.
Passo 2b: criar manualmente (se preferir)
Se sua política interna não aceita CloudFormation de terceiro, dá pra criar na mão:
- Console AWS, IAM, Roles, Create role.
- Trusted entity: "Another AWS account", Account ID
833073837959. - Marque "Require external ID" e cole o valor.
- Anexe
ReadOnlyAccess(e opcionalmentejob-function/Billing). - Nome da Role:
WiserOpsReadOnly. - Create role.
No final, abra a Role recém-criada e copie o Role ARN (formato arn:aws:iam::SUA_CONTA:role/WiserOpsReadOnly).
Passo 3: conectar no painel
Volta no WiserOps, cola o Role ARN, clica "Validar". A ferramenta faz três chamadas em sequência:
sts:AssumeRole → token temporário (15min)
sts:GetCallerIdentity → confirma que a Role é acessível
iam:ListAccountAliases → confirma permissão read
Se as três passam, tá conectado. O primeiro scan dispara automaticamente.
Quando dá "AccessDenied"
Esse é o erro mais comum, e quase sempre significa uma de cinco coisas:
- A Trust Policy não autoriza a conta da ferramenta, ou seja, o Principal está errado. Verifique o account ID.
- O External ID não bate. Confirme o valor exato, espaços em branco extras quebram.
- A Role existe mas ainda não propagou. IAM tem uns 30 segundos de delay depois do Create, é só esperar.
- A conta da ferramenta foi autorizada, mas a Role não tem nenhuma policy anexada (então
GetCallerIdentitypassa eListAccountAliasesfalha). - Algum SCP no AWS Organizations está bloqueando. Verifique nas SCPs da sua OU.
No WiserOps, o botão "Verificar role" faz esse diagnóstico e devolve qual dos cinco falhou. Se a sua ferramenta só diz "AccessDenied genérico" sem desambiguar, pede suporte. Esse diagnóstico é o que separa uma hora de dor de um Slack rápido.
Revogação
Pra desconectar a qualquer momento, você não precisa avisar a ferramenta. Deleta a Role no IAM (ou remove as policies anexadas). O próximo sts:AssumeRole falha e a ferramenta perde acesso imediatamente. Zero cerimônia.
Por que isso é padrão de mercado
Cross-account Role com External ID é o padrão recomendado pela própria AWS, pelo NIST, pelo CIS Benchmark, e é o que praticamente toda ferramenta cloud-native séria usa (Wiz, Prowler, Vanta, Drata, Datadog, WiserOps). Quando uma ferramenta ainda pede AKIA + Secret Access Key, é sinal vermelho. Ou o produto é antigo, ou alguém tá cortando caminho em segurança. Você não quer nem um, nem outro.
No WiserOps, o setup inteiro leva dois minutos via CloudFormation Quick-Create. Zero chave privada saindo da AWS, zero chance de vazar. Começa grátis.