Skip to content

Security: aws-samples/sample-agent-interoperability

Security

SECURITY.md

Security

This document describes the security architecture of the AWS-GCP agent interoperability demo.

Threat Model

See docs/threat-model.md for the full STRIDE threat model (17 threats, 14 mitigations).

JWT Verification Boundaries

This demo has three JWT verification points:

  1. API Gateway custom authorizer (src/gemini-proxy/authorizer.py): Full RS256 signature verification via PyJWT + Cognito JWKS. Validates issuer, audience, expiry, and allowed client IDs. This is the public entry point for Gemini Enterprise traffic.

  2. AgentCore Runtime edge: Each runtime uses RuntimeAuthorizerConfiguration.usingJWT(...) which verifies JWTs against the Cognito OIDC discovery endpoint before the container is invoked. This is managed by the AgentCore service.

  3. Agent IdentityMiddleware (src/agents/shared/agent_core.py, src/agents/shared/strands_agent_core.py): Extracts email and name claims from the JWT without signature verification. This is safe because the JWT has already been verified at the AgentCore edge (point 2). If the edge gate is ever disabled, these claims become untrusted.

Production upgrade: Add defense-in-depth signature verification in the IdentityMiddleware.

Secrets Handling

All sensitive credentials are stored in AWS Secrets Manager:

  • aws-gcp-agents/cognito-m2m -- Cognito M2M client secret (used for agent-to-gateway auth)
  • aws-gcp-agents/google-api-key -- Google API key (used by Gemini agents)

Applications fetch secrets at startup via boto3 and cache them in memory. Secret rotation requires a runtime restart (acceptable for a demo).

CDK synthesis caveat

Secrets are created via SecretValue.unsafePlainText(...), which embeds the value in the synthesized CloudFormation template (cdk.out/). This directory is .gitignored and never published. For production, pre-create secrets out-of-band and reference them by ARN, or use a rotation schedule.

The -c clientSecret=<val> and -c googleApiKey=<val> deploy-time values exist only in shell history and the local cdk.out/ directory.

Authentication Flows

  • Frontend -> Cognito (PKCE + Google federation) -> AgentCore Runtime
  • Gemini Enterprise -> Google OAuth -> Cognito (federation) -> API Gateway (custom authorizer) -> Lambda proxy -> AgentCore Runtime
  • Machine-to-machine -> Cognito client-credentials -> Gateway / AgentCore

Demo vs Production

If you fork this for production, also:

  • Enable AWS Secrets Manager rotation for all secrets
  • Add defense-in-depth JWT verification in the agent IdentityMiddleware
  • Scope IAM wildcards to specific models and resources
  • Enable AWS CloudTrail for audit logging
  • Use SecretValue.secretsManager(...) instead of unsafePlainText in CDK
  • Add WAF rules on the API Gateway
  • Pin dependency versions and run regular vulnerability scans

There aren't any published security advisories