chalice: Authorizer won't work on after deployment.

After each successful deployment, I am facing some problems with Authorizer.

So whenever i ran the following command:

chalice deploy --stage development

My endpoint response is following with incorrect Headers and Payload:

HTTP/1.1 500 Internal Server Error
Connection: keep-alive
Content-Length: 16
Content-Type: application/json
Date: Tue, 09 Jan 2018 05:27:23 GMT
x-amzn-ErrorType: AuthorizerConfigurationException
x-amzn-RequestId: c549c9dc-f4fd-11e7-9066-2d91a1bf8bf4

{
    "message": null
}

My endpoint definition is as following:

@app.route('/dataset', methods=['POST'], authorizer=auth0, cors=True)
  ...

The Solution is to login into console and go to API Gateway > Authorizer > Edit and without any changes click on save. It will ask to Grant permission to invoke the arn click on Grant and re-deploy the API to it’s stage.

step1 step2

After re-deploying same request started working and i am getting correct headers as well:

HTTP/1.1 200 OK
Access-Control-Allow-Headers: Authorization,Content-Type,X-Amz-Date,X-Amz-Security-Token,X-Api-Key
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 3278
Content-Type: application/json
Date: Tue, 09 Jan 2018 05:37:32 GMT
X-Amzn-Trace-Id: sampled=0;root=1-5a54551b-f344e6467c4fb4d33d05a081
x-amzn-RequestId: 2ef0086e-f4ff-11e7-9473-3fe4e73405a2

[]

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 8
  • Comments: 24 (1 by maintainers)

Commits related to this issue

Most upvoted comments

I had exactly the same thing happen when deploying my API using CloudFormation in a SAM YAML template. This was my permission config in the SAM YAML template:

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Resources:
  MyApiGateway: 
    Type: AWS::Serverless::Api
    Properties:
      StageName: Prod
      DefinitionBody:
        swagger: "2.0"  # Had to inline the swagger.yaml so that I don't have to hard code function names into the function uri
  ... snip ...
  MyLambdaAuthoriser:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: lambda_function.lambda_handler
      Runtime: python3.6
  ... snip ...
  ApiAuthLambdaPermission:
    DependsOn: MyApiGateway
    Type: 'AWS::Lambda::Permission'
    Properties:
      Action: 'lambda:InvokeFunction'
      FunctionName: !Ref MyLambdaAuthoriser
      Principal: !Sub "apigateway.amazonaws.com"
      SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${MyApiGateway}/authorizers/*"

The SourceArn is built up using the $ macros, including the API Id which is resolved by ${MyApiGateway}, where MyApiGateway is the name of the serverless api resource.

I’d prefer to have the actual authorizer id at the end of the SourceArn, but I’m not sure how to get it with the macros. This works and is good enough for me.

Just in case someone is having the same issue. I noticed there was a slight difference between the AWS::Lambda::Permission that I created and the one the API Gateway appends when you “edit” the Authorizer config.

In this case the sourceArn was the issue. At the end of my pattern(arn:(aws[a-zA-Z0-9-])😦[a-zA-Z0-9-])+:([a-z]{2}(-gov)?-[a-z]±\d{1})?😦\d{12})?😦.)) I had three asterisks(/*/*/*) to allow everything, my CRUD Lambda function is configured the same way and the API Gateway is able to call it without any issues.

To solve the issue, instead of the three asterisks(/*/*/*), I changed it to (/authorizers/*).

The entire policy looks like this.

"myfunctionnamepermission": {
    "Type": "AWS::Lambda::Permission",
    "Properties": {
        "FunctionName": {
            "Fn::GetAtt": [
                "functionName",
                "Arn"
            ]
        },
        "Action": "lambda:InvokeFunction",
        "Principal": "apigateway.amazonaws.com",
        "SourceArn": {
            "Fn::Join":[
             "",
                [
                   "arn:aws:execute-api:",
                   {
                          "Ref": "AWS::Region"
                   },
                   ":",
                   {
                           "Ref": "AWS:AccountId"
                   },
                   ":",
                   {
                           "Ref": "awsAccountTrackingAPI"
                   },
                   "/authorizers/*"
                ] 
            ]
       }
   }  
}

People who are still facing this issue.

Below steps to fix it on deployment:

  1. Create a new role.
  2. Edit Trust relationships to
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "lambda.amazonaws.com",
          "apigateway.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}                        
        
  1. Create a new policy [allow lambda:invokeFunction] allow resource according to your needs.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "lambda:InvokeFunction",
            "Resource": "*"
        }
    ]
}

Now use this role at the time of deployment in chalice config.json, like below

    "dev": {
      "api_gateway_stage": "api",
      "manage_iam_role": false,
      "iam_role_arn": "created role arn"
    }

Cheers!

Eye opener: https://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-lambda.html

Hi everyone

I think I have figured out the solution for this.

TLDR; The example from the Chalice documentation for setting up a Lambda authorizer contains a a URI of the form:

authorizer = CustomAuthorizer(
    'MyCustomAuth', header='Authorization',
    authorizer_uri=('arn:aws:apigateway:region:lambda:path/2015-03-01'
                    '/functions/arn:aws:lambda:region:account-id:'
                    'function:FunctionName/invocations'))

Note the date component of the Lambda URI: 2015-03-01

To work as expected with API Gateway, this date needs to be: 2015-03-31, -31 not -01!

The Lambda permissions, if you set them up as detailed elsewhere in the thread (eg as per @DaBozUK 's example), work fine as either wildcard or specific authorizer IDs.

To detail the process, I used CloudTrail to monitor exactly what API Gateway is doing when going through the process: API Gateway > Authorizer > Edit and without any changes click on save.

Like @DaBozUK I’m using a YAML template and specifying custom authorizers as:

SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${MyApiGateway}/authorizers/*"

I found via the CloudTrail logs that APIGateway was making an UpdateAuthorizer call on the unchanged edit save, but only replacing the value of the lambda function URI:

    "requestParameters": {
        "restApiId": "XXXXXX",
        "updateAuthorizerInput": {
            "patchOperations": [
                {
                    "path": "/authorizerUri",
                    "value": "arn:aws:apigateway:ap-southeast-2:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-southeast-2:XXXXX:function:CustomAuth/invocations",
                    "op": "replace"
                }
            ]
        },

It was subsequently updating the Lambda invoke permissions as well, but with the authorizer ID:

    "requestParameters": {
        "statementId": "3eb4a3df-3fdb-497b-9557-7dcba38c4289",
        "action": "lambda:InvokeFunction",
        "functionName": "arn:aws:lambda:ap-southeast-2:XXXXX:function:CustomAuth",
        "principal": "apigateway.amazonaws.com",
        "sourceArn": "arn:aws:execute-api:ap-southeast-2:XXXXX:XXXXXX/authorizers/lr4y5i"
    },

Previously I’d tried manually updating the Lambda invoke permissions to use the entire Arn (rather than the wildcard authorizers/*), but this made no difference. This lead me to suspect that the problem was likely to be on the API Gateway side, as testing the authorizer would fail with the permissions error with single millisecond latency.

I also tried the various other flush operations on the API Gateway CLI without success, as well as updating just the name of the authorizer, these didn’t work either.

However, after a lot of false starts I finally noticed when inspecting the logs from the authorizer test on the API Gateway console that the dates on the URIs are subtly different.

Reconfiguring all my templates to use the 2015-03-31 format URI had everything working flawlessly.

I really hope that this insight helps someone else, as this has been a rather frustrating exercise!

@rms1000watt I use terraform and it’s a aws_lambda_permission resource.

However you can set it in the aws console when editing the lambda by clicking the key in the screenshot below and then entering it in the Function policy box

screen shot 2018-08-08 at 19 50 55

Just to report I am having the same issue. But the workaround is not working for me, because I never see the screen in the 2nd step.