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.
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}/
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?
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.