Search code examples
amazon-web-servicesaws-lambdaaws-api-gatewayamazon-iam

AWS::Lambda::Permission vs AWS::IAM::Role to give API Gateway permission to invoke Lambda function


I'm programatically building a CloudFormation template that sets up API Gateway and Lambda functions to serve HTTP requests. Everything is going well and I am successfully provisioning both services and tying them together, but currently API Gateway doesn't have permission to invoke my Lambda functions which is causing an Internal Server Error response.

In Googling how to grant this permission I came across two ways to do it.

First way: AWS::Lambda::Permission

As we can see from this example I came across, I can create a AWS::Lambda::Permission resource that allows API Gateway to invoke my function:

  lambdaApiGatewayInvoke:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !GetAtt lambdaFunction.Arn
      Principal: apigateway.amazonaws.com
      SourceArn: !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${apiGateway}/${apiGatewayStageName}/${apiGatewayHTTPMethod}/

Second way: AWS::IAM::Role

I also stumbled on this article which gives API Gateway permission to invoke the Lambda using an IAM role:

  ApiGatewayIamRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Sid: ''
            Effect: 'Allow'
            Principal:
              Service:
                - 'apigateway.amazonaws.com'
            Action:
              - 'sts:AssumeRole'
      Path: '/'
      Policies:
        - PolicyName: LambdaAccess
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: 'Allow'
                Action: 'lambda:*'
                Resource: !GetAtt LambdaFunction.Arn

My question is, which way is best? AWS::Lambda::Permission seems easiest if all I want to do is give API Gateway permission to invoke my functions, but AWS::IAM::Role seems like it'd give me more flexibility in future by being able to add additional permissions down the line.

Do I have that correct? Is there a best practice here?


Solution

  • Use what AWS docs recommend to use, which is resource-based policy:

    Amazon API Gateway gets permission to invoke your function from the function's resource-based policy.

    This way, you can indicate that lambda function is in charge of its own interactions permissions.