1+ {
2+ "Description" : " Bedrock Access Gateway - OpenAI-compatible RESTful APIs for Amazon Bedrock" ,
3+ "Parameters" : {
4+ "ApiKeySecretArn" : {
5+ "Type" : " String" ,
6+ "AllowedPattern" : " ^arn:aws:secretsmanager:.*$" ,
7+ "Description" : " The secret ARN in Secrets Manager used to store the API Key"
8+ },
9+ "ContainerImageUri" : {
10+ "Type" : " String" ,
11+ "Description" : " The ECR image URI for the Lambda function (e.g., 123456789012.dkr.ecr.us-east-1.amazonaws.com/bedrock-proxy-api:latest)"
12+ },
13+ "DefaultModelId" : {
14+ "Type" : " String" ,
15+ "Default" : " anthropic.claude-3-sonnet-20240229-v1:0" ,
16+ "Description" : " The default model ID, please make sure the model ID is supported in the current region"
17+ },
18+ "EnablePromptCaching" : {
19+ "Type" : " String" ,
20+ "Default" : " false" ,
21+ "AllowedValues" : [
22+ " true" ,
23+ " false"
24+ ],
25+ "Description" : " Enable prompt caching for supported models (Claude, Nova). When enabled, adds cachePoint to system prompts and messages for cost savings."
26+ },
27+ "LambdaExecutionRoleArn" : {
28+ "Type" : " String" ,
29+ "AllowedPattern" : " ^arn:aws:iam::\\ d{12}:role/.*$" ,
30+ "Description" : " The ARN of an existing IAM role to be used by the Lambda function"
31+ }
32+ },
33+ "Resources" : {
34+ "VPCB9E5F0B4" : {
35+ "Type" : " AWS::EC2::VPC" ,
36+ "Properties" : {
37+ "CidrBlock" : " 10.250.0.0/16" ,
38+ "EnableDnsHostnames" : true ,
39+ "EnableDnsSupport" : true ,
40+ "InstanceTenancy" : " default" ,
41+ "Tags" : [
42+ {
43+ "Key" : " Name" ,
44+ "Value" : " BedrockProxy/VPC"
45+ }
46+ ]
47+ }
48+ },
49+ "VPCPublicSubnet1SubnetB4246D30" : {
50+ "Type" : " AWS::EC2::Subnet" ,
51+ "Properties" : {
52+ "AvailabilityZone" : {
53+ "Fn::Select" : [
54+ 0 ,
55+ {
56+ "Fn::GetAZs" : " "
57+ }
58+ ]
59+ },
60+ "CidrBlock" : " 10.250.0.0/24" ,
61+ "MapPublicIpOnLaunch" : true ,
62+ "Tags" : [
63+ {
64+ "Key" : " aws-cdk:subnet-name" ,
65+ "Value" : " Public"
66+ },
67+ {
68+ "Key" : " aws-cdk:subnet-type" ,
69+ "Value" : " Public"
70+ },
71+ {
72+ "Key" : " Name" ,
73+ "Value" : " BedrockProxy/VPC/PublicSubnet1"
74+ }
75+ ],
76+ "VpcId" : {
77+ "Ref" : " VPCB9E5F0B4"
78+ }
79+ }
80+ },
81+ "VPCPublicSubnet1RouteTableFEE4B781" : {
82+ "Type" : " AWS::EC2::RouteTable" ,
83+ "Properties" : {
84+ "Tags" : [
85+ {
86+ "Key" : " Name" ,
87+ "Value" : " BedrockProxy/VPC/PublicSubnet1"
88+ }
89+ ],
90+ "VpcId" : {
91+ "Ref" : " VPCB9E5F0B4"
92+ }
93+ }
94+ },
95+ "VPCPublicSubnet1RouteTableAssociation0B0896DC" : {
96+ "Type" : " AWS::EC2::SubnetRouteTableAssociation" ,
97+ "Properties" : {
98+ "RouteTableId" : {
99+ "Ref" : " VPCPublicSubnet1RouteTableFEE4B781"
100+ },
101+ "SubnetId" : {
102+ "Ref" : " VPCPublicSubnet1SubnetB4246D30"
103+ }
104+ }
105+ },
106+ "VPCPublicSubnet1DefaultRoute91CEF279" : {
107+ "Type" : " AWS::EC2::Route" ,
108+ "Properties" : {
109+ "DestinationCidrBlock" : " 0.0.0.0/0" ,
110+ "GatewayId" : {
111+ "Ref" : " VPCIGWB7E252D3"
112+ },
113+ "RouteTableId" : {
114+ "Ref" : " VPCPublicSubnet1RouteTableFEE4B781"
115+ }
116+ },
117+ "DependsOn" : [
118+ " VPCVPCGW99B986DC"
119+ ]
120+ },
121+ "VPCPublicSubnet2Subnet74179F39" : {
122+ "Type" : " AWS::EC2::Subnet" ,
123+ "Properties" : {
124+ "AvailabilityZone" : {
125+ "Fn::Select" : [
126+ 1 ,
127+ {
128+ "Fn::GetAZs" : " "
129+ }
130+ ]
131+ },
132+ "CidrBlock" : " 10.250.1.0/24" ,
133+ "MapPublicIpOnLaunch" : true ,
134+ "Tags" : [
135+ {
136+ "Key" : " aws-cdk:subnet-name" ,
137+ "Value" : " Public"
138+ },
139+ {
140+ "Key" : " aws-cdk:subnet-type" ,
141+ "Value" : " Public"
142+ },
143+ {
144+ "Key" : " Name" ,
145+ "Value" : " BedrockProxy/VPC/PublicSubnet2"
146+ }
147+ ],
148+ "VpcId" : {
149+ "Ref" : " VPCB9E5F0B4"
150+ }
151+ }
152+ },
153+ "VPCPublicSubnet2RouteTable6F1A15F1" : {
154+ "Type" : " AWS::EC2::RouteTable" ,
155+ "Properties" : {
156+ "Tags" : [
157+ {
158+ "Key" : " Name" ,
159+ "Value" : " BedrockProxy/VPC/PublicSubnet2"
160+ }
161+ ],
162+ "VpcId" : {
163+ "Ref" : " VPCB9E5F0B4"
164+ }
165+ }
166+ },
167+ "VPCPublicSubnet2RouteTableAssociation5A808732" : {
168+ "Type" : " AWS::EC2::SubnetRouteTableAssociation" ,
169+ "Properties" : {
170+ "RouteTableId" : {
171+ "Ref" : " VPCPublicSubnet2RouteTable6F1A15F1"
172+ },
173+ "SubnetId" : {
174+ "Ref" : " VPCPublicSubnet2Subnet74179F39"
175+ }
176+ }
177+ },
178+ "VPCPublicSubnet2DefaultRouteB7481BBA" : {
179+ "Type" : " AWS::EC2::Route" ,
180+ "Properties" : {
181+ "DestinationCidrBlock" : " 0.0.0.0/0" ,
182+ "GatewayId" : {
183+ "Ref" : " VPCIGWB7E252D3"
184+ },
185+ "RouteTableId" : {
186+ "Ref" : " VPCPublicSubnet2RouteTable6F1A15F1"
187+ }
188+ },
189+ "DependsOn" : [
190+ " VPCVPCGW99B986DC"
191+ ]
192+ },
193+ "VPCIGWB7E252D3" : {
194+ "Type" : " AWS::EC2::InternetGateway" ,
195+ "Properties" : {
196+ "Tags" : [
197+ {
198+ "Key" : " Name" ,
199+ "Value" : " BedrockProxy/VPC"
200+ }
201+ ]
202+ }
203+ },
204+ "VPCVPCGW99B986DC" : {
205+ "Type" : " AWS::EC2::VPCGatewayAttachment" ,
206+ "Properties" : {
207+ "InternetGatewayId" : {
208+ "Ref" : " VPCIGWB7E252D3"
209+ },
210+ "VpcId" : {
211+ "Ref" : " VPCB9E5F0B4"
212+ }
213+ }
214+ },
215+ "ProxyApiHandlerEC15A492" : {
216+ "Type" : " AWS::Lambda::Function" ,
217+ "Properties" : {
218+ "Architectures" : [
219+ " arm64"
220+ ],
221+ "Code" : {
222+ "ImageUri" : {
223+ "Ref" : " ContainerImageUri"
224+ }
225+ },
226+ "Description" : " Bedrock Proxy API Handler" ,
227+ "Environment" : {
228+ "Variables" : {
229+ "DEBUG" : " false" ,
230+ "API_KEY_SECRET_ARN" : {
231+ "Ref" : " ApiKeySecretArn"
232+ },
233+ "DEFAULT_MODEL" : {
234+ "Ref" : " DefaultModelId"
235+ },
236+ "DEFAULT_EMBEDDING_MODEL" : " cohere.embed-multilingual-v3" ,
237+ "ENABLE_CROSS_REGION_INFERENCE" : " true" ,
238+ "ENABLE_APPLICATION_INFERENCE_PROFILES" : " true" ,
239+ "ENABLE_PROMPT_CACHING" : {
240+ "Ref" : " EnablePromptCaching"
241+ }
242+ }
243+ },
244+ "MemorySize" : 1024 ,
245+ "PackageType" : " Image" ,
246+ "Role" : {
247+ "Ref" : " LambdaExecutionRoleArn"
248+ },
249+ "Timeout" : 600
250+ }
251+ },
252+ "ProxyApiHandlerInvoke2UTWxhlfyqbT5FTn5jvgbLgjFfJwzswGk55DU1HYF6C33779" : {
253+ "Type" : " AWS::Lambda::Permission" ,
254+ "Properties" : {
255+ "Action" : " lambda:InvokeFunction" ,
256+ "FunctionName" : {
257+ "Fn::GetAtt" : [
258+ " ProxyApiHandlerEC15A492" ,
259+ " Arn"
260+ ]
261+ },
262+ "Principal" : " elasticloadbalancing.amazonaws.com"
263+ }
264+ },
265+ "ProxyALB87756780" : {
266+ "Type" : " AWS::ElasticLoadBalancingV2::LoadBalancer" ,
267+ "Properties" : {
268+ "LoadBalancerAttributes" : [
269+ {
270+ "Key" : " deletion_protection.enabled" ,
271+ "Value" : " false"
272+ }
273+ ],
274+ "Scheme" : " internet-facing" ,
275+ "SecurityGroups" : [
276+ {
277+ "Fn::GetAtt" : [
278+ " ProxyALBSecurityGroup0D6CA3DA" ,
279+ " GroupId"
280+ ]
281+ }
282+ ],
283+ "Subnets" : [
284+ {
285+ "Ref" : " VPCPublicSubnet1SubnetB4246D30"
286+ },
287+ {
288+ "Ref" : " VPCPublicSubnet2Subnet74179F39"
289+ }
290+ ],
291+ "Type" : " application"
292+ },
293+ "DependsOn" : [
294+ " VPCPublicSubnet1DefaultRoute91CEF279" ,
295+ " VPCPublicSubnet1RouteTableAssociation0B0896DC" ,
296+ " VPCPublicSubnet2DefaultRouteB7481BBA" ,
297+ " VPCPublicSubnet2RouteTableAssociation5A808732"
298+ ]
299+ },
300+ "ProxyALBSecurityGroup0D6CA3DA" : {
301+ "Type" : " AWS::EC2::SecurityGroup" ,
302+ "Properties" : {
303+ "GroupDescription" : " Automatically created Security Group for ELB BedrockProxyALB1CE4CAD1" ,
304+ "SecurityGroupEgress" : [
305+ {
306+ "CidrIp" : " 255.255.255.255/32" ,
307+ "Description" : " Disallow all traffic" ,
308+ "FromPort" : 252 ,
309+ "IpProtocol" : " icmp" ,
310+ "ToPort" : 86
311+ }
312+ ],
313+ "SecurityGroupIngress" : [
314+ {
315+ "CidrIp" : " 0.0.0.0/0" ,
316+ "Description" : " Allow from anyone on port 80" ,
317+ "FromPort" : 80 ,
318+ "IpProtocol" : " tcp" ,
319+ "ToPort" : 80
320+ }
321+ ],
322+ "VpcId" : {
323+ "Ref" : " VPCB9E5F0B4"
324+ }
325+ }
326+ },
327+ "ProxyALBListener933E9515" : {
328+ "Type" : " AWS::ElasticLoadBalancingV2::Listener" ,
329+ "Properties" : {
330+ "DefaultActions" : [
331+ {
332+ "TargetGroupArn" : {
333+ "Ref" : " ProxyALBListenerTargetsGroup187739FA"
334+ },
335+ "Type" : " forward"
336+ }
337+ ],
338+ "LoadBalancerArn" : {
339+ "Ref" : " ProxyALB87756780"
340+ },
341+ "Port" : 80 ,
342+ "Protocol" : " HTTP"
343+ }
344+ },
345+ "ProxyALBListenerTargetsGroup187739FA" : {
346+ "Type" : " AWS::ElasticLoadBalancingV2::TargetGroup" ,
347+ "Properties" : {
348+ "HealthCheckEnabled" : false ,
349+ "TargetType" : " lambda" ,
350+ "Targets" : [
351+ {
352+ "Id" : {
353+ "Fn::GetAtt" : [
354+ " ProxyApiHandlerEC15A492" ,
355+ " Arn"
356+ ]
357+ }
358+ }
359+ ]
360+ },
361+ "DependsOn" : [
362+ " ProxyApiHandlerInvoke2UTWxhlfyqbT5FTn5jvgbLgjFfJwzswGk55DU1HYF6C33779"
363+ ]
364+ }
365+ },
366+ "Outputs" : {
367+ "APIBaseUrl" : {
368+ "Description" : " Proxy API Base URL (OPENAI_API_BASE)" ,
369+ "Value" : {
370+ "Fn::Join" : [
371+ " " ,
372+ [
373+ " http://" ,
374+ {
375+ "Fn::GetAtt" : [
376+ " ProxyALB87756780" ,
377+ " DNSName"
378+ ]
379+ },
380+ " /api/v1"
381+ ]
382+ ]
383+ }
384+ }
385+ }
386+ }
0 commit comments