Skip to content

Commit 681e3c2

Browse files
author
User
committed
Add BedrockProxy-ExistingRole CloudFormation template for existing IAM role deployment
1 parent 37374e7 commit 681e3c2

File tree

3 files changed

+628
-0
lines changed

3 files changed

+628
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ After creation, you'll see your secret in the Secrets Manager console. Make note
106106

107107
1. Download the CloudFormation template you want to use:
108108
- For Lambda: [`deployment/BedrockProxy.template`](deployment/BedrockProxy.template)
109+
- For Lambda using existing IAM Role and Policy: [`deployment/BedrockProxy-ExistingRole.template`](deployment/BedrockProxy-ExistingRole.template)
109110
- For Fargate: [`deployment/BedrockProxyFargate.template`](deployment/BedrockProxyFargate.template)
110111

111112
2. Sign in to AWS Management Console and navigate to the CloudFormation service in your target region.
Lines changed: 386 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,386 @@
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

Comments
 (0)