Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with Lambda-Permission for API-Gateway #59

Closed
gpuettmann opened this Issue Jan 11, 2017 · 34 comments

Comments

Projects
None yet
@gpuettmann
Copy link

gpuettmann commented Jan 11, 2017

All,

it seems to me that there is a bug with the created LAMBDA-Policy when creating a "ANY"- API-Gateway-Mapping to a Lambda-Function, see the template here:

app_spec.txt

The created Lambda policy includes (for Resource analytics the following condition), and therefore a Lambda permission Error occurs when testing the API-Gateway:

"Condition":{"ArnLike":{"AWS:SourceArn":"arn:aws:execute-api:us-east-1:310073746091:yi1i6eckj4/*/ANY/analytics/*"}}

instead of (resource manual has been created manually afterwards via API-Gateway-Gui):

"Condition":{"ArnLike":{"AWS:SourceArn":"arn:aws:execute-api:us-east-1:310073746091:yi1i6eckj4/*/*/manual/*"}}

Any Idea?

Best Regards,

Gregor
gpuettmann@tecracer.de

@sanathkr

This comment has been minimized.

Copy link
Collaborator

sanathkr commented Jan 26, 2017

Where is the actual error? Does it happen when you make HTTP request to the API, say via Curl?

@sanathkr sanathkr added the question label Jan 26, 2017

@gpuettmann

This comment has been minimized.

Copy link
Author

gpuettmann commented Jan 31, 2017

...yes, the error occurs, when I test the function, Error-Message:
"Tue Jan 31 14:52:20 UTC 2017 : Execution failed due to configuration error: Invalid permissions on Lambda function
Tue Jan 31 14:52:20 UTC 2017 : Method completed with status: 500"

@sanathkr

This comment has been minimized.

Copy link
Collaborator

sanathkr commented Feb 2, 2017

This error is on the APIGateway Web Console UI right? If so, I think this is a known problem

@ghost

This comment has been minimized.

Copy link

ghost commented Apr 23, 2017

Hi, yes it seams that permissions for api gateway to call laambdas are not given to certain endpoints, I have seen it randomly in some resources of mine too

@ryanlitalien

This comment has been minimized.

Copy link

ryanlitalien commented Apr 24, 2017

Hi @sanathkr , I'm experiencing the same problems as the others here. Hopefully I can provide some more info.

I have a SAM with an API and 3 lambdas. Everything is deployed successfully and connected using stage variables as well. My API cannot talk to the lambda because of the permissions issue mentioned above.

I was able to click to change the lambda:
image

and then this is the modal that popped:

image

After I said "OK", the lambda was reachable via API Gateway.

In addition, since I'm using a stage variable, it provided an extra message:

You defined your Lambda function as a stage variable; you must manually give permissions to all the functions you will use. You can do this by running the below AWS CLI command for each function, replacing the stage variable in the function-name parameter with the necessary function name.

aws lambda add-permission --function-name arn:aws:lambda:us-east-1:1234567890:function:${stageVariables.SignupFunctionName} --source-arn 'arn:aws:execute-api:us-east-1:1234567890:aeleq5o0z0/*/GET/v1/accounts/*/groups' --principal apigateway.amazonaws.com --statement-id 123456-96c3-4362-b900-860d14191d9f --action lambda:InvokeFunction

Is there a step missing when the AWS::Serverless::Api is created to access the lambdas?

@ryanlitalien

This comment has been minimized.

Copy link

ryanlitalien commented Apr 24, 2017

Corresponding AWS link regarding this issue: https://forums.aws.amazon.com/thread.jspa?threadID=217143

@ryanlitalien

This comment has been minimized.

Copy link

ryanlitalien commented Apr 26, 2017

@gpuettmann, @Squareomatic Hey, I was able to get this to work by applying permissions on the lambda. I added this config to the sam yaml:

  ConfigLambdaPermission:
    Type: "AWS::Lambda::Permission"
    DependsOn:
    - MyAwesomeApi
    - ConfigHandlerLambdaFunction
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !Ref ConfigHandlerLambdaFunction
      Principal: apigateway.amazonaws.com
@BradNation4Eva

This comment has been minimized.

Copy link

BradNation4Eva commented Oct 25, 2017

@ryanlitalien I'm trying to do the same (API GW + Lambda) but via cloudformation. Would you mind posting a sharable version of your cloudformation template ?
thnx

@haiko

This comment has been minimized.

Copy link

haiko commented Nov 20, 2017

@ryanlitalien
I am too facing difficulties with Lambda permission for the API Gateway. Would you be able to post a complete sam yaml for the permission with a proxy-any example?

@ryanlitalien

This comment has been minimized.

Copy link

ryanlitalien commented Nov 20, 2017

@BradNation4Eva @haiko Unfortunately I don't have access to the source anymore. Essentially you'll need to explicitly add and set permissions within the sam, with the DependsOn so it's run after the API GW and Lambda are created. Good luck 👍

@luebken

This comment has been minimized.

Copy link

luebken commented Nov 30, 2017

I ran into the same issue and fixed it thanks to @ryanlitalien . You can see a simple example here: https://github.com/luebken/hello-sam

Now my question would be if this permission is always needed in an API / Lambda example. And if that is the case if it shouldn't be added to the examples.

@haiko

This comment has been minimized.

Copy link

haiko commented Dec 2, 2017

Works for me, thanks for sharing!

@sanathkr

This comment has been minimized.

Copy link
Collaborator

sanathkr commented Dec 2, 2017

If you are using APIGW Console Test button, then yes this problem still exists. But if you Curl the API or go using browser default SAM settings will work. This is a bug, and the workaround you suggested is only temporarily needed until we fix this.

If you are using separate Swagger, make sure you add the APIs to the events section as well. This will make SAM add correct Lambda::Permissions. See https://github.com/awslabs/serverless-application-model/blob/master/examples/2016-10-31/api_swagger_cors/template.yaml#L24-L35

@jsancho

This comment has been minimized.

Copy link

jsancho commented Dec 30, 2017

@sanathkr
I've been experiencing the same issue with an ANY method*, when using a function name with a stage variable.
That is when using the configuration just as in the api_swagger_cors example in the documentation, and not just from the test button in the console, but when querying externally as well.

The resolution has been using the explicit ConfigLambdaPermission as described by ryanliatien above.

*no issues when using an explicit POST instead of ANY (this could be a red herring though)

@jfuss

This comment has been minimized.

Copy link
Collaborator

jfuss commented Jan 10, 2018

I am reaching out to the relevant teams internally to see what we can do about this. Will update when more information is available.

@AnilRo-Kore

This comment has been minimized.

Copy link

AnilRo-Kore commented Jan 22, 2018

I'm having the problem with nodejs "aws-sdk". while testing the invoking the test getting the internal server error with 500. How can we enable the permission from nodejs "aws-sdk"

@tqhoughton

This comment has been minimized.

Copy link

tqhoughton commented Feb 1, 2018

I am also getting this issue when I use an ANY method for an endpoint.

@jfuss

This comment has been minimized.

Copy link
Collaborator

jfuss commented Feb 12, 2018

Edit: My suggestion below is incorrect, please see @ryanlitalien workaround suggestion above. We are working on getting this addressed. Thanks and sorry for any trouble my suggestion caused.

All,

I spoke with the relevant team and have a path forward. If you are seeing problems calling your API Gateway endpoint (outside of the Test Button on the console), update the Method: ANY to Method: "*" until we can get out the update to this policy.

@jjmschofield

This comment has been minimized.

Copy link

jjmschofield commented Feb 24, 2018

@jfuss the above didn't work for us and sadly we found that the issue still occurred when using curl. The exact scenario was:

  • We had two lambda functions (different handlers) defined
  • We didn't have an API defined (we allowed the transform to handle this)
  • We used package / deploy to deploy
@jfuss

This comment has been minimized.

Copy link
Collaborator

jfuss commented Feb 24, 2018

@jjmschofield Looks like I didn’t test deep enough before suggesting. My fault! You are correct, that doesn’t seem to work. Looks like the only option may be to do what was suggested above by others by applying permissions manually in the template. There is an example above. I will edit my above comment to reflect that it will not work. Sorry for the troubles and thank you for pointing it out.

@lusentis

This comment has been minimized.

Copy link

lusentis commented Apr 3, 2018

Regarding @ryanlitalien solution above:

  • DependsOn is not necessary: declaring the MyAwesomeApi dependency is not needed (the permission does not depend in any way on that specific API); the dependency with ConfigHandlerLambdaFunction is already implicit because you used the !Ref function with ConfigHandlerLambdaFunction as a parameter.

  • it is important to define a SourceARN property: If you add a permission without providing the source ARN, any AWS account that creates a mapping to your function ARN can send events to invoke your Lambda function.

A more correct version would look like:

  ConfigLambdaPermission:
    Type: "AWS::Lambda::Permission"
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !Ref ConfigHandlerLambdaFunction
      Principal: apigateway.amazonaws.com
      SourceARN: arn:aws:execute-api:<region>:<accountNumber>:<restApiId>/<stage>/<method>/<path>

Sources:

@jabalsad

This comment has been minimized.

Copy link

jabalsad commented Apr 4, 2018

Thanks for that update @lusentis - the part about SourceArn is particularly useful (and worrisome). It would be much better if this problem is solved properly within the SAM service/project, instead of us having to create a workaround to create permissions that works appropriately.

@jfuss

This comment has been minimized.

Copy link
Collaborator

jfuss commented Apr 4, 2018

Hey all! So I am back to shed a deeper light into what is going on. This is going to be a longer post with links to....... CODE. :)

So SAM will set/create Lambda Permissions for Api Gateway in this method. The important piece is self._construct_permission call at the end of the method that will return the LambdaPermission resource that will be added to the output CloudFormation Template (the one that run in CloudFormation that creates all the resources).

Where this goes wrong is when we create the resource

Revlevant code snippet:

resource = '${__ApiId__}/' + '${__Stage__}/' + self.Method.upper() + path

You can see that we just add the Method, which is why ANY is in the policy instead of *. This is a great first issue for anyone willing to dive into the code and contribute. Given that we are now fully Open Sourced, anyone willing to take a swing at it? I have happy to guide/help the person if they run into anything :).

@blade2005

This comment has been minimized.

Copy link

blade2005 commented Apr 25, 2018

@jfuss I've not been able to test this change but based on my meager understanding. This patch should work. I'll continue working out my issues with pyenv and try to get a PR sent in.

diff --git a/samtranslator/model/eventsources/push.py b/samtranslator/model/eventsources/push.py
index c155b5a..76d710a 100644
--- a/samtranslator/model/eventsources/push.py
+++ b/samtranslator/model/eventsources/push.py
@@ -396,9 +396,12 @@ class Api(PushEventSource):
         if not function:
             raise TypeError("Missing required keyword argument: function")
 
-        if self.Method is not None:
+        if self.Method is not None and self.Method.lower() != 'ANY'.lower():
             # Convert to lower case so that user can specify either GET or get
             self.Method = self.Method.lower()
+        elif self.Method is not None and self.Method.lower() == 'ANY'.lower():
+            # Special handling required when dealing with ANY requests
+            self.Method = '*'
 
         resources.extend(self._get_permissions(kwargs))
@jfuss

This comment has been minimized.

Copy link
Collaborator

jfuss commented Apr 25, 2018

@blade2005 Send a PR!

The easiest way I have found testing these things, is to write a 'unit test' with a SAM Template and add it here. You can take the output and put it into CloudFormation and test (manually). This is how I normally test new additions before sending to CR and writing integ tests.

If you need further help, its easy to communicate through our slack channel (#samdev). Feel free to ping me there, makes this process faster instead of going back and forth on github issues for help :)

@villasv

This comment has been minimized.

Copy link
Contributor

villasv commented May 23, 2018

If no one picks up @blade2005 until June, I guess I'll give it a try.

@blade2005

This comment has been minimized.

Copy link

blade2005 commented May 23, 2018

Sorry got slammed with a thing at work. Not sure when I'll break free. I'll see if I can't eek out some time this weekend to work on the issue. It should be mostly writing unit tests which I'm horrible at.

@villasv

This comment has been minimized.

Copy link
Contributor

villasv commented May 29, 2018

I applied a similar patch and it broke several tests already (not so "unit"ary heh). Gonna spend some time fixing them before even adding a new one.

@villasv

This comment has been minimized.

Copy link
Contributor

villasv commented May 29, 2018

Well, I guess it's not that simple. Apparently the 'ANY' method is used elsewhere and changing it to '*' at that translation phase will break stuff. Here's what applying that patch caused in one of the tests:

304a305,314
>                 "*": {
>                   "x-amazon-apigateway-integration": {
>                     "httpMethod": "POST",
>                     "type": "aws_proxy",
>                     "uri": {
>                       "Fn::Sub": "arn:aws-us-gov:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ImplicitApiFunction.Arn}/invocations"
>                     }
>                   },
>                   "responses": {}
>                 },
353,362c363
<               "x-amazon-apigateway-any-method": {
<                 "x-amazon-apigateway-integration": {
<                   "httpMethod": "POST",
<                   "type": "aws_proxy",
<                   "uri": {
<                     "Fn::Sub": "arn:aws-us-gov:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ImplicitApiFunction.Arn}/invocations"
<                   }
<                 },
<                 "responses": {}
<               }
---
>                 "x-amazon-apigateway-any-method": {}

So I guess that's not the best place to fix the issue.
Perhaps it should be fixed only in the relevant line mentioned by @jfuss:

resource = '${__ApiId__}/' + '${__Stage__}/' + self.Method.upper() + path

@villasv

This comment has been minimized.

Copy link
Contributor

villasv commented Jun 8, 2018

I believe this issue can be closed since #449 was merged.

@brettstack

This comment has been minimized.

Copy link
Contributor

brettstack commented Jun 8, 2018

@brettstack brettstack closed this Jun 28, 2018

@beary

This comment has been minimized.

Copy link

beary commented Sep 6, 2018

I meet this problem when using lambda authorizer,

This is my template.yml

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: account

Globals:
  Function:
    Timeout: 3
    Runtime: nodejs8.10
Resources:
  AccountRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - dynamodb.amazonaws.com
                - lambda.amazonaws.com
                - apigateway.amazonaws.com
            Action:
              - sts:AssumeRole

  AccountApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: prod
      DefinitionBody:
        swagger: 2.0
        info:
          title: 帐号中心接口
        securityDefinitions:
          CustomAuthorizer:
            type: apiKey
            name: Authorization
            in: header
            x-amazon-apigateway-authtype: custom
            x-amazon-apigateway-authorizer:
              type: token
              authorizerUri: !Sub arn:aws-cn:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${AuthCheckFunction.Arn}/invocations
              authorizerCredentials: !GetAtt AccountRole.Arn
              authorizerResultTtlInSeconds: 60
        paths:
          /account/resources:
            get:
              security:
                - CustomAuthorizer: []
              x-amazon-apigateway-integration:
                httpMethod: POST
                type: aws_proxy
                uri: !Sub arn:aws-cn:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ResourceFunction.Arn}/invocations
          /account/test:
            get:
              x-amazon-apigateway-integration:
                httpMethod: POST
                type: aws_proxy
                uri: !Sub arn:aws-cn:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${TestFunction.Arn}/invocations

  AuthCheckFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: app/
      Description: 验证用户 token
      Handler: handler/authCheck.default
      Role: !GetAtt AccountRole.Arn

  TestFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: app/
      Description: 测试方法
      Handler: handler/test.default
      Role: !GetAtt AccountRole.Arn
      Events:
        TestApiEvent:
          Type: Api
          Properties:
            Path: /account/test
            Method: GET
            RestApiId: !Ref AccountApi

  ResourceFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: app/
      Description: 被保护的资源
      Handler: handler/resource.default
      Role: !GetAtt AccountRole.Arn
      Events:
        TestApiEvent:
          Type: Api
          Properties:
            Path: /account/resource
            Method: GET
            RestApiId: !Ref AccountApi

As you can see, I have specify the role which trust apigateway service to all the functions. /account/test works fine but /account/resource reports

Execution failed due to configuration error: Invalid permissions on Lambda function.

@steven-gong

This comment has been minimized.

Copy link

steven-gong commented Feb 7, 2019

Hi, @beary
I got the same permission issue for the authorizer lambda function, have you got any solution yet?
Cheers

@beary

This comment has been minimized.

Copy link

beary commented Feb 9, 2019

@steven-gong I found solution but I fogot it...
Now I use serverless instead of aws-sam-cli.
It looks like

functions:
  authorize:
    handler: app/authorize.fn
  resource-api:
    handler: app/resource.fn
    events:
      - http:
          path: /test
          authorizer: authorize

or

functions:
  test-fn:
    handler: app/handler.fn
    events:
      - http:
          path: /test
          method: get
          authorizer:
            arn: arn:aws:lambda:ap-southeast-1:999999999:function:account-dev-authorize
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.