Um agente é quem chama que você não consegue prever totalmente, e é exatamente esse tipo de chamador que deveria ter o menor privilégio. O instinto com um agente novo é dar a ele um papel amplo para que "simplesmente funcione" enquanto você itera. Esse instinto é como você acaba com um modelo de linguagem segurando credenciais que conseguem ler todo bucket e apagar toda tabela, guiado por texto que um atacante pode influenciar. Least privilege sempre foi a regra. Um chamador não determinístico torna isso inegociável.

A mudança de mentalidade é parar de pensar no agente como seu código e começar a pensar nele como um ator semiconfiável agindo em seu nome. Seu código faz o que você escreveu. Um agente faz o que o modelo decidiu, e o modelo decidiu com base em um input que você não controla. A fronteira de IAM é o que fica entre "o agente tomou uma decisão estranha" e "o agente tomou uma decisão estranha com privilégios de admin".

Um papel por ferramenta, não um papel por agente

O antipadrão comum é um único papel de execução anexado ao agente inteiro, carregando a união de toda permissão que qualquer ferramenta possa precisar. Esse papel agora é o raio de impacto de todas as ferramentas ao mesmo tempo. Uma prompt injection que alcança a ferramenta mais fraca herda as permissões da mais forte.

Delimite as permissões pela ferramenta, não pelo agente. A Lambda por trás de uma ferramenta lookup_order recebe um papel que pode ler uma tabela e nada mais. A função por trás de send_email recebe um papel que pode chamar o SES para uma única identidade verificada. Nenhuma ferramenta carrega uma permissão que não usa, então uma chamada de ferramenta comprometida só consegue fazer o único trabalho daquela ferramenta.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "dynamodb:GetItem",
    "Resource": "arn:aws:dynamodb:eu-west-1:111122223333:table/orders",
    "Condition": {
      "ForAllValues:StringEquals": {
        "dynamodb:LeadingKeys": ["${aws:PrincipalTag/tenant}"]
      }
    }
  }]
}

Essa é toda a permissão para a ferramenta de consulta de pedido: ler um item, de uma tabela, e só linhas do tenant de quem está chamando. Não há mais nada para uma instrução injetada alcançar.

Delimite ainda mais o papel em runtime com session policies

Papéis por ferramenta são o piso. Para sistemas multi-tenant, você também quer a permissão delimitada à solicitação específica. Session policies permitem isso: quando seu backend assume o papel da ferramenta, ele passa uma policy inline que intersecta com as permissões do papel para aquela única sessão, então uma solicitação agindo pelo tenant A não consegue tocar nos dados do tenant B mesmo que o papel tecnicamente abranja a tabela inteira.

aws sts assume-role \
  --role-arn arn:aws:iam::111122223333:role/order-lookup \
  --role-session-name agent-tenant-a \
  --policy '{"Version":"2012-10-17","Statement":[{
    "Effect":"Allow","Action":"dynamodb:GetItem",
    "Resource":"arn:aws:dynamodb:eu-west-1:111122223333:table/orders",
    "Condition":{"ForAllValues:StringEquals":
      {"dynamodb:LeadingKeys":["tenant-a"]}}}]}'

A permissão efetiva é a interseção entre o papel e a session policy, então as credenciais que a ferramenta de fato detém ficam delimitadas a essa solicitação. Session tags mais uma condição de tenant no papel alcançam a mesma coisa de forma declarativa. De qualquer forma, as credenciais entregues à chamada guiada pelo modelo são o menor conjunto que completa a tarefa atual.

Policy na frente das credenciais

IAM decide o que um principal pode fazer. Não decide se este agente em particular, neste turno em particular, deveria estar chamando esta ferramenta. Essa pergunta de autorização agora tem uma resposta feita sob medida na AWS: Policy no Amazon Bedrock AgentCore, geral geralmente disponível desde o início deste mês, avalia cada solicitação agente-para-ferramenta contra regras que você escreve em linguagem natural e que são compiladas para Cedar, aplicadas em um AgentCore Gateway antes que a chamada prossiga. Trate isso como uma camada na frente do IAM, não como um substituto: o gateway decide se a chamada de ferramenta é permitida, e um papel de IAM restrito decide o quão pouco dano ela pode causar se for.

Registre a assunção do papel, não só a chamada de API

Como as ferramentas assumem papéis delimitados, o CloudTrail te dá uma trilha de auditoria limpa: qual papel foi assumido, com qual nome de sessão, para qual tarefa. Defina o role-session-name como algo que se conecte de volta ao turno do agente e ao tenant, e você consegue reconstruir exatamente o que um agente fez e sob a autoridade de quem. Quando um agente se comporta mal, essa trilha é a diferença entre um incidente delimitado que você consegue explicar e um mistério que você não consegue.

A conclusão

Least privilege não relaxa porque quem chama é inteligente. Ele fica mais rígido, porque quem chama é não determinístico e influenciado por input não confiável. Dê a cada ferramenta seu próprio papel estreito, intersecte com uma session policy por solicitação, coloque uma camada de autorização como o AgentCore Policy na frente, e registre toda assunção de papel. Quando o modelo tomar uma decisão ruim, e ele vai tomar, o IAM é o que decide que a decisão ruim permaneça pequena.

Leia isto a seguir

O lado profundo do IAM e do harden de contas vive nas notas de campo de nuvem: como proteger sua conta AWS, em ercan.cloud. O hub está em ercanermis.com.