11'use strict' ;
22const NOT_FOUND = - 1 ;
33const _ = require ( 'lodash' ) ;
4+ const awsArnRegExs = require ( '../../../utils/arnRegularExpressions' ) ;
45
56module . exports = {
67 httpValidate ( ) {
@@ -15,6 +16,10 @@ module.exports = {
1516 http . path = this . getHttpPath ( http , stateMachineName ) ;
1617 http . method = this . getHttpMethod ( http , stateMachineName ) ;
1718
19+ if ( http . authorizer ) {
20+ http . authorizer = this . getAuthorizer ( http , stateMachineName ) ;
21+ }
22+
1823 if ( http . cors ) {
1924 http . cors = this . getCors ( http ) ;
2025
@@ -107,6 +112,123 @@ module.exports = {
107112 throw new this . serverless . classes . Error ( errorMessage ) ;
108113 } ,
109114
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+
110232 getCors ( http ) {
111233 const headers = [
112234 'Content-Type' ,
@@ -164,4 +286,10 @@ module.exports = {
164286
165287 return cors ;
166288 } ,
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+ } ,
167295} ;
0 commit comments