Si vous construisez des agents sur AWS dans un secteur régulé, votre équipe sécurité a probablement imposé une permissions boundary IAM sur chaque rôle que vous créez. La mienne s’appelle BoundaryForLPMA — la vôtre porte peut-être un autre nom. Le principe est le même : même avec des credentials admin, vous ne pouvez pas sortir de ce que la boundary autorise.

Bedrock AgentCore est un magnifique service dans un compte vierge. Dans un compte d’entreprise contraint par une boundary, c’est une suite de casse-têtes IAM que la documentation ne relie pas pour vous. Après avoir déployé AgentCore Runtime, Memory, Gateway, Evaluations, Registry et l’accès cross-account sous une boundary LPMA, voici les patterns que j’aurais aimé lire avant de commencer.

Pattern 1 — Le nommage des rôles est votre garde-barrière

La plupart des rôles contraints par une boundary ne délèguent la création de rôles à votre équipe que si le nom du rôle commence par un préfixe précis. Dans mon univers, c’est LPMA_*. Si vous essayez d’appeler iam:CreateRole pour un rôle nommé CrossAccount-BedrockAgent-FromProd, vous obtenez un AccessDenied qui ne mentionne pas la règle de nommage. La boundary sur votre rôle créateur d’IAM limite iam:CreateRole par Resource: arn:aws:iam::*:role/LPMA_*, et vous ne voyez pas la condition.

Convention que j’utilise désormais systématiquement :

  • Rôle d’exécution du runtime : LPMA_<App>_AgentCoreRuntime
  • Rôle de la Lambda dispatcher : LPMA_<App>_AlertDispatcher
  • Rôle d’exécution des évaluations : LPMA_<App>_EvaluationExecution
  • Invocateur cross-account (un nouveau rôle, pas un réutilisé) : LPMA_<App>_CrossAccount<Purpose>

Choisissez un identifiant de projet (<App>) et tenez-vous-y sur tous les rôles, files, secrets, runtimes.

Pattern 2 — iam:PassRole vers le principal de service AgentCore est généralement bloqué

La politique de boundary sur un rôle d’entreprise typique n’autorise iam:PassRole que vers une liste triée sur le volet de principaux de service : ec2.amazonaws.com, lambda.amazonaws.com, ecs-tasks.amazonaws.com, etc. Le principal de service AgentCore bedrock-agentcore.amazonaws.com y figure rarement.

Conséquence pratique : un CD automatisé qui crée le runtime via votre CI ne peut pas passer le rôle d’exécution. Vous devez soit :

  • Faire passer le rôle une seule fois par quelqu’un disposant de droits élevés, hors boundary ; ensuite le runtime existe et la CI se contente de lancer UpdateAgentRuntime dessus (ce qui n’a pas besoin de PassRole).
  • Soit demander à la sécurité d’ajouter bedrock-agentcore.amazonaws.com à la whitelist PassRole de la boundary.

J’ai choisi l’option 1. La CI ne crée jamais un runtime de zéro — elle fait toujours passer un runtime existant vers une nouvelle image. Le runtime lui-même est provisionné via un script à droits élevés, exécuté une seule fois.

Pattern 3 — Recréer un runtime, c’est une mise à jour à deux endroits

Si vous supprimez puis recréez un runtime (par ex. pour migrer de direct_code_deploy vers un artefact conteneur), l’ID du runtime change. Deux endroits doivent être mis à jour ensemble :

  1. La variable d’environnement de la Lambda (ou là où le code consommateur stocke l’ARN) — facile, facile à retenir.
  2. La politique IAM du rôle qui invoque le runtime, où l’ARN du runtime est restreint dans Resource. Celle-là, on l’oublie facilement, et le symptôme est un AccessDenied sur un runtime qui tourne parfaitement, des heures après avoir cru en avoir fini.

J’ai perdu une heure là-dessus. Maintenant, je traite la recréation d’un runtime comme une triple action : variables d’env + politique IAM + smoke test.

Pattern 4 — La policy de la clé KMS doit autoriser explicitement chaque service qui l’utilise

Les environnements de comptes régulés exigent souvent une CMK KMS dédiée au projet sur Secrets Manager, les topics SNS, les files SQS, les logs CloudWatch, les buckets S3. La policy de la clé CMK doit autoriser chaque principal de service à utiliser la clé, restreint à votre projet.

Un pattern qui marche bien pour une famille de ressources <app>-* :

{
  "Sid": "AllowSNSUsage",
  "Effect": "Allow",
  "Principal": { "Service": "sns.amazonaws.com" },
  "Action": ["kms:GenerateDataKey", "kms:Decrypt", "kms:DescribeKey"],
  "Resource": "*",
  "Condition": {
    "StringEquals": { "aws:SourceAccount": "<your-account-id>" },
    "ArnLike": { "aws:SourceArn": "arn:aws:sns:<region>:<acct>:<app>-*" }
  }
}

Ajoutez un statement par service AWS pour lequel vous voulez que la CMK chiffre. Le scope aws:SourceArn est votre filet de sécurité contre le confused deputy. Sans ces statements, l’appel de création du topic SNS réussit, mais chaque Publish suivant échoue avec une erreur d’accès KMS.

Pattern 5 — La politique basée sur la ressource du runtime est le pattern cross-account le plus propre

Je ne vais pas répéter mon autre article, mais : quand l’appelant est dans un autre compte, la politique basée sur la ressource du runtime et de son endpoint vous évite de créer un rôle intermédiaire dans le compte propriétaire de la ressource. put-resource-policy est une action bedrock-agentcore-control, pas une action IAM — donc même sous une boundary qui bloque iam:CreateRole hors du namespace LPMA_*, vous pouvez attacher une politique de ressource sans négocier avec la sécurité.

Cela dit, l’ARN de ressource dans la politique de ressource doit être exact. Pas de wildcards. AgentCore valide et rejette.

Pattern 6 — Les permissions du plan de données Memory vivent dans une politique séparée

La politique d’identité du rôle d’exécution du runtime accorde généralement des actions de plan de contrôle comme bedrock-agentcore:CreateAgentRuntime. Les actions de plan de données sur Memory (bedrock-agentcore:CreateEvent, RetrieveMemoryRecords, ListEvents, etc.) sont une autre histoire. Vous les restreignez sur l’ARN de la memory de votre store :

{
  "Sid": "AgentCoreMemoryEvents",
  "Effect": "Allow",
  "Action": [
    "bedrock-agentcore:CreateEvent",
    "bedrock-agentcore:GetEvent",
    "bedrock-agentcore:ListEvents",
    "bedrock-agentcore:RetrieveMemoryRecords",
    "bedrock-agentcore:BatchCreateMemoryRecords",
    "bedrock-agentcore:BatchUpdateMemoryRecords",
    "bedrock-agentcore:BatchDeleteMemoryRecords"
  ],
  "Resource": "arn:aws:bedrock-agentcore:<region>:<acct>:memory/<memory-id>"
}

Si vous oubliez ça, votre agent tourne bien mais chaque écriture LTM échoue silencieusement avec un Parameter validation failed: AccessDenied que le SDK tronque. L’agent semble fonctionner, le store de mémoire reste vide, et vous ne le remarquez que des semaines plus tard, en essayant de l’interroger.

Pattern 7 — Le rôle d’exécution des Evaluations a son propre pattern de confiance

Si vous activez AgentCore Evaluations (le scoring de qualité par LLM-juge), le service a besoin d’un rôle à assumer pour lire vos traces, invoquer les modèles juges et écrire les résultats. La trust policy est :

{
  "Effect": "Allow",
  "Principal": { "Service": "bedrock-agentcore.amazonaws.com" },
  "Action": "sts:AssumeRole",
  "Condition": {
    "StringEquals": {
      "aws:SourceAccount": "<your-acct>",
      "aws:ResourceAccount": "<your-acct>"
    },
    "ArnLike": {
      "aws:SourceArn": [
        "arn:aws:bedrock-agentcore:<region>:<acct>:evaluator/*",
        "arn:aws:bedrock-agentcore:<region>:<acct>:online-evaluation-config/*"
      ]
    }
  }
}

Ce rôle nomme le service AgentCore comme principal, restreint aux ressources evaluator / online-eval-config de votre compte. Sous une boundary qui limite iam:CreateRole, vous en avez quand même besoin — et oui, le nom du rôle doit porter le préfixe conforme à la boundary.

Pattern 8 — Le chiffrement SNS n’est pas négociable

Si vous créez un topic SNS sans KmsMasterKeyId, votre scanner de sécurité (Prisma Cloud dans notre cas) le signale en HIGH dans l’heure. Attachez toujours le chiffrement KMS à la création, pas après. Le pattern que j’utilise désormais par programmation :

sns.create_topic(Name=name, Attributes={
    "KmsMasterKeyId": "<your-project-cmk-id>",
})

Plus le statement AllowSNSUsage sur la policy de la clé CMK (pattern 4).

Les cinq tags à ne jamais oublier

Chaque ressource reçoit ces cinq tags, sinon elle est signalée rétroactivement :

  • ApplicationId — l’UUID de votre application enregistrée dans le référentiel d’actifs de l’entreprise
  • Environmentpreprod / prod
  • Project — identifiant court du projet
  • ServiceLine — votre business unit
  • ManagedBy — en général l’identifiant de votre CI/CD ou de votre équipe plateforme

Si vous oubliez les tags sur un rôle IAM, le scanner de sécurité vous le dira. Si vous oubliez les tags sur le runtime Bedrock AgentCore, ça peut prendre plus de temps à se voir — et un tag manquant sur une ressource critique a déjà conduit à mettre des programmes en pause pour revue.

Deux détails au niveau du service

  • Le mode VPC est obligatoire pour tout MCP qui doit atteindre des systèmes on-prem via le TGW de l’entreprise. Le runtime peut aussi être PUBLIC, selon qu’il parle uniquement à des API AWS publiques ou à de l’on-prem.
  • requireServiceS3Endpoint ne peut pas être défini à la création de l’agent. Il se configure au niveau de l’organisation. L’API boto3 rejettera le paramètre avec une ValidationException. Laissez-le simplement hors de votre appel CreateAgentRuntime.

Le modèle mental qui relie tout

Les permissions boundaries ne sont pas votre ennemi. Ce sont une contrainte qui vous force à exprimer, dans le code, l’enveloppe de privilèges de votre application. Le coût est réel — un quart à une demi-journée de travail en plus la première fois que vous déployez AgentCore — mais le dividende, c’est un déploiement dont vous pouvez défendre la posture d’audit devant un comité de sécurité sans rien réécrire.

Les huit patterns ci-dessus couvrent ~90 % des frictions liées à la boundary que j’ai rencontrées. Les 10 % restants, c’était la négociation avec la sécurité pour ajouter bedrock-agentcore.amazonaws.com à la whitelist PassRole pour l’automatisation CI/CD. Ça vaut le coup d’insister.

Si vous démarrez un déploiement AgentCore dans un compte contraint par une boundary, épargnez-vous la course : nommez vos rôles LPMA_<App>_*, attachez KMS à la création sur tout, restreignez les actions de plan de données Memory sur l’ARN de la memory, et faites des politiques de ressource votre pattern cross-account préféré. Échangeons.