Using yaml cloud formation, I have configured a lambda AWS::ApiGateway::Authorizer on an AWS::ApiGateway::RestApi. I have successfully tested the authorizer and the gateway API methods through the console, however when I hit the deployed api with curl it fails with status code 500:
< HTTP/2 500
< content-type: application/json
< content-length: 16
< date: Fri, 25 Mar 2022 09:45:06 GMT
< x-amzn-requestid: 07f7793c-406c-44c2-b184-dbbfd3f2a4fc
< x-amzn-errortype: AuthorizerConfigurationException
< x-amz-apigw-id: PiNNVFTTPHcFwyA=
< x-cache: Error from cloudfront
I see this error in the API-Gateway-Execution log:
Execution failed due to configuration error: API Gateway does not have permission to assume the provided role arn:aws:iam::XXXXXXXXXXXX:role/auth
Execution failed due to configuration error: Authorizer error
As I understand it, API Gateway is attempting to execute the lambda authorizer, but does not have a trust relationship allowing it to execute the lambda despite being granted said trust thusly:
lambdaAuthorizerFunctionRole:
Type: AWS::IAM::Role
Properties:
Path: /
RoleName: auth
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
# allow lambda and apigateway to assume the policies attached to this role
Service: [ lambda.amazonaws.com, apigateway.amazonaws.com ]
Action: sts:AssumeRole
Policies:
...
Can someone please explain to me what I'm doing wrong here? Any help would be much appreciated.
UPDATE:
Thanks Marcin. This solved the problem and has freed me from my long and lonely efforts.
The error API-Gateway-Execution log message misled me. It states that 'API Gateway does not have permission to assume the provided role', which, in the absence of any meaningful AWS documentation, I took to mean that it required a trust relationship brought by an AssumeRolePolicyDocument in an AWS::IAM::Role.
This issue was particularly difficult to resolve, since I could not find a clear explanation for exactly what the missing permission was, given that it could refer missing 'AuthorizerCredentials' in the 'AWS::ApiGateway::Authorizer'. I'd tried adding permissions there to no effect. In my working solution, I have removed the AuthorizerCredentials altogether. It's not clear to me what those credentials are actually for, since they were not needed. Adding them didn't hurt, but didn't solve the problem.
I thought the missing permissions might also have to do with the authorizer lambda's AssumeRolePolicyDocument not granting trust to apigateway.amazonaws.com as mentioned elsewhere. But no. Only lambda.amazonaws.com is required as the Principal, as is usually the case.
Lastly, I note that this problem was exacerbated by the fact that the Cloud Formation update-stack operation silently fails to update the authorizer: While debugging, removing the authorizer from the AWS::ApiGateway::RestApi and the AWS::ApiGateway::Methods' AuthorizerId properties silently left the authorizer in tact. That is, with the authorizer removed by the update, I still experienced the 'API Gateway does not have permission to assume the provided role' error. Deleting and recreating the stack overcame this blockage.
CodePudding user response:
The preferred way to allow an API to invoke your function is through AWS::Lambda::Permission, not IAM roles. So you can create something as the below:
permission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !GetAtt function.Arn
Action: lambda:InvokeFunction
Principal: apigateway.amazonaws.com
SourceArn: <arn:aws:execute-api:region>:<accountid>:<api_id>/authorizers/<authorizer_id>