Reputation: 379
I'm trying to build a CFT that creates a Lambda Function and an API, and integrates both of them. I'm currently able to create the Lambda Function and the API, but I can't integrate them.
I thought of using AWS:Lambda:Permission, or specifying the Lambda Function in the AWS:RestApi resource, but both require either ARN value of the Lambda Function or the API ID- Both of which I don't have access to because I'm trying to create, deploy, and integrate Lambda and API Gateway in a SINGLE CFT.
What method or resource should I specify in my CFT that can integrate my lambda function and API Gateway, without needing the Lambda ARN or API Id, since I don't have access to those until after theyre created?
EDIT: If it helps, I'm also using Swagger in my CFT
Upvotes: 2
Views: 2466
Reputation: 2768
So the first thing you have to do is to create the Lambda function.
Make sure lambda is the first thing CFN does. You can do this by specifying the DependsOn
attribute for AWS::ApiGateway::RestApi
- but usually CFN is smart enough to figure it out. Value would be the resource name for AWS::Lambda::Function
.
Define your rest API. In the swagger document, you have to have the custom x-amazon-apigateway-integration
section. Refer x-amazon-apigateway-integration. The uri
attribute of this contains the ARN of the lambda function created earlier. This is not the ARN displayed on lambda console. It can be constructed like this (yaml example). You may need more if you have stages or versions for your lambda.
uri: !Join ["", ["arn:aws:apigateway:", {"Ref": "AWS::Region"}, ":lambda:path/2015-03-31/functions/", !GetAtt <YourLambdaResourceName>.Arn, "/invocations"]]
Also define a role in the credentials
attribute of the x-amazon-apigateway-integration
. This role needs to define permissions for API gateway to assume to call lambda. Sample role & policy in CFN yaml.
ApiGatewayRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: !Join ["-", [{"Ref": "AWS::Region"}, {"Ref": "AWS::StackName"}, "apigateway_lambda_role"]]
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action:
- "sts:AssumeRole"
Principal:
Service:
- "apigateway.amazonaws.com"
Path: "/"
ApiGatewayPolicy:
Type: "AWS::IAM::Policy"
DependsOn: ApiGatewayRole
Properties:
PolicyName: !Join ["-", [{"Ref": "AWS::Region"}, {"Ref": "AWS::StackName"}, "apigateway_lambda_policy"]]
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action: "lambda:InvokeFunction"
Resource:
- "*"
Roles:
-
Ref: ApiGatewayRole
Finally create you lambda permission with function name as ARN of your lambda you just created (GetAtt .Arn) and principal as apigateway.amazonaws.com
. Sample
LambdaPermission1:
Type: "AWS::Lambda::Permission"
Properties:
Action: lambda:InvokeFunction
FunctionName: !GetAtt HandlerFunction.Arn
Principal: apigateway.amazonaws.com
SourceAccount: !Ref AWS::AccountId
SourceArn: !Join ["", ["arn:aws:execute-api:", {"Ref": "AWS::Region"}, ":", {"Ref": "AWS::AccountId"}, ":", <API id>, "/<stage>/<method>/path"]]
API id can be retrieved by using Ref function. Hope this helps.
Upvotes: 2