@@ -5,8 +5,10 @@ who provision roles and policies in environments where access is tightly control
55action-by-action reference. Developers who just need to get unblocked can skip to
66[ What developers need] ( #what-developers-need ) .
77
8- Ready-to-use policy documents are provided at [ iam-policy-user.json] ( ./policies/iam-policy-user.json ) and
9- [ iam-policy-cfn-execution.json] ( ./policies/iam-policy-cfn-execution.json ) .
8+ Ready-to-use policy documents are provided at [ iam-policy-user.json] ( ./policies/iam-policy-user.json ) ,
9+ [ iam-policy-cfn-execution.json] ( ./policies/iam-policy-cfn-execution.json ) , and
10+ [ iam-policy-boundary.json] ( ./policies/iam-policy-boundary.json ) . Replace ` ACCOUNT_ID ` placeholders with your AWS account
11+ number before deploying.
1012
1113## How the CLI uses AWS
1214
@@ -170,23 +172,70 @@ safely removed:
170172| Policy engine | ` PolicyGeneration ` | Remove ` *PolicyEngine* ` and ` *Policy ` actions from ` BedrockAgentCoreResources ` |
171173| Online evaluations | Remove ` UpdateOnlineEvaluationConfig ` from ` AgentCoreResourceStatus ` | Remove ` *OnlineEvaluationConfig* ` actions from ` BedrockAgentCoreResources ` |
172174
173- ## Permission boundaries
175+ ## Hardening with permission boundaries
174176
175- If your organization uses
176- [ IAM permission boundaries ] ( https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html ) , there are
177- two places they can come into play .
177+ The CFN execution role policy includes ` iam:CreateRole ` with ` Resource: "*" ` . Without further constraints,
178+ CloudFormation could theoretically create a role with ` AdministratorAccess ` and a trust policy allowing the developer to
179+ assume it. This is a well-known CDK privilege escalation pattern .
178180
179- ** On the developer's role. ** The developer policy from [ iam-policy-user.json ] ( ./policies/iam-policy-user.json ) defines
180- the maximum set of actions a developer needs. You can use this as both the identity policy and the permissions boundary,
181- or create a broader boundary and use the policy for the effective permissions. The critical thing is that
182- ` sts:AssumeRole ` on the CDK bootstrap roles must be allowed through the boundary, otherwise deployments will fail .
181+ [ IAM permission boundaries ] ( https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html ) close this
182+ gap. A permission boundary caps the effective permissions of any role it is attached to, regardless of what identity
183+ policies that role carries. Even if someone attaches ` AdministratorAccess ` to an execution role, the boundary limits
184+ what the role can actually do .
183185
184- ** On roles that CloudFormation creates.** During ` agentcore deploy ` , CloudFormation creates execution roles for
185- runtimes, gateways, memory stores, and other resources. If your organization requires that all IAM roles have a
186- permissions boundary attached, you will need to ensure the CFN execution role has ` iam:PutRolePermissionsBoundary `
187- permission, and the CDK constructs in your project pass the boundary ARN to the created roles. Currently, AgentCore's
188- CDK constructs create roles with inline policies scoped to the specific resource. These roles are not given permission
189- boundaries by default.
186+ The setup has three parts: creating the boundary policy, adding deny statements to the CFN execution role so it is
187+ forced to apply the boundary, and scoping the user policy to a single account.
188+
189+ ### Step 1: Create the execution role boundary
190+
191+ This policy defines the maximum permissions any AgentCore execution role (runtime, memory, gateway, etc.) can have at
192+ runtime. Create it once per account.
193+
194+ The provided [ iam-policy-boundary.json] ( ./policies/iam-policy-boundary.json ) allows:
195+
196+ - ` bedrock:InvokeModel ` and ` bedrock:InvokeModelWithResponseStream ` for model access
197+ - CloudWatch Logs scoped to ` /aws/bedrock-agentcore/* ` log groups
198+ - X-Ray trace submission
199+ - CloudWatch metrics scoped to the ` bedrock-agentcore ` namespace
200+ - ` bedrock-agentcore:GetWorkloadAccessToken* ` for identity federation
201+
202+ ``` bash
203+ aws iam create-policy \
204+ --policy-name AgentCoreExecutionRoleBoundary \
205+ --policy-document file://docs/policies/iam-policy-boundary.json
206+ ```
207+
208+ ### Step 2: Add deny statements to the CFN execution role
209+
210+ The provided [ iam-policy-cfn-execution.json] ( ./policies/iam-policy-cfn-execution.json ) includes three deny statements
211+ that close the escalation paths. Replace ` ACCOUNT_ID ` with your account number before deploying.
212+
213+ | Statement | What it blocks |
214+ | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
215+ | ` ForceExecutionRoleBoundary ` | Denies ` iam:CreateRole ` unless the boundary is attached. Any role CloudFormation creates must carry ` AgentCoreExecutionRoleBoundary ` . |
216+ | ` PreventBoundaryRemoval ` | Denies ` iam:DeleteRolePermissionsBoundary ` and ` iam:PutRolePermissionsBoundary ` . Prevents removing or swapping the boundary after role creation. |
217+ | ` PreventBoundaryPolicyTampering ` | Denies ` iam:CreatePolicyVersion ` , ` iam:DeletePolicy ` , etc. on the boundary policy itself. Prevents widening the boundary to bypass it. |
218+
219+ Together these ensure that even though ` iam:CreateRole ` targets ` Resource: "*" ` , every created role is capped by the
220+ boundary, and neither the boundary nor its attachment can be tampered with.
221+
222+ ### Step 3: Scope the user policy to your account
223+
224+ The provided [ iam-policy-user.json] ( ./policies/iam-policy-user.json ) uses ` ACCOUNT_ID ` placeholders in the CDK bootstrap
225+ role ARNs. Replace these with your actual account ID before deploying:
226+
227+ ```
228+ arn:aws:iam::ACCOUNT_ID:role/cdk-*-deploy-role-*
229+ ```
230+
231+ This prevents the developer from assuming CDK bootstrap roles in other accounts.
232+
233+ ### What about the developer's own role?
234+
235+ The developer policy from [ iam-policy-user.json] ( ./policies/iam-policy-user.json ) does not include ` iam:CreateRole ` or
236+ any IAM write actions. Developers interact with IAM only indirectly through CloudFormation, which is constrained by the
237+ boundary. If your organization applies permission boundaries to all IAM principals, you can use the developer policy
238+ itself as the boundary, but make sure ` sts:AssumeRole ` on the CDK bootstrap roles is allowed through it.
190239
191240## What developers need
192241
@@ -239,12 +288,12 @@ outside of CloudFormation.
239288
240289Required for all deployment operations (` deploy ` , ` status ` , ` diff ` ).
241290
242- | Action | Resource |
243- | ---------------- | --------------------------------------------------- |
244- | ` sts:AssumeRole ` | ` arn:aws:iam::* :role/cdk-*-deploy-role-* ` |
245- | ` sts:AssumeRole ` | ` arn:aws:iam::* :role/cdk-*-file-publishing-role-* ` |
246- | ` sts:AssumeRole ` | ` arn:aws:iam::* :role/cdk-*-image-publishing-role-* ` |
247- | ` sts:AssumeRole ` | ` arn:aws:iam::* :role/cdk-*-lookup-role-* ` |
291+ | Action | Resource |
292+ | ---------------- | ------------------------------------------------------------ |
293+ | ` sts:AssumeRole ` | ` arn:aws:iam::ACCOUNT_ID :role/cdk-*-deploy-role-* ` |
294+ | ` sts:AssumeRole ` | ` arn:aws:iam::ACCOUNT_ID :role/cdk-*-file-publishing-role-* ` |
295+ | ` sts:AssumeRole ` | ` arn:aws:iam::ACCOUNT_ID :role/cdk-*-image-publishing-role-* ` |
296+ | ` sts:AssumeRole ` | ` arn:aws:iam::ACCOUNT_ID :role/cdk-*-lookup-role-* ` |
248297
249298### Core
250299
@@ -470,7 +519,12 @@ actions used today.
470519Ready-to-use IAM policy documents are provided alongside this guide:
471520
472521- [ iam-policy-user.json] ( ./policies/iam-policy-user.json ) -- Attach to your IAM user or role. Covers all direct SDK
473- calls and CDK bootstrap role assumption.
522+ calls and CDK bootstrap role assumption. Replace ` ACCOUNT_ID ` with your account number.
474523- [ iam-policy-cfn-execution.json] ( ./policies/iam-policy-cfn-execution.json ) -- Use as the CloudFormation execution role
475- policy if your organization scopes down the default ` AdministratorAccess ` . Pass it during bootstrap with
524+ policy if your organization scopes down the default ` AdministratorAccess ` . Includes deny statements to enforce
525+ permission boundaries. Replace ` ACCOUNT_ID ` with your account number. Pass it during bootstrap with
476526 ` --cloudformation-execution-policies ` .
527+ - [ iam-policy-boundary.json] ( ./policies/iam-policy-boundary.json ) -- Permission boundary for execution roles created
528+ during deployment. Caps what agent runtimes, memories, and gateways can do at runtime (model access, logging,
529+ tracing). Replace ` ACCOUNT_ID ` with your account number. See
530+ [ Hardening with permission boundaries] ( #hardening-with-permission-boundaries ) .
0 commit comments