John
John

Reputation: 11831

AWS CDK - how to grant invoke permissions on a Lambda to API Gateway before deployment?

This question relates to a problem I cam across here: AWS CDK how to create an API Gateway backed by Lambda from OpenApi spec?.

I create an API Gateway using an OpenAPI spec with the AWS CDK. The API is backed by a Lambda and the APIG needs permission to invoke the Lambda.

When I grant permission to APIG to call my lambda:

myLambda.addPermission("PermitAPIGInvocation", Permission.builder()
                                  .action("lambda:InvokeFunction")
                                  .principal(ServicePrincipal.Builder.create("apigateway.amazonaws.com")
                                     .build())
                                  .sourceArn(mySpecRestApi.arnForExecuteApi())
                                  .build());

then I get a 500 error "Invalid permissions on Lambda function" when I try to call the API endpoint until I have redeployed the API. There is no issue when I test the lambda using the APIG console.

How can I have the ApiGateway automatically work without manual intervention? i.e. how do I ensure my lambda has the necessary permission?

Upvotes: 5

Views: 25030

Answers (2)

astef
astef

Reputation: 9488

Not sure what was wrong with your code, but in CDKv2 after this issue fix the following snippet works:

myLambda.addPermission('PermitAPIGInvocation', {
  principal: new ServicePrincipal('apigateway.amazonaws.com'),
  sourceArn: apigw.arnForExecuteApi('*')
});

Upvotes: 4

Martin Muller
Martin Muller

Reputation: 206

It's kind of difficult to configure the API Gateway with the OpenAPI spec. You really need to be cautious to set the correct URI and credentials. Furthermore, credentials seem incapable of substitution. Make sure that your lambda and role is deployed too.

What worked for me was defining the role and set the following in the spec:

const apiRole = new Role(scope, 'apiRole', {
  roleName: 'apiRole',
  assumedBy: new ServicePrincipal('apigateway.amazonaws.com'),
});

apiRole.addToPolicy(new PolicyStatement({
  resources: ['*'],
  actions: ['lambda:InvokeFunction'] }));

and in the spec:

x-amazon-apigateway-integration:
    uri: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:optionsApi/invocations"
    passthroughBehavior: "when_no_match"
    httpMethod: "POST"
    type: "aws_proxy"
    credentials: "arn:aws:iam::111111122222:role/apiRole"

Upvotes: 9

Related Questions