-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtemplate.yaml
260 lines (243 loc) · 9.18 KB
/
template.yaml
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
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
AWS
Sample SAM Template for AWS
Parameters:
CognitoAuthorizerArn:
Type: 'AWS::SSM::Parameter::Value<String>'
Description: Reference to Cognito UserPool for the stage
Default: CognitoAuthorizerArn
CognitoUri:
Type: AWS::SSM::Parameter::Value<String>
Description: URI to the OAUTH endpoint of the Cognito client
Default: /NVA/CognitoUri
ApiDomain:
Type: 'AWS::SSM::Parameter::Value<String>'
Description: The Api domain
Default: /NVA/ApiDomain
CustomDomain:
Type: 'AWS::SSM::Parameter::Value<String>'
Description: Custom API to connect this lambda to
Default: CustomDomain
CustomDomainBasePath:
Type: String
Description: Base path mapping in CustomDomain
Default: doi-fetch
CrossrefPlusApiTokenName:
Type: String
Default: CrossRefPlusApiToken
CrossrefPlusApiTokenKey:
Type: String
Default: token
NvaEventsBucketName:
Type: 'AWS::SSM::Parameter::Value<String>'
Default: '/NVA/Events/EventsBucketName'
NvaEventsBucketArn:
Type: 'AWS::SSM::Parameter::Value<String>'
Default: '/NVA/Events/EventsBucketArn'
NvaEventsBusArn:
Type: 'AWS::SSM::Parameter::Value<String>'
Default: '/NVA/Events/EventsBusArn'
NvaEventsBusName:
Type: 'AWS::SSM::Parameter::Value<String>'
Default: '/NVA/Events/EventsBusName'
Globals:
Function:
Timeout: 900
MemorySize: 1798
Runtime: java21
Environment:
Variables:
COGNITO_HOST: !Ref CognitoUri
Api:
Cors:
AllowMethods: "'POST,OPTIONS'"
AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
AllowOrigin: "'*'"
Resources:
ApiAccessLogGroup:
Type: AWS::Logs::LogGroup
NvaFetchDoiFunctionApi:
Type: AWS::Serverless::Api
Properties:
AccessLogSetting:
DestinationArn: !GetAtt ApiAccessLogGroup.Arn
Format: '{ "apiId": "$context.apiId", "requestId": "$context.requestId", "requestTime": "$context.requestTime", "requestTimeEpoch": "$context.requestTimeEpoch", "httpMethod": "$context.httpMethod", "path": "$context.path", "status": "$context.status", "error.message": "$context.error.message" }'
StageName: Prod
EndpointConfiguration: REGIONAL
DefinitionBody:
'Fn::Transform':
Name: AWS::Include
Parameters:
Location: ./docs/openapi.yaml
NvaFetchDoiFunctionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: [lambda.amazonaws.com]
Action: ['sts:AssumeRole']
Policies:
- PolicyName: writeLog
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:*:*'
- PolicyName: readSecret
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- secretsmanager:GetSecretValue
Resource: !Sub 'arn:aws:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:CrossRefPlusApiToken*'
ImportDoiFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: publication-from-doi
Handler: no.unit.nva.doi.fetch.ImportDoiHandler::handleRequest
AutoPublishAlias: live
DeploymentPreference:
Type: AllAtOnce
ProvisionedConcurrencyConfig:
ProvisionedConcurrentExecutions: 1
Role: !GetAtt NvaFetchDoiFunctionRole.Arn
Environment:
Variables:
ALLOWED_ORIGIN: '*'
PUBLICATION_API_HOST: !Ref ApiDomain
CROSSREFPLUSAPITOKEN_NAME: !Ref CrossrefPlusApiTokenName
CROSSREFPLUSAPITOKEN_KEY: !Ref CrossrefPlusApiTokenKey
API_HOST: !Ref ApiDomain
ID_NAMESPACE: !Sub 'https://api.${CustomDomain}/${CustomDomainBasePath}'
Events:
NvaDoi:
Type: Api
Properties:
Path: /
Method: post
RestApiId: !Ref NvaFetchDoiFunctionApi
PreviewDoiFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: publication-from-doi
Handler: no.unit.nva.doi.fetch.PreviewDoiHandler::handleRequest
AutoPublishAlias: live
DeploymentPreference:
Type: AllAtOnce
ProvisionedConcurrencyConfig:
ProvisionedConcurrentExecutions: 1
Role: !GetAtt NvaFetchDoiFunctionRole.Arn
Environment:
Variables:
ALLOWED_ORIGIN: '*'
PUBLICATION_API_HOST: !Ref ApiDomain
CROSSREFPLUSAPITOKEN_NAME: !Ref CrossrefPlusApiTokenName
CROSSREFPLUSAPITOKEN_KEY: !Ref CrossrefPlusApiTokenKey
API_HOST: !Ref ApiDomain
ID_NAMESPACE: !Sub 'https://api.${CustomDomain}/${CustomDomainBasePath}'
Events:
NvaDoi:
Type: Api
Properties:
Path: /preview
Method: post
RestApiId: !Ref NvaFetchDoiFunctionApi
NvaFetchDoiFunctionScalableTarget:
Type: AWS::ApplicationAutoScaling::ScalableTarget
Properties:
MaxCapacity: 10
MinCapacity: 1
ResourceId: !Sub function:${ImportDoiFunction}:live # You need to specify an alias or version here
RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/lambda.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_LambdaConcurrency
ScalableDimension: lambda:function:ProvisionedConcurrency
ServiceNamespace: lambda
DependsOn: ImportDoiFunctionAliaslive # This is your function logical ID + "Alias" + what you use for AutoPublishAlias
NvaFetchDoiFunctionScalingPolicy:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
Properties:
PolicyName: NvaFetchDoiFunctionScalingPolicy
PolicyType: TargetTrackingScaling
ScalingTargetId: !Ref NvaFetchDoiFunctionScalableTarget
TargetTrackingScalingPolicyConfiguration:
TargetValue: 0.70 # Any value between 0.1 and 0.9 can be used here
PredefinedMetricSpecification:
PredefinedMetricType: LambdaProvisionedConcurrencyUtilization
NvaFetchDoiFunctionBasePathMapping:
Type: AWS::ApiGateway::BasePathMapping
Properties:
BasePath: !Ref CustomDomainBasePath
DomainName: !Join [ '.', [ 'api', !Ref CustomDomain ] ]
RestApiId: !Ref NvaFetchDoiFunctionApi
Stage: !Ref NvaFetchDoiFunctionApi.Stage
#============================ Deploy API ============================================================================#
# This solves the problem described here:
# https://stackoverflow.com/questions/41423439/cloudformation-doesnt-deploy-to-api-gateway-stages-on-update
#====================================================================================================================#
ApiGatewayCreateDeploymentLambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
Path: /
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
Policies:
- PolicyName: ApiGatewayAdmin
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- apigateway:POST
Resource: !Sub 'arn:aws:apigateway:${AWS::Region}::/restapis/${NvaFetchDoiFunctionApi}/deployments'
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-lambda-function-code-cfnresponsemodule.html
ApiGatewayCreateDeploymentLambda:
Type: AWS::Lambda::Function
Properties:
Handler: index.lambda_handler
MemorySize: 128
Timeout: 30
Role: !GetAtt ApiGatewayCreateDeploymentLambdaRole.Arn
Runtime: python3.13
Code:
ZipFile: |
import json, boto3
import cfnresponse
client = boto3.client('apigateway')
def lambda_handler(event, context):
responseData = {}
responseStatus = cfnresponse.SUCCESS
if event['RequestType'] == 'Update':
try:
properties = event['ResourceProperties']
response = client.create_deployment(
restApiId=properties['RestApiId'],
stageName=properties['StageName'],
description='Deployed from Custom Resource'
)
except:
responseStatus = cfnresponse.FAILED
cfnresponse.send(event, context, responseStatus, responseData)
ApiGatewayCreateDeploymentCustomResource:
Type: AWS::CloudFormation::CustomResource
Properties:
ServiceToken: !GetAtt ApiGatewayCreateDeploymentLambda.Arn
RestApiId: !Ref NvaFetchDoiFunctionApi
StageName: !Ref NvaFetchDoiFunctionApi.Stage
Timestamp: '${BUILD_TIMESTAMP}'
AuthorizerArn: !Ref CognitoAuthorizerArn