serverless / serverless

⚡ Serverless Framework – Effortlessly build apps that auto-scale, incur zero costs when idle, and require minimal maintenance using AWS Lambda and other managed cloud services.
https://serverless.com
MIT License
46.47k stars 5.72k forks source link

API Gateway Custom Authorizer not referencing ‘provisioned’ alias lambda when specifying provisioned concurrency #7726

Closed chrismcbride76 closed 4 years ago

chrismcbride76 commented 4 years ago

This is an issue that was first reported in the forums and that I'm also encountering. https://forum.serverless.com/t/api-gateway-custom-authorizer-not-referencing-provisioned-alias-lambda-when-specifying-provisioned-concurrency/11424.

Framework Core: 1.70.1
Plugin: 3.6.11
SDK: 2.3.0
Components: 2.30.10

I have a lambda function and custom authorizer, both using provisioned concurrency:

authenticator:
general:
name: authenticatorGeneral
type: TOKEN
# Cache authentication result for 5 minutes
resultTtlInSeconds: 300
identitySource: method.request.header.Authorization
identityValidationExpression: Bearer (.*)

functions:
  authenticatorGeneral:
    handler: src/authenticator.general
    provisionedConcurrency: 1
    reservedConcurrency: 10
    memorySize: 512
  proxy:
    handler: src/handler.server
    provisionedConcurrency: 1
    reservedConcurrency: 10
    memorySize: 1024
    events:
      - http:
          method: any
          path: /{proxy+}
          cors: true
          authorizer: ${self:custom.authenticator.general}

Both these lambda functions are created with the provisioned alias and provisioning set as expected. API Gateway is mapping to the correctly aliased function for the proxy endpoint:

aura-auth-service-prod-proxy:provisioned

This works as expected, and does not suffer cold starts. If I check API Gateway for the custom authorizer mapping, it is not using the ‘provisioned’ alias:

aura-auth-service-prod-authenticatorGeneral

So I assume this will use ‘latest’, which is not provisioned? This is not working as expected and is suffering from cold starts.

medikoo commented 4 years ago

@chrismcbride76 thanks for report. It indeed looks as a bug.

As I see problem is that here: https://github.com/serverless/serverless/blob/522e9c0ff822295a19447939b641459118e0cb37/lib/plugins/aws/package/compile/events/apiGateway/lib/authorizers.js#L43 We do not resolve path to lambda as here: https://github.com/serverless/serverless/blob/522e9c0ff822295a19447939b641459118e0cb37/lib/plugins/aws/package/compile/events/apiGateway/lib/method/integration.js#L77-L78

PR with a fix is welcome!

raiss commented 4 years ago

Is there a work around available for this issue. I cannot workout how it can be done via the AWS API Gateway Console.

steare573 commented 4 years ago

This workaround worked for us. We added some CloudFormation as an extension in the resources section to specifically reference the provisioned alias name generated by serverless. Note that the alias reference name (ReadAuthProvConcLambdaAlias) and the properties (ReadAuthApiGatewayAuthorizer and ReadAuthLambdaPermissionApiGateway) in this example will differ based on the name of your authorizer function. For this example, ours was named readAuth. You can always check the output from the "sls --package" command to determine the proper alias to reference in the CloudFormation snippet.


resources:
  - extensions:
      # This is tells the authorizer to use a provisioned lambda
      ReadAuthApiGatewayAuthorizer:
          Properties:
            # IMPORTANT: this is based on the name of your authorizer!
            AuthorizerUri:
              'Fn::Join':
                - ''
                - - 'arn:'
                  - Ref: 'AWS::Partition'
                  - ':apigateway:'
                  - Ref: 'AWS::Region'
                  - ':lambda:path/2015-03-31/functions/'
                  - Ref: 'ReadAuthProvConcLambdaAlias'
                  - '/invocations'
      ReadAuthLambdaPermissionApiGateway:
        Properties:
          FunctionName:
            Ref: 'ReadAuthProvConcLambdaAlias'