From 2b840092f5feea4927aafab462bc55a44cd34000 Mon Sep 17 00:00:00 2001 From: Tejas Kashinath Date: Thu, 26 Mar 2026 17:40:32 -0400 Subject: [PATCH 1/3] docs: add IAM permissions guide and policy files Add PERMISSIONS.md covering enterprise IAM setup for the AgentCore CLI, including admin setup instructions, CDK bootstrap configuration, permission boundaries, feature-based scoping, and a full action-by-action reference. Includes ready-to-use JSON policy documents for both the developer role and the CloudFormation execution role. --- docs/PERMISSIONS.md | 476 ++++++++++++++++++++ docs/policies/iam-policy-cfn-execution.json | 168 +++++++ docs/policies/iam-policy-user.json | 139 ++++++ 3 files changed, 783 insertions(+) create mode 100644 docs/PERMISSIONS.md create mode 100644 docs/policies/iam-policy-cfn-execution.json create mode 100644 docs/policies/iam-policy-user.json diff --git a/docs/PERMISSIONS.md b/docs/PERMISSIONS.md new file mode 100644 index 00000000..0bcf0f3c --- /dev/null +++ b/docs/PERMISSIONS.md @@ -0,0 +1,476 @@ +# IAM Permissions + +This guide covers how to configure AWS IAM for the AgentCore CLI. The first half is written for platform administrators +who provision roles and policies in environments where access is tightly controlled. The second half is a complete +action-by-action reference. Developers who just need to get unblocked can skip to +[What developers need](#what-developers-need). + +Ready-to-use policy documents are provided at [iam-policy-user.json](./policies/iam-policy-user.json) and +[iam-policy-cfn-execution.json](./policies/iam-policy-cfn-execution.json). + +## How the CLI uses AWS + +The CLI interacts with your AWS account in two fundamentally different ways, and understanding the distinction is the +key to setting up permissions correctly. + +**Direct API calls.** The CLI itself makes SDK calls for things like invoking agents, tailing logs, checking deployment +status, and managing credential providers. These calls use the developer's own IAM credentials, so those credentials +need the corresponding permissions. + +**CDK deployments.** When a developer runs `agentcore deploy`, the CLI uses AWS CDK to synthesize a CloudFormation +template and hand it off to the CloudFormation service. CloudFormation then assumes a separate IAM role (the "CFN +execution role") to actually create and manage the infrastructure: runtimes, gateways, ECR repositories, IAM roles for +the agents themselves, and so on. The developer's credentials are not used for this part. They only need permission to +assume the CDK bootstrap roles that kick off the deployment. + +This separation is what makes least-privilege feasible. Developers get a narrow policy for the SDK calls they make +directly, while the broad infrastructure permissions live on a role that only CloudFormation can assume. + +## Setting up permissions + +### 1. Developer policy (direct SDK calls + CDK role assumption) + +Attach this to every IAM user or role that will run AgentCore CLI commands. The provided +[iam-policy-user.json](./policies/iam-policy-user.json) covers everything. At a high level, it grants: + +- `sts:AssumeRole` on the four CDK bootstrap roles (deploy, file-publishing, image-publishing, lookup) +- `sts:GetCallerIdentity`, `cloudformation:DescribeStacks`, `tag:GetResources` for basic operations +- `bedrock-agentcore:Invoke*`, `bedrock-agentcore:Get*`, `bedrock-agentcore:List*` for invoking agents and checking + status +- Credential provider and token vault actions for `deploy` when the project uses identity features +- CloudWatch Logs, X-Ray, and Application Signals actions for `logs`, `traces`, and observability setup +- Bedrock actions for agent import and AI-assisted code generation (optional, see + [Scoping down by feature](#scoping-down-by-feature)) + +To create this policy: + +```bash +aws iam create-policy \ + --policy-name AgentCoreCLIUser \ + --policy-document file://docs/policies/iam-policy-user.json +``` + +Then attach it to your developer role or group: + +```bash +aws iam attach-role-policy \ + --role-name MyDeveloperRole \ + --policy-arn arn:aws:iam::ACCOUNT:policy/AgentCoreCLIUser +``` + +### 2. CloudFormation execution role (infrastructure provisioning) + +This is the role that CloudFormation assumes during `agentcore deploy` to create and update the actual infrastructure. +It is part of the CDK bootstrap stack (`CDKToolkit`) and is named `cdk-*-cfn-exec-role-*`. + +If your account uses the default CDK bootstrap, this role already has `AdministratorAccess` and you do not need to do +anything. + +If your organization scopes down the execution role (common in enterprise environments), you need to ensure it has +permissions for every resource type AgentCore deploys. The provided +[iam-policy-cfn-execution.json](./policies/iam-policy-cfn-execution.json) is a ready-to-use policy for this. It covers: + +- All `bedrock-agentcore:*` actions for runtime, memory, gateway, evaluator, and policy engine resources +- IAM role and policy management (CloudFormation creates execution roles for each deployed resource) +- S3 for CDK asset staging +- KMS for encryption keys +- ECR and CodeBuild for container-based builds +- Lambda for MCP Lambda compute and CDK custom resources +- CloudWatch Logs for log group management +- CloudFormation stack operations +- SSM Parameter Store for CDK bootstrap version lookups +- Secrets Manager for credential provider secret storage + +To create the scoped-down execution policy: + +```bash +aws iam create-policy \ + --policy-name AgentCoreCFNExecution \ + --policy-document file://docs/policies/iam-policy-cfn-execution.json +``` + +Then pass it to CDK bootstrap (see next section). + +## Bootstrapping CDK + +CDK needs to be bootstrapped once per account/region combination before the first `agentcore deploy`. The CLI normally +handles this automatically, but in locked-down environments an administrator may need to run it manually. + +Bootstrap creates a `CDKToolkit` CloudFormation stack containing several IAM roles: + +| Bootstrap Role | Purpose | +| ------------------------------- | -------------------------------------------------------------- | +| `cdk-*-deploy-role-*` | Assumed by the CLI user to trigger deployments | +| `cdk-*-cfn-exec-role-*` | Assumed by CloudFormation to create/update/delete resources | +| `cdk-*-file-publishing-role-*` | Assumed by the CLI to upload code assets to S3 | +| `cdk-*-image-publishing-role-*` | Assumed by the CLI to push container images to ECR | +| `cdk-*-lookup-role-*` | Assumed by the CLI to look up VPCs, AZs, etc. during synthesis | + +CloudFormation assumes the CFN execution role to provision infrastructure, not your user's credentials. This means your +IAM principal only needs `sts:AssumeRole` on the bootstrap roles, plus permissions for the direct SDK calls. The broad +infrastructure permissions (creating IAM roles, ECR repos, Lambda functions, etc.) live on the CFN execution role +instead. + +### Default bootstrap (quick start) + +By default, CDK bootstrap grants `AdministratorAccess` to the CFN execution role. In this configuration CloudFormation +can create any resource, and you only need the [user permissions](#user-permissions) listed below. + +```bash +npx cdk bootstrap aws://ACCOUNT_ID/REGION +``` + +### Scoped-down bootstrap (enterprise) + +Organizations often restrict the CFN execution role to a least-privilege policy. If your account does this, the +execution role must include permissions for every resource type that AgentCore deploys. See +[CFN execution role permissions](#cfn-execution-role-permissions) for the full list. + +To restrict the CFN execution role to only the permissions AgentCore requires, pass a custom policy during bootstrap: + +```bash +npx cdk bootstrap aws://ACCOUNT_ID/REGION \ + --cloudformation-execution-policies arn:aws:iam::ACCOUNT_ID:policy/AgentCoreCFNExecution +``` + +If you need to update the execution policy later (for example, when a new AgentCore release introduces new resource +types), update the policy and re-run the bootstrap command. CDK bootstrap is idempotent. For full details, see the +[AWS CDK Bootstrap documentation](https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping-env.html). + +### Trust policy for the CDK bootstrap roles + +The CDK bootstrap roles need to be assumable by your developers. By default, bootstrap configures them to trust the +entire account. If your organization restricts trust policies, ensure the four bootstrap roles (`cdk-*-deploy-role-*`, +`cdk-*-file-publishing-role-*`, `cdk-*-image-publishing-role-*`, `cdk-*-lookup-role-*`) have a trust policy that allows +your developer roles to assume them: + +```json +{ + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::ACCOUNT_ID:role/MyDeveloperRole" + }, + "Action": "sts:AssumeRole" +} +``` + +## Scoping down by feature + +The policy files provided cover every AgentCore feature. If your team only uses a subset, you can remove the +corresponding statements to further tighten the policies. This table maps features to the policy statements that can be +safely removed: + +| If your team does not use... | Remove from user policy | Remove from CFN execution policy | +| ------------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | +| Container builds (CodeZip only) | _(no change)_ | `EcrContainerBuilds`, `CodeBuildContainerBuilds` | +| MCP Lambda compute | _(no change)_ | `LambdaMcpAndCustomResources` (keep if using container builds, which need Lambda for custom resources) | +| Agent import from Bedrock | `BedrockAgentImport` | _(no change)_ | +| AI-assisted code generation | `BedrockModelInvocation` | _(no change)_ | +| Identity/credential providers | `IdentityCredentialManagement`, `TokenVaultKmsKeyCreation` | `SecretsManagerForCredentials` | +| Policy engine | `PolicyGeneration` | Remove `*PolicyEngine*` and `*Policy` actions from `BedrockAgentCoreResources` | +| Online evaluations | Remove `UpdateOnlineEvaluationConfig` from `AgentCoreResourceStatus` | Remove `*OnlineEvaluationConfig*` actions from `BedrockAgentCoreResources` | + +## Permission boundaries + +If your organization uses +[IAM permission boundaries](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html), there are +two places they can come into play. + +**On the developer's role.** The developer policy from [iam-policy-user.json](./policies/iam-policy-user.json) defines +the maximum set of actions a developer needs. You can use this as both the identity policy and the permissions boundary, +or create a broader boundary and use the policy for the effective permissions. The critical thing is that +`sts:AssumeRole` on the CDK bootstrap roles must be allowed through the boundary, otherwise deployments will fail. + +**On roles that CloudFormation creates.** During `agentcore deploy`, CloudFormation creates execution roles for +runtimes, gateways, memory stores, and other resources. If your organization requires that all IAM roles have a +permissions boundary attached, you will need to ensure the CFN execution role has `iam:PutRolePermissionsBoundary` +permission, and the CDK constructs in your project pass the boundary ARN to the created roles. Currently, AgentCore's +CDK constructs create roles with inline policies scoped to the specific resource. These roles are not given permission +boundaries by default. + +## What developers need + +If you are a developer (not an admin setting up the account), here is what you need to get started: + +1. **AWS credentials** configured in your environment (`aws configure`, environment variables, or SSO). Your admin + should have attached the AgentCore user policy to your IAM role. + +2. **CDK bootstrap** must have been run in your target account and region. If you see an error about the `CDKToolkit` + stack not existing when you run `agentcore deploy`, ask your admin to bootstrap the account or do it yourself if you + have the required permissions. + +3. **That's it.** The CLI handles the rest. Run `agentcore create` to start a new project and `agentcore deploy` to ship + it. + +## Troubleshooting + +**"Access Denied" on `sts:AssumeRole` during deploy.** The developer's policy is missing the CDK bootstrap role +assumption statement, or the bootstrap roles have a trust policy that does not include the developer's role. Check both +sides. + +**"Access Denied" during CloudFormation stack creation/update.** The CFN execution role is scoped down but missing a +required permission. Check the `DescribeStackEvents` output to see which specific API call failed, then add it to the +execution policy and re-bootstrap. + +**"CDKToolkit stack not found."** CDK has not been bootstrapped in this account/region. Run `cdk bootstrap` (or ask your +admin to) as described above. + +**Deploy succeeds but `invoke` fails with "Access Denied".** The developer policy is missing the +`bedrock-agentcore:InvokeAgentRuntime` action (or `InvokeAgentRuntimeForUser` if passing a user ID). Update the user +policy. + +**KMS key creation fails during deploy.** If the project uses identity/credential features, the CLI creates a KMS key +for the token vault. The developer policy needs `kms:CreateKey` and `kms:TagResource`. If your organization restricts +KMS key creation, have an admin pre-create the key and configure it via the token vault settings. + +--- + +# Permissions Reference + +The tables below list every IAM action the CLI requires, organized by category. Each entry notes which CLI commands use +the action and why. + +## User permissions + +These permissions are required on your IAM principal (user or role). They cover everything the CLI calls directly, +outside of CloudFormation. + +### CDK bootstrap role assumption + +Required for all deployment operations (`deploy`, `status`, `diff`). + +| Action | Resource | +| ---------------- | --------------------------------------------------- | +| `sts:AssumeRole` | `arn:aws:iam::*:role/cdk-*-deploy-role-*` | +| `sts:AssumeRole` | `arn:aws:iam::*:role/cdk-*-file-publishing-role-*` | +| `sts:AssumeRole` | `arn:aws:iam::*:role/cdk-*-image-publishing-role-*` | +| `sts:AssumeRole` | `arn:aws:iam::*:role/cdk-*-lookup-role-*` | + +### Core + +| Action | CLI Commands | Purpose | +| ------------------------------- | ------------------------------------ | -------------------------------------------------- | +| `sts:GetCallerIdentity` | All | Validate AWS credentials, resolve account ID | +| `cloudformation:DescribeStacks` | `deploy`, `status` | Check bootstrap status, stack status, read outputs | +| `tag:GetResources` | `status`, `deploy`, `invoke`, `logs` | Discover deployed stacks by project tags | + +### Agent invocation + +| Action | CLI Commands | Purpose | +| --------------------------------------------- | ------------ | ----------------------------------------------------------------------------------------- | +| `bedrock-agentcore:InvokeAgentRuntime` | `invoke` | Invoke deployed agents (HTTP, MCP, and A2A protocols) | +| `bedrock-agentcore:InvokeAgentRuntimeForUser` | `invoke` | Invoke agents with a user ID (requires `X-Amzn-Bedrock-AgentCore-Runtime-User-Id` header) | +| `bedrock-agentcore:StopRuntimeSession` | `invoke` | End an agent runtime session | + +### Runtime and resource status + +| Action | CLI Commands | Purpose | +| --------------------------------------------- | --------------------- | ------------------------------------- | +| `bedrock-agentcore:GetAgentRuntime` | `status` | Check agent runtime deployment status | +| `bedrock-agentcore:ListGatewayTargets` | `status` | Check MCP gateway target sync status | +| `bedrock-agentcore:GetEvaluator` | `status`, `run evals` | Get evaluator details | +| `bedrock-agentcore:ListEvaluators` | `run evals` | List available evaluators | +| `bedrock-agentcore:GetOnlineEvaluationConfig` | `status` | Get online eval config status | + +### Evaluation + +| Action | CLI Commands | Purpose | +| ------------------------------------------------ | ----------------------------------------- | --------------------------------------------- | +| `bedrock-agentcore:Evaluate` | `run evals` | Run on-demand evaluation against agent traces | +| `bedrock-agentcore:UpdateOnlineEvaluationConfig` | `pause online-eval`, `resume online-eval` | Pause or resume online evaluation | + +### Identity and credential management + +| Action | CLI Commands | Purpose | +| -------------------------------------------------- | ------------ | ----------------------------------------- | +| `bedrock-agentcore:GetApiKeyCredentialProvider` | `deploy` | Check if API key provider exists | +| `bedrock-agentcore:CreateApiKeyCredentialProvider` | `deploy` | Create API key credential provider | +| `bedrock-agentcore:UpdateApiKeyCredentialProvider` | `deploy` | Update API key with new value | +| `bedrock-agentcore:GetOauth2CredentialProvider` | `deploy` | Check if OAuth2 provider exists | +| `bedrock-agentcore:CreateOauth2CredentialProvider` | `deploy` | Create OAuth2 credential provider | +| `bedrock-agentcore:UpdateOauth2CredentialProvider` | `deploy` | Update OAuth2 provider | +| `bedrock-agentcore:GetTokenVault` | `deploy` | Check token vault KMS configuration | +| `bedrock-agentcore:CreateTokenVault` | `deploy` | Create token vault for credential storage | +| `bedrock-agentcore:SetTokenVaultCMK` | `deploy` | Configure KMS encryption for token vault | +| `kms:CreateKey` | `deploy` | Create KMS key for token vault encryption | +| `kms:TagResource` | `deploy` | Tag the created KMS key | + +### Policy generation + +| Action | CLI Commands | Purpose | +| ---------------------------------------------- | ----------------- | -------------------------------- | +| `bedrock-agentcore:StartPolicyGeneration` | Policy generation | Start Cedar policy generation | +| `bedrock-agentcore:GetPolicyGeneration` | Policy generation | Poll generation status | +| `bedrock-agentcore:ListPolicyGenerationAssets` | Policy generation | Retrieve generated policy assets | + +### Logging, traces, and observability + +| Action | CLI Commands | Purpose | +| ------------------------------- | ---------------------------------------- | --------------------------------------------- | +| `logs:StartLiveTail` | `logs` | Stream agent logs in real-time | +| `logs:FilterLogEvents` | `logs` | Search agent logs | +| `logs:StartQuery` | `traces list`, `traces get`, `run evals` | Run CloudWatch Logs Insights queries | +| `logs:GetQueryResults` | `traces list`, `traces get`, `run evals` | Retrieve query results | +| `logs:DescribeResourcePolicies` | `deploy` | Check for X-Ray log resource policy | +| `logs:PutResourcePolicy` | `deploy` | Create resource policy for X-Ray trace access | + +### Transaction search setup + +Called during `deploy` to enable CloudWatch Transaction Search for tracing. + +| Action | CLI Commands | Purpose | +| ------------------------------------ | ------------ | ------------------------------------ | +| `application-signals:StartDiscovery` | `deploy` | Enable Application Signals discovery | +| `xray:GetTraceSegmentDestination` | `deploy` | Check current trace destination | +| `xray:UpdateTraceSegmentDestination` | `deploy` | Route traces to CloudWatch Logs | +| `xray:UpdateIndexingRule` | `deploy` | Set trace indexing sampling rate | + +### Bedrock agent import + +Only required when using `agentcore add agent --type import` to import an existing Bedrock Agent. + +| Action | CLI Commands | Purpose | +| --------------------------------- | ------------------------- | ----------------------------- | +| `bedrock:GetFoundationModel` | `add agent --type import` | Get model metadata | +| `bedrock:GetGuardrail` | `add agent --type import` | Get guardrail configuration | +| `bedrock:ListAgents` | `add agent --type import` | List Bedrock Agents in region | +| `bedrock:ListAgentAliases` | `add agent --type import` | List agent aliases | +| `bedrock:GetAgent` | `add agent --type import` | Get agent configuration | +| `bedrock:GetAgentAlias` | `add agent --type import` | Get alias details | +| `bedrock:ListAgentActionGroups` | `add agent --type import` | List agent action groups | +| `bedrock:GetAgentActionGroup` | `add agent --type import` | Get action group details | +| `bedrock:ListAgentKnowledgeBases` | `add agent --type import` | List knowledge bases | +| `bedrock:GetKnowledgeBase` | `add agent --type import` | Get knowledge base details | +| `bedrock:ListAgentCollaborators` | `add agent --type import` | List collaborator agents | +| `s3:GetObject` | `add agent --type import` | Fetch S3-stored API schemas | + +### Bedrock model invocation + +| Action | CLI Commands | Purpose | +| --------------------- | ----------------------- | --------------------------------------------- | +| `bedrock:InvokeModel` | `add` (code generation) | Invoke Claude for AI-assisted code generation | + +## CFN execution role permissions + +These permissions are needed on the CloudFormation execution role (`cdk-*-cfn-exec-role-*`), not on your user. If your +account uses the default CDK bootstrap with `AdministratorAccess`, this section is informational only. + +If your organization scopes down the execution role, include the following. Note that the provided +[iam-policy-cfn-execution.json](./policies/iam-policy-cfn-execution.json) uses `bedrock-agentcore:*` as a convenience so +you don't need to update the policy each time a new AgentCore resource type is added. The tables below list the specific +actions used today. + +### Bedrock AgentCore resources + +| Action | Resource Type Created | +| --------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | +| `bedrock-agentcore:CreateRuntime`, `UpdateRuntime`, `DeleteRuntime`, `GetRuntime` | `AWS::BedrockAgentCore::Runtime` | +| `bedrock-agentcore:CreateMemory`, `UpdateMemory`, `DeleteMemory`, `GetMemory` | `AWS::BedrockAgentCore::Memory` | +| `bedrock-agentcore:CreateGateway`, `UpdateGateway`, `DeleteGateway`, `GetGateway` | `AWS::BedrockAgentCore::Gateway` | +| `bedrock-agentcore:CreateGatewayTarget`, `UpdateGatewayTarget`, `DeleteGatewayTarget`, `GetGatewayTarget` | `AWS::BedrockAgentCore::GatewayTarget` | +| `bedrock-agentcore:CreateEvaluator`, `UpdateEvaluator`, `DeleteEvaluator`, `GetEvaluator` | `AWS::BedrockAgentCore::Evaluator` | +| `bedrock-agentcore:CreateOnlineEvaluationConfig`, `UpdateOnlineEvaluationConfig`, `DeleteOnlineEvaluationConfig`, `GetOnlineEvaluationConfig` | `AWS::BedrockAgentCore::OnlineEvaluationConfig` | +| `bedrock-agentcore:CreatePolicyEngine`, `UpdatePolicyEngine`, `DeletePolicyEngine`, `GetPolicyEngine` | `AWS::BedrockAgentCore::PolicyEngine` | +| `bedrock-agentcore:CreatePolicy`, `UpdatePolicy`, `DeletePolicy`, `GetPolicy` | `AWS::BedrockAgentCore::Policy` | + +### IAM + +| Action | Purpose | +| ---------------------------------------------------------------- | ------------------------------------------------------------ | +| `iam:CreateRole`, `iam:DeleteRole`, `iam:GetRole` | Execution roles for runtimes, memories, gateways, evaluators | +| `iam:PassRole` | Allow services to assume created roles | +| `iam:PutRolePolicy`, `iam:DeleteRolePolicy`, `iam:GetRolePolicy` | Inline policies on execution roles | +| `iam:AttachRolePolicy`, `iam:DetachRolePolicy` | Managed policies (e.g., `AWSLambdaBasicExecutionRole`) | +| `iam:TagRole`, `iam:UpdateAssumeRolePolicy` | Role tagging and trust policy updates | + +### S3 (CDK asset staging) + +| Action | Purpose | +| ----------------------------------------------------------------- | -------------------------- | +| `s3:CreateBucket`, `s3:PutBucketPolicy`, `s3:PutBucketVersioning` | Bootstrap bucket setup | +| `s3:PutEncryptionConfiguration`, `s3:PutLifecycleConfiguration` | Bucket configuration | +| `s3:PutBucketPublicAccessBlock` | Security configuration | +| `s3:GetBucketLocation`, `s3:GetObject`, `s3:PutObject` | Asset upload and retrieval | +| `s3:ListBucket`, `s3:DeleteObject` | Asset management | + +### KMS + +| Action | Purpose | +| --------------------------------------------------------------------- | ------------------------------------ | +| `kms:CreateKey`, `kms:CreateAlias`, `kms:DescribeKey` | Encryption keys for ECR repos and S3 | +| `kms:PutKeyPolicy`, `kms:GetKeyPolicy` | Key policy management | +| `kms:Encrypt`, `kms:Decrypt`, `kms:GenerateDataKey` | Cryptographic operations | +| `kms:TagResource`, `kms:ScheduleKeyDeletion`, `kms:EnableKeyRotation` | Key lifecycle | + +### CloudFormation + +| Action | Purpose | +| ----------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | +| `cloudformation:CreateStack`, `cloudformation:UpdateStack`, `cloudformation:DeleteStack` | Stack lifecycle | +| `cloudformation:DescribeStacks`, `cloudformation:DescribeStackEvents` | Stack status | +| `cloudformation:GetTemplate` | Template retrieval | +| `cloudformation:CreateChangeSet`, `cloudformation:ExecuteChangeSet`, `cloudformation:DeleteChangeSet`, `cloudformation:DescribeChangeSet` | Change set operations | +| `cloudformation:ListStacks` | Stack discovery | + +### SSM Parameter Store + +| Action | Purpose | +| ------------------- | --------------------------------------------------------- | +| `ssm:GetParameters` | CDK bootstrap version lookup (`/cdk-bootstrap/*/version`) | + +### ECR (container builds only) + +| Action | Purpose | +| ------------------------------------------------------------------------------------------- | ------------------------ | +| `ecr:CreateRepository`, `ecr:DeleteRepository`, `ecr:DescribeRepositories` | Repository lifecycle | +| `ecr:GetAuthorizationToken` | Docker authentication | +| `ecr:BatchGetImage`, `ecr:BatchCheckLayerAvailability`, `ecr:GetDownloadUrlForLayer` | Image pull | +| `ecr:PutImage`, `ecr:InitiateLayerUpload`, `ecr:UploadLayerPart`, `ecr:CompleteLayerUpload` | Image push | +| `ecr:SetRepositoryPolicy`, `ecr:PutLifecyclePolicy`, `ecr:PutImageScanningConfiguration` | Repository configuration | +| `ecr:TagResource` | Tagging | + +### CodeBuild (container builds only) + +| Action | Purpose | +| -------------------------------------------------------------------------------- | ----------------------- | +| `codebuild:CreateProject`, `codebuild:DeleteProject`, `codebuild:UpdateProject` | Build project lifecycle | +| `codebuild:StartBuild`, `codebuild:BatchGetBuilds`, `codebuild:BatchGetProjects` | Build execution | + +### Lambda (MCP Lambda compute and container build orchestration) + +| Action | Purpose | +| ----------------------------------------------------------------- | ---------------------------------- | +| `lambda:CreateFunction`, `lambda:DeleteFunction` | Function lifecycle | +| `lambda:UpdateFunctionCode`, `lambda:UpdateFunctionConfiguration` | Function updates | +| `lambda:GetFunction`, `lambda:GetFunctionConfiguration` | Function reads | +| `lambda:InvokeFunction` | Custom resource handler invocation | +| `lambda:AddPermission`, `lambda:RemovePermission` | Resource-based policies | +| `lambda:TagResource` | Tagging | + +### CloudWatch Logs + +| Action | Purpose | +| --------------------------------------------------- | ----------------------- | +| `logs:CreateLogGroup`, `logs:DeleteLogGroup` | Log group lifecycle | +| `logs:CreateLogStream`, `logs:PutLogEvents` | Log writing | +| `logs:DescribeLogGroups`, `logs:PutRetentionPolicy` | Log group configuration | +| `logs:TagResource` | Tagging | + +### Secrets Manager + +| Action | Purpose | +| ---------------------------------------------------------------- | ----------------------------------------- | +| `secretsmanager:CreateSecret`, `secretsmanager:DeleteSecret` | Secret lifecycle for credential providers | +| `secretsmanager:DescribeSecret`, `secretsmanager:GetSecretValue` | Secret reads | +| `secretsmanager:PutSecretValue` | Secret writes | +| `secretsmanager:TagResource` | Tagging | + +## Policy JSON files + +Ready-to-use IAM policy documents are provided alongside this guide: + +- [iam-policy-user.json](./policies/iam-policy-user.json) -- Attach to your IAM user or role. Covers all direct SDK + calls and CDK bootstrap role assumption. +- [iam-policy-cfn-execution.json](./policies/iam-policy-cfn-execution.json) -- Use as the CloudFormation execution role + policy if your organization scopes down the default `AdministratorAccess`. Pass it during bootstrap with + `--cloudformation-execution-policies`. diff --git a/docs/policies/iam-policy-cfn-execution.json b/docs/policies/iam-policy-cfn-execution.json new file mode 100644 index 00000000..97239f96 --- /dev/null +++ b/docs/policies/iam-policy-cfn-execution.json @@ -0,0 +1,168 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "BedrockAgentCoreResources", + "Effect": "Allow", + "Action": "bedrock-agentcore:*", + "Resource": "*" + }, + { + "Sid": "IamRolesAndPolicies", + "Effect": "Allow", + "Action": [ + "iam:CreateRole", + "iam:DeleteRole", + "iam:GetRole", + "iam:PassRole", + "iam:PutRolePolicy", + "iam:DeleteRolePolicy", + "iam:GetRolePolicy", + "iam:AttachRolePolicy", + "iam:DetachRolePolicy", + "iam:TagRole", + "iam:UpdateAssumeRolePolicy" + ], + "Resource": "*" + }, + { + "Sid": "S3AssetStaging", + "Effect": "Allow", + "Action": [ + "s3:CreateBucket", + "s3:PutBucketPolicy", + "s3:PutBucketVersioning", + "s3:PutEncryptionConfiguration", + "s3:PutLifecycleConfiguration", + "s3:PutBucketPublicAccessBlock", + "s3:GetBucketLocation", + "s3:GetObject", + "s3:PutObject", + "s3:ListBucket", + "s3:DeleteObject" + ], + "Resource": "*" + }, + { + "Sid": "KmsEncryption", + "Effect": "Allow", + "Action": [ + "kms:CreateKey", + "kms:CreateAlias", + "kms:DescribeKey", + "kms:PutKeyPolicy", + "kms:GetKeyPolicy", + "kms:Encrypt", + "kms:Decrypt", + "kms:GenerateDataKey", + "kms:TagResource", + "kms:ScheduleKeyDeletion", + "kms:EnableKeyRotation" + ], + "Resource": "*" + }, + { + "Sid": "CloudFormationStackManagement", + "Effect": "Allow", + "Action": [ + "cloudformation:CreateStack", + "cloudformation:UpdateStack", + "cloudformation:DeleteStack", + "cloudformation:DescribeStacks", + "cloudformation:DescribeStackEvents", + "cloudformation:GetTemplate", + "cloudformation:CreateChangeSet", + "cloudformation:ExecuteChangeSet", + "cloudformation:DeleteChangeSet", + "cloudformation:DescribeChangeSet", + "cloudformation:ListStacks" + ], + "Resource": "*" + }, + { + "Sid": "EcrContainerBuilds", + "Effect": "Allow", + "Action": [ + "ecr:CreateRepository", + "ecr:DeleteRepository", + "ecr:DescribeRepositories", + "ecr:GetAuthorizationToken", + "ecr:BatchGetImage", + "ecr:BatchCheckLayerAvailability", + "ecr:GetDownloadUrlForLayer", + "ecr:PutImage", + "ecr:InitiateLayerUpload", + "ecr:UploadLayerPart", + "ecr:CompleteLayerUpload", + "ecr:SetRepositoryPolicy", + "ecr:PutLifecyclePolicy", + "ecr:PutImageScanningConfiguration", + "ecr:TagResource" + ], + "Resource": "*" + }, + { + "Sid": "CodeBuildContainerBuilds", + "Effect": "Allow", + "Action": [ + "codebuild:CreateProject", + "codebuild:DeleteProject", + "codebuild:UpdateProject", + "codebuild:StartBuild", + "codebuild:BatchGetBuilds", + "codebuild:BatchGetProjects" + ], + "Resource": "*" + }, + { + "Sid": "LambdaMcpAndCustomResources", + "Effect": "Allow", + "Action": [ + "lambda:CreateFunction", + "lambda:DeleteFunction", + "lambda:UpdateFunctionCode", + "lambda:UpdateFunctionConfiguration", + "lambda:GetFunction", + "lambda:GetFunctionConfiguration", + "lambda:InvokeFunction", + "lambda:AddPermission", + "lambda:RemovePermission", + "lambda:TagResource" + ], + "Resource": "*" + }, + { + "Sid": "CloudWatchLogs", + "Effect": "Allow", + "Action": [ + "logs:CreateLogGroup", + "logs:DeleteLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + "logs:DescribeLogGroups", + "logs:PutRetentionPolicy", + "logs:TagResource" + ], + "Resource": "*" + }, + { + "Sid": "CdkBootstrapVersionLookup", + "Effect": "Allow", + "Action": "ssm:GetParameters", + "Resource": "arn:aws:ssm:*:*:parameter/cdk-bootstrap/*/version" + }, + { + "Sid": "SecretsManagerForCredentials", + "Effect": "Allow", + "Action": [ + "secretsmanager:CreateSecret", + "secretsmanager:DeleteSecret", + "secretsmanager:DescribeSecret", + "secretsmanager:GetSecretValue", + "secretsmanager:PutSecretValue", + "secretsmanager:TagResource" + ], + "Resource": "*" + } + ] +} diff --git a/docs/policies/iam-policy-user.json b/docs/policies/iam-policy-user.json new file mode 100644 index 00000000..8f5a269e --- /dev/null +++ b/docs/policies/iam-policy-user.json @@ -0,0 +1,139 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "CdkBootstrapRoleAssumption", + "Effect": "Allow", + "Action": "sts:AssumeRole", + "Resource": [ + "arn:aws:iam::*:role/cdk-*-deploy-role-*", + "arn:aws:iam::*:role/cdk-*-file-publishing-role-*", + "arn:aws:iam::*:role/cdk-*-image-publishing-role-*", + "arn:aws:iam::*:role/cdk-*-lookup-role-*" + ] + }, + { + "Sid": "AccountIdentity", + "Effect": "Allow", + "Action": "sts:GetCallerIdentity", + "Resource": "*" + }, + { + "Sid": "CloudFormationStackStatus", + "Effect": "Allow", + "Action": "cloudformation:DescribeStacks", + "Resource": "*" + }, + { + "Sid": "StackDiscoveryByTags", + "Effect": "Allow", + "Action": "tag:GetResources", + "Resource": "*" + }, + { + "Sid": "AgentInvocation", + "Effect": "Allow", + "Action": [ + "bedrock-agentcore:InvokeAgentRuntime", + "bedrock-agentcore:InvokeAgentRuntimeForUser", + "bedrock-agentcore:Evaluate", + "bedrock-agentcore:StopRuntimeSession" + ], + "Resource": "*" + }, + { + "Sid": "AgentCoreResourceStatus", + "Effect": "Allow", + "Action": [ + "bedrock-agentcore:GetAgentRuntime", + "bedrock-agentcore:GetEvaluator", + "bedrock-agentcore:ListEvaluators", + "bedrock-agentcore:GetOnlineEvaluationConfig", + "bedrock-agentcore:UpdateOnlineEvaluationConfig", + "bedrock-agentcore:ListGatewayTargets" + ], + "Resource": "*" + }, + { + "Sid": "IdentityCredentialManagement", + "Effect": "Allow", + "Action": [ + "bedrock-agentcore:GetApiKeyCredentialProvider", + "bedrock-agentcore:CreateApiKeyCredentialProvider", + "bedrock-agentcore:UpdateApiKeyCredentialProvider", + "bedrock-agentcore:GetOauth2CredentialProvider", + "bedrock-agentcore:CreateOauth2CredentialProvider", + "bedrock-agentcore:UpdateOauth2CredentialProvider", + "bedrock-agentcore:GetTokenVault", + "bedrock-agentcore:CreateTokenVault", + "bedrock-agentcore:SetTokenVaultCMK" + ], + "Resource": "*" + }, + { + "Sid": "PolicyGeneration", + "Effect": "Allow", + "Action": [ + "bedrock-agentcore:StartPolicyGeneration", + "bedrock-agentcore:GetPolicyGeneration", + "bedrock-agentcore:ListPolicyGenerationAssets" + ], + "Resource": "*" + }, + { + "Sid": "TokenVaultKmsKeyCreation", + "Effect": "Allow", + "Action": ["kms:CreateKey", "kms:TagResource"], + "Resource": "*" + }, + { + "Sid": "LogsStreamingAndSearch", + "Effect": "Allow", + "Action": [ + "logs:StartLiveTail", + "logs:FilterLogEvents", + "logs:StartQuery", + "logs:GetQueryResults", + "logs:DescribeResourcePolicies", + "logs:PutResourcePolicy" + ], + "Resource": "*" + }, + { + "Sid": "TransactionSearchSetup", + "Effect": "Allow", + "Action": [ + "application-signals:StartDiscovery", + "xray:GetTraceSegmentDestination", + "xray:UpdateTraceSegmentDestination", + "xray:UpdateIndexingRule" + ], + "Resource": "*" + }, + { + "Sid": "BedrockModelInvocation", + "Effect": "Allow", + "Action": "bedrock:InvokeModel", + "Resource": "*" + }, + { + "Sid": "BedrockAgentImport", + "Effect": "Allow", + "Action": [ + "bedrock:GetFoundationModel", + "bedrock:GetGuardrail", + "bedrock:ListAgents", + "bedrock:ListAgentAliases", + "bedrock:GetAgent", + "bedrock:GetAgentAlias", + "bedrock:ListAgentActionGroups", + "bedrock:GetAgentActionGroup", + "bedrock:ListAgentKnowledgeBases", + "bedrock:GetKnowledgeBase", + "bedrock:ListAgentCollaborators", + "s3:GetObject" + ], + "Resource": "*" + } + ] +} From c2a053ce7daf896597ba3f6430947c12abfbeef8 Mon Sep 17 00:00:00 2001 From: Tejas Kashinath Date: Fri, 27 Mar 2026 13:37:21 -0400 Subject: [PATCH 2/3] docs: add permission boundaries, scope ARNs, close escalation paths - Add iam-policy-boundary.json for execution role permission boundaries - Add deny statements to CFN execution role policy (ForceExecutionRoleBoundary, PreventBoundaryRemoval, PreventBoundaryPolicyTampering) - Scope CDK bootstrap role ARNs to single account (ACCOUNT_ID placeholder) - Expand permission boundaries section with step-by-step enterprise hardening guide --- docs/PERMISSIONS.md | 102 +++++++++++++++----- docs/policies/iam-policy-boundary.json | 51 ++++++++++ docs/policies/iam-policy-cfn-execution.json | 29 ++++++ docs/policies/iam-policy-user.json | 8 +- 4 files changed, 162 insertions(+), 28 deletions(-) create mode 100644 docs/policies/iam-policy-boundary.json diff --git a/docs/PERMISSIONS.md b/docs/PERMISSIONS.md index 0bcf0f3c..87743981 100644 --- a/docs/PERMISSIONS.md +++ b/docs/PERMISSIONS.md @@ -5,8 +5,10 @@ who provision roles and policies in environments where access is tightly control action-by-action reference. Developers who just need to get unblocked can skip to [What developers need](#what-developers-need). -Ready-to-use policy documents are provided at [iam-policy-user.json](./policies/iam-policy-user.json) and -[iam-policy-cfn-execution.json](./policies/iam-policy-cfn-execution.json). +Ready-to-use policy documents are provided at [iam-policy-user.json](./policies/iam-policy-user.json), +[iam-policy-cfn-execution.json](./policies/iam-policy-cfn-execution.json), and +[iam-policy-boundary.json](./policies/iam-policy-boundary.json). Replace `ACCOUNT_ID` placeholders with your AWS account +number before deploying. ## How the CLI uses AWS @@ -170,23 +172,70 @@ safely removed: | Policy engine | `PolicyGeneration` | Remove `*PolicyEngine*` and `*Policy` actions from `BedrockAgentCoreResources` | | Online evaluations | Remove `UpdateOnlineEvaluationConfig` from `AgentCoreResourceStatus` | Remove `*OnlineEvaluationConfig*` actions from `BedrockAgentCoreResources` | -## Permission boundaries +## Hardening with permission boundaries -If your organization uses -[IAM permission boundaries](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html), there are -two places they can come into play. +The CFN execution role policy includes `iam:CreateRole` with `Resource: "*"`. Without further constraints, +CloudFormation could theoretically create a role with `AdministratorAccess` and a trust policy allowing the developer to +assume it. This is a well-known CDK privilege escalation pattern. -**On the developer's role.** The developer policy from [iam-policy-user.json](./policies/iam-policy-user.json) defines -the maximum set of actions a developer needs. You can use this as both the identity policy and the permissions boundary, -or create a broader boundary and use the policy for the effective permissions. The critical thing is that -`sts:AssumeRole` on the CDK bootstrap roles must be allowed through the boundary, otherwise deployments will fail. +[IAM permission boundaries](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html) close this +gap. A permission boundary caps the effective permissions of any role it is attached to, regardless of what identity +policies that role carries. Even if someone attaches `AdministratorAccess` to an execution role, the boundary limits +what the role can actually do. -**On roles that CloudFormation creates.** During `agentcore deploy`, CloudFormation creates execution roles for -runtimes, gateways, memory stores, and other resources. If your organization requires that all IAM roles have a -permissions boundary attached, you will need to ensure the CFN execution role has `iam:PutRolePermissionsBoundary` -permission, and the CDK constructs in your project pass the boundary ARN to the created roles. Currently, AgentCore's -CDK constructs create roles with inline policies scoped to the specific resource. These roles are not given permission -boundaries by default. +The setup has three parts: creating the boundary policy, adding deny statements to the CFN execution role so it is +forced to apply the boundary, and scoping the user policy to a single account. + +### Step 1: Create the execution role boundary + +This policy defines the maximum permissions any AgentCore execution role (runtime, memory, gateway, etc.) can have at +runtime. Create it once per account. + +The provided [iam-policy-boundary.json](./policies/iam-policy-boundary.json) allows: + +- `bedrock:InvokeModel` and `bedrock:InvokeModelWithResponseStream` for model access +- CloudWatch Logs scoped to `/aws/bedrock-agentcore/*` log groups +- X-Ray trace submission +- CloudWatch metrics scoped to the `bedrock-agentcore` namespace +- `bedrock-agentcore:GetWorkloadAccessToken*` for identity federation + +```bash +aws iam create-policy \ + --policy-name AgentCoreExecutionRoleBoundary \ + --policy-document file://docs/policies/iam-policy-boundary.json +``` + +### Step 2: Add deny statements to the CFN execution role + +The provided [iam-policy-cfn-execution.json](./policies/iam-policy-cfn-execution.json) includes three deny statements +that close the escalation paths. Replace `ACCOUNT_ID` with your account number before deploying. + +| Statement | What it blocks | +| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| `ForceExecutionRoleBoundary` | Denies `iam:CreateRole` unless the boundary is attached. Any role CloudFormation creates must carry `AgentCoreExecutionRoleBoundary`. | +| `PreventBoundaryRemoval` | Denies `iam:DeleteRolePermissionsBoundary` and `iam:PutRolePermissionsBoundary`. Prevents removing or swapping the boundary after role creation. | +| `PreventBoundaryPolicyTampering` | Denies `iam:CreatePolicyVersion`, `iam:DeletePolicy`, etc. on the boundary policy itself. Prevents widening the boundary to bypass it. | + +Together these ensure that even though `iam:CreateRole` targets `Resource: "*"`, every created role is capped by the +boundary, and neither the boundary nor its attachment can be tampered with. + +### Step 3: Scope the user policy to your account + +The provided [iam-policy-user.json](./policies/iam-policy-user.json) uses `ACCOUNT_ID` placeholders in the CDK bootstrap +role ARNs. Replace these with your actual account ID before deploying: + +``` +arn:aws:iam::ACCOUNT_ID:role/cdk-*-deploy-role-* +``` + +This prevents the developer from assuming CDK bootstrap roles in other accounts. + +### What about the developer's own role? + +The developer policy from [iam-policy-user.json](./policies/iam-policy-user.json) does not include `iam:CreateRole` or +any IAM write actions. Developers interact with IAM only indirectly through CloudFormation, which is constrained by the +boundary. If your organization applies permission boundaries to all IAM principals, you can use the developer policy +itself as the boundary, but make sure `sts:AssumeRole` on the CDK bootstrap roles is allowed through it. ## What developers need @@ -239,12 +288,12 @@ outside of CloudFormation. Required for all deployment operations (`deploy`, `status`, `diff`). -| Action | Resource | -| ---------------- | --------------------------------------------------- | -| `sts:AssumeRole` | `arn:aws:iam::*:role/cdk-*-deploy-role-*` | -| `sts:AssumeRole` | `arn:aws:iam::*:role/cdk-*-file-publishing-role-*` | -| `sts:AssumeRole` | `arn:aws:iam::*:role/cdk-*-image-publishing-role-*` | -| `sts:AssumeRole` | `arn:aws:iam::*:role/cdk-*-lookup-role-*` | +| Action | Resource | +| ---------------- | ------------------------------------------------------------ | +| `sts:AssumeRole` | `arn:aws:iam::ACCOUNT_ID:role/cdk-*-deploy-role-*` | +| `sts:AssumeRole` | `arn:aws:iam::ACCOUNT_ID:role/cdk-*-file-publishing-role-*` | +| `sts:AssumeRole` | `arn:aws:iam::ACCOUNT_ID:role/cdk-*-image-publishing-role-*` | +| `sts:AssumeRole` | `arn:aws:iam::ACCOUNT_ID:role/cdk-*-lookup-role-*` | ### Core @@ -470,7 +519,12 @@ actions used today. Ready-to-use IAM policy documents are provided alongside this guide: - [iam-policy-user.json](./policies/iam-policy-user.json) -- Attach to your IAM user or role. Covers all direct SDK - calls and CDK bootstrap role assumption. + calls and CDK bootstrap role assumption. Replace `ACCOUNT_ID` with your account number. - [iam-policy-cfn-execution.json](./policies/iam-policy-cfn-execution.json) -- Use as the CloudFormation execution role - policy if your organization scopes down the default `AdministratorAccess`. Pass it during bootstrap with + policy if your organization scopes down the default `AdministratorAccess`. Includes deny statements to enforce + permission boundaries. Replace `ACCOUNT_ID` with your account number. Pass it during bootstrap with `--cloudformation-execution-policies`. +- [iam-policy-boundary.json](./policies/iam-policy-boundary.json) -- Permission boundary for execution roles created + during deployment. Caps what agent runtimes, memories, and gateways can do at runtime (model access, logging, + tracing). Replace `ACCOUNT_ID` with your account number. See + [Hardening with permission boundaries](#hardening-with-permission-boundaries). diff --git a/docs/policies/iam-policy-boundary.json b/docs/policies/iam-policy-boundary.json new file mode 100644 index 00000000..751278c0 --- /dev/null +++ b/docs/policies/iam-policy-boundary.json @@ -0,0 +1,51 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "BedrockModelAccess", + "Effect": "Allow", + "Action": ["bedrock:InvokeModel", "bedrock:InvokeModelWithResponseStream"], + "Resource": ["arn:aws:bedrock:*::foundation-model/*", "arn:aws:bedrock:*:ACCOUNT_ID:*"] + }, + { + "Sid": "CloudWatchLogs", + "Effect": "Allow", + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + "logs:DescribeLogGroups", + "logs:DescribeLogStreams" + ], + "Resource": "arn:aws:logs:*:ACCOUNT_ID:log-group:/aws/bedrock-agentcore/*" + }, + { + "Sid": "XRayTracing", + "Effect": "Allow", + "Action": [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + "xray:GetSamplingRules", + "xray:GetSamplingTargets" + ], + "Resource": "*" + }, + { + "Sid": "CloudWatchMetrics", + "Effect": "Allow", + "Action": "cloudwatch:PutMetricData", + "Resource": "*", + "Condition": { + "StringEquals": { + "cloudwatch:namespace": "bedrock-agentcore" + } + } + }, + { + "Sid": "AgentCoreIdentity", + "Effect": "Allow", + "Action": "bedrock-agentcore:GetWorkloadAccessToken*", + "Resource": "arn:aws:bedrock-agentcore:*:ACCOUNT_ID:workload-identity-directory/*" + } + ] +} diff --git a/docs/policies/iam-policy-cfn-execution.json b/docs/policies/iam-policy-cfn-execution.json index 97239f96..2d47ad5c 100644 --- a/docs/policies/iam-policy-cfn-execution.json +++ b/docs/policies/iam-policy-cfn-execution.json @@ -151,6 +151,35 @@ "Action": "ssm:GetParameters", "Resource": "arn:aws:ssm:*:*:parameter/cdk-bootstrap/*/version" }, + { + "Sid": "ForceExecutionRoleBoundary", + "Effect": "Deny", + "Action": "iam:CreateRole", + "Resource": "*", + "Condition": { + "StringNotEquals": { + "iam:PermissionsBoundary": "arn:aws:iam::ACCOUNT_ID:policy/AgentCoreExecutionRoleBoundary" + } + } + }, + { + "Sid": "PreventBoundaryRemoval", + "Effect": "Deny", + "Action": ["iam:DeleteRolePermissionsBoundary", "iam:PutRolePermissionsBoundary"], + "Resource": "*" + }, + { + "Sid": "PreventBoundaryPolicyTampering", + "Effect": "Deny", + "Action": [ + "iam:CreatePolicy", + "iam:CreatePolicyVersion", + "iam:DeletePolicy", + "iam:DeletePolicyVersion", + "iam:SetDefaultPolicyVersion" + ], + "Resource": "arn:aws:iam::ACCOUNT_ID:policy/AgentCoreExecutionRoleBoundary" + }, { "Sid": "SecretsManagerForCredentials", "Effect": "Allow", diff --git a/docs/policies/iam-policy-user.json b/docs/policies/iam-policy-user.json index 8f5a269e..d5fb5855 100644 --- a/docs/policies/iam-policy-user.json +++ b/docs/policies/iam-policy-user.json @@ -6,10 +6,10 @@ "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": [ - "arn:aws:iam::*:role/cdk-*-deploy-role-*", - "arn:aws:iam::*:role/cdk-*-file-publishing-role-*", - "arn:aws:iam::*:role/cdk-*-image-publishing-role-*", - "arn:aws:iam::*:role/cdk-*-lookup-role-*" + "arn:aws:iam::ACCOUNT_ID:role/cdk-*-deploy-role-*", + "arn:aws:iam::ACCOUNT_ID:role/cdk-*-file-publishing-role-*", + "arn:aws:iam::ACCOUNT_ID:role/cdk-*-image-publishing-role-*", + "arn:aws:iam::ACCOUNT_ID:role/cdk-*-lookup-role-*" ] }, { From 00df3377a05ee056eed0101990d233835742aac1 Mon Sep 17 00:00:00 2001 From: Tejas Kashinath Date: Fri, 27 Mar 2026 13:54:39 -0400 Subject: [PATCH 3/3] Add note that permission boundary deny statements require CDK construct changes The CDK constructs don't currently attach permissionsBoundary to IAM roles they create, so the ForceExecutionRoleBoundary deny statement would block deployments. Mark Step 2 as a recommended future configuration until the constructs are updated. --- docs/PERMISSIONS.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/PERMISSIONS.md b/docs/PERMISSIONS.md index 87743981..7895513e 100644 --- a/docs/PERMISSIONS.md +++ b/docs/PERMISSIONS.md @@ -219,6 +219,12 @@ that close the escalation paths. Replace `ACCOUNT_ID` with your account number b Together these ensure that even though `iam:CreateRole` targets `Resource: "*"`, every created role is capped by the boundary, and neither the boundary nor its attachment can be tampered with. +> **Note:** These deny statements require a corresponding update to the AgentCore CDK constructs. The constructs do not +> currently attach a `permissionsBoundary` to the IAM roles they create (runtime, memory, gateway, etc.), so +> CloudFormation will fail to create those roles when `ForceExecutionRoleBoundary` is active. Until the CDK constructs +> are updated to accept and apply a permission boundary ARN, treat this section as a recommended future configuration. +> You can still create the boundary policy (Step 1) and scope the user policy (Step 3) today. + ### Step 3: Scope the user policy to your account The provided [iam-policy-user.json](./policies/iam-policy-user.json) uses `ACCOUNT_ID` placeholders in the CDK bootstrap