Feat/add AgentCore Policy integration with user identity propagation#97
Conversation
- Add Cognito V3 Pre-Token Lambda for M2M token claim injection - Add Cedar Policy Engine lifecycle via Custom Resource Lambda - Add user identity propagation from frontend JWT to Gateway Cedar policies - Move Cedar policy to gateway/policies/policy.cedar - Add direct Cognito token call with aws_client_metadata for user identity - Update backend-stack.ts with Policy Engine, GatewayRole permissions - Update cognito-stack.ts with featurePlan ESSENTIALS and V3 trigger
Add user identity propagation from frontend JWT through M2M tokens to AgentCore Policy Cedar policy evaluation at the Gateway. Includes Cedar Policy Engine lifecycle management via Custom Resource Lambda, Cognito V3 Pre-Token Generation Lambda for claim injection, and department-based Cedar policy for fine-grained access control. All 6 agent patterns updated with two authentication approaches: - Approach 1 (active): direct Cognito call with aws_client_metadata - Approach 2 (commented out): @requires_access_token decorator New documentation: docs/IDENTITY_POLICY.md Fixed: ZIP packager (recursive reader, utils inclusion, agentcore_tools naming, dynamic entry point), Cognito domain ordering for newer CDK, langgraph/copilotkit version bumps.
|
Latest scan for commit: Security Scan ResultsScan Metadata
SummaryScanner ResultsThe table below shows findings by scanner, with status based on severity thresholds and dependencies: Column Explanations: Severity Levels (S/C/H/M/L/I):
Other Columns:
Scanner Results:
Severity Thresholds (Thresh Column):
Threshold Source: Values in parentheses indicate where the threshold is configured:
Statistics calculation:
Detailed FindingsShow 3 actionable findingsFinding 1: python.lang.security.audit.logging.logger-credential-leak.python-logger-credential-disclosure
Description: Code Snippet: Finding 2: python.lang.security.audit.logging.logger-credential-leak.python-logger-credential-disclosure
Description: Code Snippet: Finding 3: python.lang.security.audit.logging.logger-credential-leak.python-logger-credential-disclosure
Description: Code Snippet: Report generated by Automated Security Helper (ASH) at 2026-05-13T14:21:23+00:00 |
…with user identity propagation Code updates: - ZIP permissiveness: readPatternFiles now reads all file types recursively - Replace general username with fastprojectadmin/fastuser in pretoken-v3 - Update policy.cedar comments referencing new user names Documentation: - Add IDENTITY_POLICY.md with AgentCore Policy overview, architecture flow, and components - Add CEDAR_POLICY_GUIDE.md with policy syntax, capabilities, schema constraints, and verified tool list logging instructions - Add REPLACING_COGNITO.md covering IdP swap, Gateway Interceptors, and Cognito User Groups - Update CHANGELOG, README, GATEWAY.md with new file references
|
Requested Items Addressed:
Testing completed: Verified Cedar policy V1 (allow) and V2 (deny) with different agent patterns, Docker and ZIP deployment types. Tool filtering confirmed via Runtime logs. |
Testing SummaryDeployed two fresh stacks from this branch to validate the full identity propagation chain: Stack 1 (Cedar V1 — Allow): Confirmed end-to-end flow works. Pre-Token Lambda correctly fires on TokenGeneration_ClientCredentials, assigns department=guest, role=viewer for my email, injects claims, and the Gateway tool call returns HTTP 200. The gateway_sample-tool-target___text_analysis_tool executes successfully and returns results. Stack 2 (Cedar V2 — Deny): Switched to the V2 policy (only finance/engineering permitted), deployed a fresh stack. Agent correctly only sees the Code Interpreter tool — the Gateway tool is filtered out by Cedar deny-by-default. Confirmed the policy enforcement works as documented. Bug Found: The handle_update path in infra-cdk/lambdas/cedar-policy/index.py generates a policy name that exceeds the 48-character API limit. The name format {engine_name}cedar_policy{timestamp} produces 52 characters for typical stack names, causing cdk deploy to fail on policy updates with: ValidationException: 1 validation error detected. Value with length 52 at '/name' failed to satisfy constraint: Member must have length between 1 and 48, inclusive Possible fix: Shorten the update policy name format, e.g. {engine_name}cp{suffix}[:48], and update the _delete_managed_policies helper to also match the new naming pattern. Feel free to fix it another way though. cc: @MichaelBMC |
- Change policy name format from {engine}_cedar_policy_{timestamp} to {engine}_cp_{timestamp}
- Add timestamp to Create path for consistency with Update path
- Update _delete_managed_policies to match new _cp prefix
- Add 48-character limit warning comments in backend-stack.ts and cedar-policy/index.py
- Update IDENTITY_POLICY.md example policy name
Fixed. Changed policy name format from |
…attachment - Add bedrock-agentcore:CheckAuthorizePermissions action (newly enforced by AgentCore) - Add /policy-engines/* resource pattern to match compound ARN format
|
Fix: Root cause: AgentCore now performs a pre-flight validation when attaching a Policy Engine to a Gateway via Why the scoped resource was needed: The permission check uses a compound resource ARN format ( Changes:
Tested: Fresh deploy, policy switch (V1→V2) redeploy, and agent framework switch — all succeed. |
feat: add AgentCore Policy integration with user identity propagation
Summary
Adds AgentCore Policy integration to FAST by propagating user identity from frontend JWT through M2M tokens to Cedar policy evaluation at the AgentCore Gateway. This enables fine-grained, user-level access control on Gateway tools — for example, allowing finance users to access billing tools while denying guest users. All 6 agent patterns are updated with identity-aware Gateway authentication, and 4 pre-existing ZIP packager bugs are fixed.
Motivation
AgentCore Policy enables fine-grained access control on Gateway tools by evaluating Cedar policies against user claims (e.g., department, role) in the request token. However, the existing M2M authentication flow used pure machine credentials — the M2M token contained no user identity information. Without user claims in the token, the Policy Engine has nothing to evaluate against.
This PR bridges that gap by:
aws_client_metadataChanges
Infrastructure (
infra-cdk/)New Files
lambdas/cedar-policy/index.py: Custom Resource Lambda for Cedar Policy Engine lifecycle (Create, Update, Delete)
_delete_managed_policieshelper with stale ID fallback via naming conventionlambdas/cedar-policy/requirements.txt: boto3>=1.42.0 dependency
lambdas/pretoken-v3/index.py: Cognito V3 Pre-Token Generation Lambda
verified_user_idfromclientMetadata(passed viaaws_client_metadata)user_id,department,role) into M2M access tokenModified Files
lib/backend-stack.ts:
GetPolicyEngine,AuthorizeAction,PartiallyAuthorizeActions)gateway/policies/policy.cedarwith comment stripping and{{GATEWAY_ARN}}replacementpatterns/utils/to deployment packagetools/toagentcore_tools/to avoid conflict with pattern'stools/directorybasic_agent.pylib/cognito-stack.ts:
featurePlan: cognito.FeaturePlan.ESSENTIALS(required for V3 triggers)Code.fromAssetwithpathimportaddPropertyOverride)Cedar Policy (
gateway/)New Files
{{GATEWAY_ARN}}placeholder replaced by CDK at deploy timeAgent Patterns (
patterns/)Modified Files
utils/auth.py:
get_secret()for Secrets Manager access with explicit exception handlingget_gateway_access_token()with direct Cognito/oauth2/tokencall acceptinguser_idparameteruser_idasaws_client_metadata[verified_user_id]for V3 Pre-Token Lambda enrichmentstrands-single-agent/tools/gateway.py: Two authentication approaches
create_gateway_mcp_client(user_id)with direct Cognito call@requires_access_tokendecorator for pure M2Mlanggraph-single-agent/tools/gateway.py: Async version of above for LangGraph/MultiServerMCPClient
agui-strands-agent/tools/gateway.py: Same as strands-single-agent version
agui-langgraph-agent/tools/gateway.py: Same as langgraph-single-agent async version
strands-single-agent/basic_agent.py:
create_gateway_mcp_client()→create_gateway_mcp_client(user_id)langgraph-single-agent/langgraph_agent.py:
create_langgraph_agent()→create_langgraph_agent(user_id: str), passesuser_idthroughagui-strands-agent/agent.py:
create_gateway_mcp_client()→create_gateway_mcp_client(user_id)agui-langgraph-agent/agent.py:
ActorAwareLangGraphAgent.__init__storing_user_idwith placeholder graph for newer copilotkit validationcreate_langgraph_agent()→create_langgraph_agent(user_id: str)claude-agent-sdk-single-agent/agent.py:
get_gateway_access_token()→get_gateway_access_token(user_id)claude-agent-sdk-multi-agent/agent.py: Same as single-agent
langgraph-single-agent/requirements.txt:
langgraph==1.1.3→langgraph>=1.1.5(fixesServerInfoimport error)agui-langgraph-agent/requirements.txt:
copilotkit>=0.1.84,langchain>=1.2.10,langgraph>=1.1.5(fixesExecutionInfoimport error + copilotkit compatibility)Documentation
New Files
Modified Files
cedar-policy/,pretoken-v3/,policy.cedar,IDENTITY_POLICY.md)create_gateway_mcp_client(access_token)tocreate_gateway_mcp_client(user_id)Security Considerations
Identity Chain Security
user_id) is extracted from the validated JWTsubclaim in the Runtime's Session Context, not from the LLM or request payloadaws_client_metadataparameter carries the verified user_id to Cognito, where the V3 Pre-Token Lambda injects claimsTwo Authentication Approaches
@requires_access_tokendecorator — AgentCore Identity handles token exchange server-side (no NAT Gateway needed)Testing
cdk deploywithout recreating Policy EngineVerifying Policy Allow/Deny via Tracing (Optional)
To verify Cedar policy decisions in CloudWatch logs:
FAST_stack_FASTAgent) from the Runtime resources sectionFAST-stack-gateway), scroll down to Tracing, click Edit, and toggle Enable tracing to Enableaws/spanslog group, then click on the default log streampolicyAgentCore.Policy.PartiallyAuthorizeActionsspan — it contains:aws.agentcore.policy.allowed_tools: tools the user is permitted to useaws.agentcore.policy.denied_tools: tools the user is denied access toaws.agentcore.gateway.policy.mode: should showENFORCEFiles Changed (33)
Added (7)
gateway/policies/policy.cedar- Cedar policy with V1 (allow) and V2 (deny) versionsinfra-cdk/lambdas/cedar-policy/index.py- Custom Resource Lambda for Policy Engine lifecycleinfra-cdk/lambdas/cedar-policy/requirements.txt- boto3 dependencyinfra-cdk/lambdas/pretoken-v3/index.py- Cognito V3 Pre-Token Generation Lambdadocs/IDENTITY_POLICY.md- Identity propagation and Cedar policy documentationdocs/CEDAR_POLICY_GUIDE.md- Cedar policy syntax, capabilities, and referencedocs/REPLACING_COGNITO.md- Identity provider swap and Gateway interceptors guideModified (26)
CHANGELOG.md- Added entries under [Unreleased]README.md- Updated architecture flow and project structuredocs/AGENT_CONFIGURATION.md- Updated gateway client code snippetdocs/DEPLOYMENT.md- Updated NAT Gateway section for identity propagationdocs/GATEWAY.md- Added related documentation referencesdocs/RUNTIME_GATEWAY_AUTH.md- Added cross-reference to IDENTITY_POLICY.mdinfra-cdk/README.md- Updated stack descriptionsinfra-cdk/lib/backend-stack.ts- Cedar Policy Custom Resource, Gateway role permissions, ZIP packager fixesinfra-cdk/lib/cognito-stack.ts- ESSENTIALS tier, Pre-Token Lambda, domain ordering fixpatterns/utils/auth.py- Added get_secret(), replaced get_gateway_access_token() with identity-aware versionpatterns/strands-single-agent/basic_agent.py- Pass user_id to gateway clientpatterns/strands-single-agent/tools/gateway.py- Two auth approaches with identity propagationpatterns/strands-single-agent/README.md- Updated gateway auth descriptionpatterns/langgraph-single-agent/langgraph_agent.py- Pass user_id through agent creationpatterns/langgraph-single-agent/tools/gateway.py- Async two auth approaches with identity propagationpatterns/langgraph-single-agent/requirements.txt- langgraph>=1.1.5patterns/langgraph-single-agent/README.md- Updated gateway auth descriptionpatterns/agui-strands-agent/agent.py- Pass user_id to gateway clientpatterns/agui-strands-agent/tools/gateway.py- Two auth approaches with identity propagationpatterns/agui-langgraph-agent/agent.py- ActorAwareLangGraphAgent with user_id and placeholder graphpatterns/agui-langgraph-agent/tools/gateway.py- Async two auth approaches with identity propagationpatterns/agui-langgraph-agent/requirements.txt- copilotkit, langchain, langgraph version bumpspatterns/claude-agent-sdk-single-agent/agent.py- Pass user_id to get_gateway_access_tokenpatterns/claude-agent-sdk-single-agent/README.md- Updated gateway auth descriptionpatterns/claude-agent-sdk-multi-agent/agent.py- Pass user_id to get_gateway_access_tokenpatterns/claude-agent-sdk-multi-agent/README.md- Updated gateway auth descriptionKey Architectural Decisions
Direct Cognito Call (Approach 1): The
@requires_access_tokendecorator does not supportaws_client_metadata, so a direct Cognito/oauth2/tokencall is required to propagate user identity into M2M tokens.Custom Resource for Policy Engine: No L1/L2 CDK construct exists for AgentCore Policy Engine or Cedar Policy. A Custom Resource Lambda manages the full lifecycle, following the same pattern as the existing OAuth2 Credential Provider.
Same PhysicalResourceId on Update: The Custom Resource returns the same PhysicalResourceId during updates to prevent CloudFormation from interpreting the change as a resource replacement (which would trigger a cleanup Delete that detaches the Policy Engine from the Gateway).
Two Approaches Preserved: Both authentication approaches are kept in each pattern's
tools/gateway.pywith clear switching instructions, allowing users to choose based on their needs (identity-aware vs pure M2M).Cognito Domain Ordering Fix: Newer CDK versions fail when ESSENTIALS tier + managed login v2 + branding are created simultaneously. Fixed by creating domain without v2 first, adding branding, then updating to v2 via L1 escape hatch.
Compliance with FAST Tenets
cdk deploysets up the entire identity propagation chain. Policy changes require only editingpolicy.cedarand redeploying.IDENTITY_POLICY.mdcovers the full feature with architecture flow, component details, Cedar policy guide, and customization instructions.Additional Notes
infra-terraform/directory is not updated in this PR. The Terraform maintainer can mirror the CDK changes using this PR as reference.docs/DEPLOYMENT.md.aws-cdk-libwas bumped from 2.241.0 to 2.243.0 in main.