@@ -12,8 +12,8 @@ This CDK infrastructure deploys a complete MCP gateway solution that enables VS
1212- ** Policy-Based Access Control** with custom Cedar policies
1313- ** Request/Response Interception** for logging and transformation
1414- ** PII Protection** using Bedrock Guardrails
15- - ** Flexible Deployment Options** (ALB or API Gateway)
1615- ** Custom Domain Support** with SSL/TLS
16+ - ** ALB Access Logging** to S3 with encryption and lifecycle management
1717
1818## Architecture
1919
@@ -25,10 +25,8 @@ This CDK infrastructure deploys a complete MCP gateway solution that enables VS
2525- ** OAuth Clients** :
2626 - VS Code Client (Authorization Code Grant with PKCE)
2727
28- #### 2. ** API Gateway Layer**
29- Choose between two deployment options:
30- - ** Application Load Balancer (ALB)** : Production-grade with custom domains and SSL/TLS
31- - ** API Gateway HTTP API** : Serverless, cost-effective for development/testing
28+ #### 2. ** Application Load Balancer**
29+ Production-grade internet-facing ALB with custom domain, SSL/TLS, WAF, and access logging.
3230
3331#### 3. ** MCP Proxy Lambda**
3432Central component that handles:
@@ -90,12 +88,12 @@ Example Lambda functions that implement MCP tools:
9088| Amazon Cognito | OAuth 2.0 authentication and user management |
9189| AWS Lambda | Serverless compute for proxy, MCP servers, and policy engine |
9290| Amazon Bedrock AgentCore | MCP gateway and protocol handling |
93- | Application Load Balancer | Production routing with custom domains (optional) |
94- | API Gateway HTTP API | Serverless API endpoint (optional) |
95- | Amazon VPC | Network isolation for ALB deployment |
91+ | Application Load Balancer | Internet-facing ALB with TLS, WAF, and access logging |
92+ | Amazon VPC | Network isolation with private subnets and VPC endpoints |
9693| AWS IAM | Identity and access management |
9794| Amazon Route53 | DNS management for custom domains |
9895| AWS Certificate Manager | SSL/TLS certificates |
96+ | Amazon S3 | ALB access log storage (encrypted, 90-day lifecycle) |
9997| Bedrock Guardrails | Content filtering and PII protection |
10098
10199## Prerequisites
@@ -116,7 +114,7 @@ Example Lambda functions that implement MCP tools:
116114### 1. Install Dependencies
117115
118116``` bash
119- cd enterprise-mcp-infra/ cdk
117+ cd cdk
120118npm install
121119```
122120
@@ -130,63 +128,31 @@ cdk bootstrap aws://ACCOUNT-ID/REGION
130128
131129Edit ` cdk/cdk.context.json ` to configure your deployment:
132130
133- #### Option A: ALB Deployment with Custom Domain
134-
135131``` json
136132{
137- "deploymentType" : " ALB" ,
138133 "domainName" : " enterprise-mcp" ,
139134 "hostedZoneName" : " example.com" ,
140135 "hostedZoneId" : " Z1234567890ABC" ,
141136 "certificateArn" : " arn:aws:acm:region:account:certificate/xxx"
142137}
143138```
144139
145- #### Option B: API Gateway Deployment (Default URL)
146-
147- ``` json
148- {
149- "deploymentType" : " API_GATEWAY" ,
150- "domainName" : " " ,
151- "hostedZoneName" : " " ,
152- "hostedZoneId" : " " ,
153- "certificateArn" : " "
154- }
155- ```
156-
157- #### Option C: API Gateway with Custom Domain
158-
159- ``` json
160- {
161- "deploymentType" : " API_GATEWAY" ,
162- "domainName" : " enterprise-mcp.example.com" ,
163- "hostedZoneName" : " example.com" ,
164- "hostedZoneId" : " Z1234567890ABC" ,
165- "certificateArn" : " arn:aws:acm:region:account:certificate/xxx"
166- }
167- ```
168-
169140** Configuration Parameters:**
170141
171142| Parameter | Description | Required | Default |
172143| -----------| -------------| ----------| ---------|
173- | ` deploymentType ` | Deployment type: ` ALB ` or ` API_GATEWAY ` | Yes | ` ALB ` |
174- | ` domainName ` | Custom domain name (e.g., ` enterprise-mcp ` for ALB, or full domain for API Gateway) | No (API Gateway only) | ` "" ` |
175- | ` hostedZoneName ` | Route53 hosted zone name (e.g., ` example.com ` ) | Only with custom domain | ` "" ` |
176- | ` hostedZoneId ` | Route53 hosted zone ID (e.g., ` Z1234567890ABC ` ) | Only with custom domain | ` "" ` |
177- | ` certificateArn ` | ACM certificate ARN for HTTPS | Only with custom domain | ` "" ` |
144+ | ` domainName ` | Custom domain name (e.g., ` enterprise-mcp ` ) | Yes | ` "" ` |
145+ | ` hostedZoneName ` | Route53 hosted zone name (e.g., ` example.com ` ) | Yes | ` "" ` |
146+ | ` hostedZoneId ` | Route53 hosted zone ID (e.g., ` Z1234567890ABC ` ) | Yes | ` "" ` |
147+ | ` certificateArn ` | ACM certificate ARN for HTTPS | Yes | ` "" ` |
178148
179149### 4. Deploy the Stack
180150
181151``` bash
182152cdk deploy
183153```
184154
185- You can also override context values via command line:
186-
187- ``` bash
188- cdk deploy -c deploymentType=API_GATEWAY
189- ```
155+ > ** Note:** The stack is pinned to ` us-east-1 ` in ` cdk/bin/enterprise-mcp-infra.ts ` . Update the ` region ` value there if you need a different region.
190156
191157### 5. Save CDK Outputs
192158
@@ -208,25 +174,26 @@ EnterpriseMcpInfraStack.Gateway = agentcore-mcp-gateway-xxxxx
208174
209175#### Using the Automated Script (Recommended)
210176
211- 1 . ** Edit** ` enterprise-mcp-infra/ scripts/script.py` :
177+ 1 . ** Edit** ` scripts/script.py ` :
212178 - Replace the ` output ` variable content with your actual CDK outputs (from step 4)
213179 - Customize the users list with your desired email addresses and passwords
214180
2151812 . ** Run the script** to create users:
216182``` bash
217- cd enterprise-mcp-infra/ scripts
183+ cd scripts
218184python script.py
219185```
220186
221187The script will:
222188- Parse the CDK outputs to extract the User Pool ID
223- - Create two default users: ` vscode- admin@example.com ` and ` vscode-user@example.com `
189+ - Create three default users ( admin, regular, and read-only)
224190- Set permanent passwords (no need for password reset on first login)
225191- Skip users that already exist
226192
227193** Default Users Created:**
228194- ` vscode-admin@example.com ` / ` TempPassword123! `
229195- ` vscode-user@example.com ` / ` TempPassword1234! `
196+ - ` vscode-readonly@example.com ` / ` TempPassword1235! `
230197
231198#### Manual User Creation (Alternative)
232199
@@ -374,15 +341,26 @@ cdk deploy
374341
375342### Lambda Logs
376343
377- ``` bash
378- # MCP Proxy Lambda
379- aws logs tail /aws/lambda/< ProxyLambdaName> --follow
380-
381- # Policy Engine Lambda
382- aws logs tail /aws/lambda/< PolicyEngineLambdaName> --follow
344+ The CDK stack outputs the function names for the two most commonly debugged Lambdas (` ProxyLambdaName ` , ` PreTokenGenerationLambdaName ` ). For the others, look up the auto-generated name in the AWS Console (Lambda → Functions, filter by stack name) or use the AWS CLI:
383345
384- # Interceptor Lambda
385- aws logs tail /aws/lambda/< InterceptorLambdaName> --follow
346+ ``` bash
347+ # MCP Proxy Lambda – name from CDK output: EnterpriseMcpInfraStack.ProxyLambdaName
348+ aws logs tail /aws/lambda/$( aws cloudformation describe-stacks \
349+ --stack-name EnterpriseMcpInfraStack \
350+ --query " Stacks[0].Outputs[?OutputKey=='ProxyLambdaName'].OutputValue" \
351+ --output text) --follow
352+
353+ # Pre-Token Generation Lambda – name from CDK output: EnterpriseMcpInfraStack.PreTokenGenerationLambdaName
354+ aws logs tail /aws/lambda/$( aws cloudformation describe-stacks \
355+ --stack-name EnterpriseMcpInfraStack \
356+ --query " Stacks[0].Outputs[?OutputKey=='PreTokenGenerationLambdaName'].OutputValue" \
357+ --output text) --follow
358+
359+ # Interceptor Lambda – look up name in AWS Console (filter by stack: EnterpriseMcpInfraStack)
360+ # aws logs tail /aws/lambda/<McpInterceptorLambda-name> --follow
361+
362+ # Policy Engine Lambda – look up name in AWS Console (filter by stack: EnterpriseMcpInfraStack)
363+ # aws logs tail /aws/lambda/<AgentCorePolicyEngine-PolicyFunction-name> --follow
386364```
387365
388366### CloudWatch Insights Queries
@@ -401,24 +379,66 @@ fields @timestamp, method, path, statusCode
401379| sort @timestamp desc
402380```
403381
404- ## Security Considerations
405-
406- ### Authentication
382+ ## Security Posture
383+
384+ ### Implemented
385+
386+ | Feature | Details |
387+ | ---| ---|
388+ | Cognito User Pool | Admin-only sign-up, strong password policy, Pre-Token Generation Lambda for audience/role claims |
389+ | OAuth 2.0 | Authorization Code Grant with custom scopes (` mcp.read ` , ` mcp.write ` ) |
390+ | JWT audience validation | Proxy Lambda validates ` aud ` claim before forwarding to AgentCore |
391+ | AgentCore Cognito authorizer | Token verified a second time by AWS at the gateway level |
392+ | Cedar policy engine | Fine-grained per-user tool access in ENFORCE mode |
393+ | Bedrock Guardrails | PII masking (address, name, email) and blocking (credit card numbers) via interceptor |
394+ | Lambda-in-VPC proxy | Private subnet, NAT egress only |
395+ | VPC Interface Endpoint | AgentCore traffic stays on AWS private network, never crosses public internet |
396+ | ALB TLS termination | TLS 1.2+ on custom domain via ACM certificate |
397+ | ALB ` dropInvalidHeaderFields ` | Rejects malformed headers (request-smuggling mitigation) |
398+ | ALB Host-header gating | Every forwarding rule requires Host header match; raw ` *.elb ` DNS returns 404 |
399+ | HTTP → HTTPS redirect | Permanent redirect on port 80 |
400+ | WAF WebACL | IP rate limit (1,000 req/5 min), AWS IP Reputation list, Core Rule Set (OWASP Top 10), Known Bad Inputs |
401+ | WAF Bot Control | COMMON level in COUNT mode (switch to BLOCK after traffic validation) |
402+ | Reserved Lambda concurrency | Caps on all functions to limit DoS blast radius |
403+ | Gateway resource policy | Restricts ` InvokeGateway ` to the VPC |
404+ | Shield Standard | Automatic L3/L4 DDoS protection on public ALBs |
405+ | ALB access logging | S3 bucket with SSE, public access blocked, SSL enforced, 90-day lifecycle expiration |
406+ | Redirect URI allowlist | ` handle_callback ` validates ` redirect_uri ` against registered Cognito callback URLs before issuing 302 redirects (prevents open-redirect / auth code theft) |
407+ | Per-Lambda IAM roles | Four dedicated least-privilege roles: ` preTokenLambdaRole ` (Cognito trigger), ` proxyLambdaRole ` (VPC + AgentCore invoke), ` interceptorLambdaRole ` (Bedrock Guardrails only), ` toolLambdaRole ` (CloudWatch Logs only) |
408+
409+ ### Not Implemented – Consider Before Production
410+
411+ | Feature | Details |
412+ | ---| ---|
413+ | Shield Advanced | L7 DDoS protection, SRT access, cost protection (subscription required) |
414+ | Bot Control TARGETED | Higher inspection level for WAF Bot Control (additional cost) |
415+ | CloudTrail / Security Hub | Centralized audit and security findings |
416+ | ALB access-log Athena workgroup | Query access logs via Athena for forensic analysis |
417+ | GuardDuty findings | Threat detection integration |
418+ | MFA enforcement | Cognito User Pool is MFA-ready but not enforced (` mfa: cognito.Mfa.REQUIRED ` ) |
419+ | Scoped IAM resources | Several policies use ` Resource: "*" ` — scope to specific ARNs |
420+ | PKCE enforcement | Verify PKCE is enforced on the Cognito public client (no client secret) |
421+ | Log encryption | Lambda CloudWatch logs use default settings (no KMS CMK encryption) |
422+ | Log retention policy | Lambda CloudWatch log retention is indefinite by default |
423+
424+ ### Additional Security Details
425+
426+ #### Authentication
407427- OAuth 2.0 with PKCE (Proof Key for Code Exchange)
408428- JWT tokens with custom claims
409429- Secure token storage in VS Code
410430
411- ### Authorization
431+ #### Authorization
412432- Policy-based access control using Cedar
413433- User attribute injection via Lambda triggers
414434- Gateway-level authorization enforcement
415435
416- ### Data Protection
436+ #### Data Protection
417437- SSL/TLS encryption in transit
418438- PII anonymization via Bedrock Guardrails
419- - VPC isolation for ALB deployments
439+ - VPC isolation with private subnets and VPC endpoints
420440
421- ### Secrets Management
441+ #### Secrets Management
422442- Client secrets stored in environment variables
423443- OAuth tokens never exposed to logs
424444- IAM role-based access for Lambda functions
@@ -452,10 +472,12 @@ cdk destroy
452472
453473## Architecture Decisions
454474
455- ### Why Two Deployment Options ?
475+ ### Why ALB ?
456476
457- - ** ALB** : Production environments requiring custom domains, SSL/TLS, and fine-grained routing
458- - ** API Gateway** : Development/testing, serverless preference, cost optimization
477+ - Production-grade with custom domains, SSL/TLS, and fine-grained routing
478+ - WAF WebACL integration for OWASP Top 10, rate limiting, and bot control
479+ - Access logging to S3 for forensic analysis
480+ - VPC integration for network isolation
459481
460482### Why Lambda for MCP Servers?
461483
0 commit comments