-
Notifications
You must be signed in to change notification settings - Fork 0
/
cloudformation.yml
465 lines (435 loc) · 15.7 KB
/
cloudformation.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
AWSTemplateFormatVersion: "2010-09-09"
Description: Stack for setting up EC2, RDS, and API Gateway
Parameters:
DBInstanceClass:
Type: String
Default: db.t3.micro
Description: RDS instance class
DBName:
Type: String
Default: courseQA
Description: RDS database name
LLMEndpointName:
Type: String
Description: LLM endpoint name
EmbeddingEndpointName:
Type: String
Description: Embedding endpoint name
RegionName:
Type: String
Default: us-west-2
Description: Region name
LLMInference:
Type: String
Description: LLM inference component name
DockerImageName:
Type: String
Default: ilamparithi10/cic-course-qa-backend
Description: Docker image name
BucketName:
Type: String
Default: institutionname
Description: BucketName for storing course documents
SecretId:
Type: String
Description: Secret manager secret id
DBUserKey:
Type: String
Default: DBUser
Description: Secret manager key for DB user
DBPasswordKey:
Type: String
Default: DBPassword
Description: Secret manager key for DB password
Resources:
IAMRole:
Type: AWS::IAM::Role
Properties:
RoleName: CourseQA
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: ec2.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: S3FullAccessPolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:*
Resource: "*"
- PolicyName: TextractFullAccessPolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- textract:*
Resource: "*"
- PolicyName: SageMakerFullAccessPolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- sagemaker:*
Resource: "*"
- PolicyName: RDSFullAccessPolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- rds:*
Resource: "*"
- PolicyName: SecretsManagerFullAccessPolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- secretsmanager:*
Resource: "*"
S3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref BucketName
InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: "/"
Roles:
- !Ref IAMRole
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
EnableDnsSupport: true
InstanceTenancy: default
Subnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.0.0/24
MapPublicIpOnLaunch: true
AvailabilityZone: !Select
- 0
- !GetAZs ""
Subnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.1.0/24
MapPublicIpOnLaunch: true
AvailabilityZone: !Select
- 0
- !GetAZs ""
Subnet3:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.2.0/24
MapPublicIpOnLaunch: true
AvailabilityZone: !Select
- 1
- !GetAZs ""
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: InternetGateway
InternetGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
Subnet1RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Subnet1Route:
Type: AWS::EC2::Route
DependsOn: Subnet1RouteTable
Properties:
RouteTableId: !Ref Subnet1RouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
Subnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref Subnet1
RouteTableId: !Ref Subnet1RouteTable
RDSInstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "Security group for RDS instance"
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 5432
ToPort: 5432
SourceSecurityGroupId: !GetAtt EC2SecurityGroup.GroupId
DBSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: Subnets available for the RDS instance
SubnetIds:
- !Ref Subnet2
- !Ref Subnet3
DBInstance:
Type: AWS::RDS::DBInstance
Properties:
DBName: !Ref DBName
Engine: "postgres"
DBInstanceClass: !Ref DBInstanceClass
AllocatedStorage: "20"
MasterUsername: !Sub "{{resolve:secretsmanager:${SecretId}:SecretString:${DBUserKey}}}"
MasterUserPassword: !Sub "{{resolve:secretsmanager:${SecretId}:SecretString:${DBPasswordKey}}}"
DBSubnetGroupName: !Ref DBSubnetGroup
MultiAZ: false
VPCSecurityGroups:
- !Ref RDSInstanceSecurityGroup
EC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: "ami-0395649fbe870727e"
SubnetId: !Ref Subnet1
InstanceType: "t2.micro"
SecurityGroupIds:
- !GetAtt EC2SecurityGroup.GroupId
UserData:
Fn::Base64: !Sub |
#!/bin/bash
sudo yum update -y
sudo yum install -y docker
sudo systemctl start docker
sudo docker pull ilamparithi10/cic-course-qa-backend
sudo docker run -d \
-e secret_id=${SecretId} \
-e db_user_key=${DBUserKey} \
-e db_password_key=${DBPasswordKey} \
-e postgres_hostname=${DBInstance.Endpoint.Address} \
-e postgres_port=5432 \
-e postgres_database_name=${DBName} \
-e bucket_name=${BucketName} \
-e llm_endpoint_name=${LLMEndpointName} \
-e embedding_endpoint_name=${EmbeddingEndpointName} \
-e region_name=${RegionName} \
-e llm_inference_component_name=${LLMInference} \
-p 80:5000 \
-p 5432:5432 \
${DockerImageName}
IamInstanceProfile: !Ref InstanceProfile
EC2SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "Enable outbound access to PostgreSQL port"
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 5432
ToPort: 5432
CidrIp: 10.0.0.0/16
UserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: UserPool
UsernameAttributes:
- email
Schema:
- Name: email
AttributeDataType: String
Mutable: false
Required: true
- Name: name
AttributeDataType: String
Mutable: true
Required: true
Policies:
PasswordPolicy:
MinimumLength: 8
RequireLowercase: true
RequireNumbers: true
RequireSymbols: true
RequireUppercase: true
AutoVerifiedAttributes:
- email
EmailVerificationSubject: "Your verification code"
EmailVerificationMessage: "Please use the following code to verify your email address: {####}"
UserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
UserPoolId: !Ref UserPool
ClientName: UserPoolClient
ExplicitAuthFlows:
- ALLOW_REFRESH_TOKEN_AUTH
- ALLOW_USER_SRP_AUTH
GenerateSecret: false
CogAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
Name: CognitoAuthorizer
RestApiId:
Ref: Api
Type: COGNITO_USER_POOLS
IdentitySource: method.request.header.Authorization
ProviderARNs:
- Fn::GetAtt:
- UserPool
- Arn
Api:
Type: "AWS::ApiGateway::RestApi"
Properties:
Name: ProxyApi
BinaryMediaTypes:
- application/pdf
- text/html
- multipart/form-data
Resource:
Type: "AWS::ApiGateway::Resource"
Properties:
ParentId: !GetAtt Api.RootResourceId
RestApiId: !Ref Api
PathPart: "{proxy+}"
UserResource:
Type: AWS::ApiGateway::Resource
Properties:
ParentId: !GetAtt Api.RootResourceId
RestApiId: !Ref Api
PathPart: "users"
RegisterResource:
Type: AWS::ApiGateway::Resource
Properties:
ParentId: !Ref UserResource
RestApiId: !Ref Api
PathPart: "register"
ProxyMethod:
Type: "AWS::ApiGateway::Method"
Properties:
HttpMethod: ANY
ResourceId: !Ref Resource
RestApiId: !Ref Api
AuthorizationType: COGNITO_USER_POOLS
AuthorizerId: !Ref CogAuthorizer
RequestParameters:
method.request.path.proxy: true
Integration:
CacheKeyParameters:
- "method.request.path.proxy"
RequestParameters:
integration.request.path.proxy: "method.request.path.proxy"
IntegrationHttpMethod: ANY
Type: HTTP_PROXY
Uri: !Sub http://${EC2Instance.PublicIp}/{proxy}
RegisterMethod:
Type: "AWS::ApiGateway::Method"
Properties:
HttpMethod: POST
ResourceId: !Ref RegisterResource
RestApiId: !Ref Api
AuthorizationType: NONE
Integration:
IntegrationHttpMethod: POST
Type: HTTP_PROXY
Uri: !Sub http://${EC2Instance.PublicIp}/users/register
# Enabling cors ref: https://stackoverflow.com/questions/40292888/enable-cors-for-api-gateway-in-cloudformation-template
RegisterOptionsMethod:
Type: AWS::ApiGateway::Method
Properties:
AuthorizationType: NONE
ResourceId: !Ref RegisterResource
RestApiId: !Ref Api
HttpMethod: OPTIONS
Integration:
IntegrationResponses:
- StatusCode: 200
ResponseParameters:
method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
method.response.header.Access-Control-Allow-Methods: "'POST,OPTIONS'"
method.response.header.Access-Control-Allow-Origin: "'*'"
ResponseTemplates:
application/json: ""
PassthroughBehavior: WHEN_NO_MATCH
RequestTemplates:
application/json: '{"statusCode": 200}'
Type: MOCK
MethodResponses:
- StatusCode: 200
ResponseModels:
application/json: "Empty"
ResponseParameters:
method.response.header.Access-Control-Allow-Headers: false
method.response.header.Access-Control-Allow-Methods: false
method.response.header.Access-Control-Allow-Origin: false
ProxyOptionsMethod:
Type: AWS::ApiGateway::Method
Properties:
AuthorizationType: NONE
ResourceId: !Ref Resource
RestApiId: !Ref Api
HttpMethod: OPTIONS
Integration:
IntegrationResponses:
- StatusCode: 200
ResponseParameters:
method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
method.response.header.Access-Control-Allow-Methods: "'DELETE,GET,PUT,POST,OPTIONS'"
method.response.header.Access-Control-Allow-Origin: "'*'"
ResponseTemplates:
application/json: ""
PassthroughBehavior: WHEN_NO_MATCH
RequestTemplates:
application/json: '{"statusCode": 200}'
Type: MOCK
MethodResponses:
- StatusCode: 200
ResponseModels:
application/json: "Empty"
ResponseParameters:
method.response.header.Access-Control-Allow-Headers: false
method.response.header.Access-Control-Allow-Methods: false
method.response.header.Access-Control-Allow-Origin: false
Deployment:
DependsOn:
- ProxyMethod
- RegisterMethod
- RegisterOptionsMethod
- ProxyOptionsMethod
Type: "AWS::ApiGateway::Deployment"
Properties:
RestApiId: !Ref Api
StageName: Prod
Outputs:
BackendAPIURL:
Value: !Sub "https://${Api}.execute-api.${RegionName}.amazonaws.com/Prod"
UserPoolId:
Value: !Ref UserPool
UserPoolClientId:
Value: !Ref UserPoolClient