1
1
'use strict' ;
2
2
const NOT_FOUND = - 1 ;
3
3
const _ = require ( 'lodash' ) ;
4
+ const awsArnRegExs = require ( '../../../utils/arnRegularExpressions' ) ;
4
5
5
6
module . exports = {
6
7
httpValidate ( ) {
@@ -15,6 +16,10 @@ module.exports = {
15
16
http . path = this . getHttpPath ( http , stateMachineName ) ;
16
17
http . method = this . getHttpMethod ( http , stateMachineName ) ;
17
18
19
+ if ( http . authorizer ) {
20
+ http . authorizer = this . getAuthorizer ( http , stateMachineName ) ;
21
+ }
22
+
18
23
if ( http . cors ) {
19
24
http . cors = this . getCors ( http ) ;
20
25
@@ -107,6 +112,123 @@ module.exports = {
107
112
throw new this . serverless . classes . Error ( errorMessage ) ;
108
113
} ,
109
114
115
+ getIntegration ( http , stateMachineName ) {
116
+ if ( http . integration ) {
117
+ // normalize the integration for further processing
118
+ const normalizedIntegration = http . integration . toUpperCase ( ) . replace ( '-' , '_' ) ;
119
+ const allowedIntegrations = [
120
+ 'LAMBDA_PROXY' , 'LAMBDA' , 'AWS' , 'AWS_PROXY' , 'HTTP' , 'HTTP_PROXY' , 'MOCK' ,
121
+ ] ;
122
+
123
+ // check if the user has entered a non-valid integration
124
+ if ( allowedIntegrations . indexOf ( normalizedIntegration ) === NOT_FOUND ) {
125
+ const errorMessage = [
126
+ `Invalid APIG integration "${ http . integration } "` ,
127
+ ` in function "${ stateMachineName } ".` ,
128
+ ' Supported integrations are:' ,
129
+ ' lambda, lambda-proxy, aws, aws-proxy, http, http-proxy, mock.' ,
130
+ ] . join ( '' ) ;
131
+ throw new this . serverless . classes . Error ( errorMessage ) ;
132
+ }
133
+ if ( normalizedIntegration === 'LAMBDA' ) {
134
+ return 'AWS' ;
135
+ } else if ( normalizedIntegration === 'LAMBDA_PROXY' ) {
136
+ return 'AWS_PROXY' ;
137
+ }
138
+ return normalizedIntegration ;
139
+ }
140
+ return 'AWS_PROXY' ;
141
+ } ,
142
+
143
+ getAuthorizer ( http , functionName ) {
144
+ const authorizer = http . authorizer ;
145
+
146
+ let type ;
147
+ let name ;
148
+ let arn ;
149
+ let identitySource ;
150
+ let resultTtlInSeconds ;
151
+ let identityValidationExpression ;
152
+ let claims ;
153
+ let authorizerId ;
154
+
155
+ if ( typeof authorizer === 'string' ) {
156
+ if ( authorizer . toUpperCase ( ) === 'AWS_IAM' ) {
157
+ type = 'AWS_IAM' ;
158
+ } else if ( authorizer . indexOf ( ':' ) === - 1 ) {
159
+ name = authorizer ;
160
+ arn = this . getLambdaArn ( authorizer ) ;
161
+ } else {
162
+ arn = authorizer ;
163
+ name = this . provider . naming . extractAuthorizerNameFromArn ( arn ) ;
164
+ }
165
+ } else if ( typeof authorizer === 'object' ) {
166
+ if ( authorizer . type && authorizer . authorizerId ) {
167
+ type = authorizer . type ;
168
+ authorizerId = authorizer . authorizerId ;
169
+ } else if ( authorizer . type && authorizer . type . toUpperCase ( ) === 'AWS_IAM' ) {
170
+ type = 'AWS_IAM' ;
171
+ } else if ( authorizer . arn ) {
172
+ arn = authorizer . arn ;
173
+ if ( _ . isString ( authorizer . name ) ) {
174
+ name = authorizer . name ;
175
+ } else {
176
+ name = this . provider . naming . extractAuthorizerNameFromArn ( arn ) ;
177
+ }
178
+ } else if ( authorizer . name ) {
179
+ name = authorizer . name ;
180
+ arn = this . getLambdaArn ( name ) ;
181
+ } else {
182
+ throw new this . serverless . classes . Error ( 'Please provide either an authorizer name or ARN' ) ;
183
+ }
184
+
185
+ if ( ! type ) {
186
+ type = authorizer . type ;
187
+ }
188
+
189
+ resultTtlInSeconds = Number . parseInt ( authorizer . resultTtlInSeconds , 10 ) ;
190
+ resultTtlInSeconds = Number . isNaN ( resultTtlInSeconds ) ? 300 : resultTtlInSeconds ;
191
+ claims = authorizer . claims || [ ] ;
192
+
193
+ identitySource = authorizer . identitySource ;
194
+ identityValidationExpression = authorizer . identityValidationExpression ;
195
+ } else {
196
+ const errorMessage = [
197
+ `authorizer property in function ${ functionName } is not an object nor a string.` ,
198
+ ' The correct format is: authorizer: functionName' ,
199
+ ' OR an object containing a name property.' ,
200
+ ' Please check the docs for more info.' ,
201
+ ] . join ( '' ) ;
202
+ throw new this . serverless . classes . Error ( errorMessage ) ;
203
+ }
204
+
205
+ if ( typeof identitySource === 'undefined' ) {
206
+ identitySource = 'method.request.header.Authorization' ;
207
+ }
208
+
209
+ const integration = this . getIntegration ( http ) ;
210
+ if ( integration === 'AWS_PROXY'
211
+ && typeof arn === 'string'
212
+ && awsArnRegExs . cognitoIdpArnExpr . test ( arn )
213
+ && authorizer . claims ) {
214
+ const errorMessage = [
215
+ 'Cognito claims can only be filtered when using the lambda integration type' ,
216
+ ] ;
217
+ throw new this . serverless . classes . Error ( errorMessage ) ;
218
+ }
219
+
220
+ return {
221
+ type,
222
+ name,
223
+ arn,
224
+ authorizerId,
225
+ resultTtlInSeconds,
226
+ identitySource,
227
+ identityValidationExpression,
228
+ claims,
229
+ } ;
230
+ } ,
231
+
110
232
getCors ( http ) {
111
233
const headers = [
112
234
'Content-Type' ,
@@ -164,4 +286,10 @@ module.exports = {
164
286
165
287
return cors ;
166
288
} ,
289
+
290
+ getLambdaArn ( name ) {
291
+ this . serverless . service . getFunction ( name ) ;
292
+ const lambdaLogicalId = this . provider . naming . getLambdaLogicalId ( name ) ;
293
+ return { 'Fn::GetAtt' : [ lambdaLogicalId , 'Arn' ] } ;
294
+ } ,
167
295
} ;
0 commit comments