Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
CloudFormation API Gateway endpoint calling a Lambda function using proxy integration example.

CloudFormation API Gateway integration to Lambda function

Template that will create the following:

  • API Gateway:
    • Deployed as a REGIONAL endpoint.
    • Single root method, accepting POST requests only, with Lambda proxy integration to a target function.
  • In-line Python Lambda function echoing back requesting users IP address to API Gateway requests:
    • IAM role for Lambda allowing CloudWatch logs access.
    • Permissions for Lambda that allow API Gateway endpoint to successfully invoke function.
  • CloudWatch logs group for Lambda, with 90 day log retention.

After standing up the template, you will be able to make a HTTP POST request to the URL listed as the apiGatewayInvokeURL output value.

$ curl --request POST https://APIGW_ID.execute-api.AWS_REGION.amazonaws.com/call
# Hello there 127.0.0.1

Reference

AWSTemplateFormatVersion: 2010-09-09
Description: My API Gateway and Lambda function
Parameters:
apiGatewayName:
Type: String
Default: my-api
apiGatewayStageName:
Type: String
AllowedPattern: "[a-z0-9]+"
Default: call
apiGatewayHTTPMethod:
Type: String
Default: POST
lambdaFunctionName:
Type: String
AllowedPattern: "[a-zA-Z0-9]+[a-zA-Z0-9-]+[a-zA-Z0-9]+"
Default: my-function
Resources:
apiGateway:
Type: AWS::ApiGateway::RestApi
Properties:
Description: Example API Gateway
EndpointConfiguration:
Types:
- REGIONAL
Name: !Ref apiGatewayName
apiGatewayRootMethod:
Type: AWS::ApiGateway::Method
Properties:
AuthorizationType: NONE
HttpMethod: !Ref apiGatewayHTTPMethod
Integration:
IntegrationHttpMethod: POST
Type: AWS_PROXY
Uri: !Sub
- arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
- lambdaArn: !GetAtt lambdaFunction.Arn
ResourceId: !GetAtt apiGateway.RootResourceId
RestApiId: !Ref apiGateway
apiGatewayDeployment:
Type: AWS::ApiGateway::Deployment
DependsOn:
- apiGatewayRootMethod
Properties:
RestApiId: !Ref apiGateway
StageName: !Ref apiGatewayStageName
lambdaFunction:
Type: AWS::Lambda::Function
Properties:
Code:
ZipFile: |
def handler(event,context):
return {
'body': 'Hello there {0}'.format(event['requestContext']['identity']['sourceIp']),
'headers': {
'Content-Type': 'text/plain'
},
'statusCode': 200
}
Description: Example Lambda function
FunctionName: !Ref lambdaFunctionName
Handler: index.handler
MemorySize: 128
Role: !GetAtt lambdaIAMRole.Arn
Runtime: python3.8
lambdaApiGatewayInvoke:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !GetAtt lambdaFunction.Arn
Principal: apigateway.amazonaws.com
# note: if route *not* at API Gateway root, `SourceArn` would take the form of:
# arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${apiGateway}/${apiGatewayStageName}/${apiGatewayHTTPMethod}/PATH_PART
SourceArn: !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${apiGateway}/${apiGatewayStageName}/${apiGatewayHTTPMethod}/
lambdaIAMRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- sts:AssumeRole
Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Policies:
- PolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Effect: Allow
Resource:
- !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${lambdaFunctionName}:*
PolicyName: lambda
lambdaLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${lambdaFunctionName}
RetentionInDays: 90
Outputs:
apiGatewayInvokeURL:
Value: !Sub https://${apiGateway}.execute-api.${AWS::Region}.amazonaws.com/${apiGatewayStageName}
lambdaArn:
Value: !GetAtt lambdaFunction.Arn
@uchar

This comment has been minimized.

Copy link

@uchar uchar commented Apr 7, 2019

I think
SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${apiGateway}/*/POST/"
should be :
SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:my-api/*/POST/"

@aghalbert

This comment has been minimized.

Copy link

@aghalbert aghalbert commented Apr 12, 2019

Tested @uchar's comment, the change causes an {"message": "Internal server error"} response, so the original value is correct.

@nankan06

This comment has been minimized.

Copy link

@nankan06 nankan06 commented Apr 18, 2019

I am facing an error in AWS::ApiGateway::Deployment. The error is,
'Encountered unsupported property RestApiID'. Any help please?

@jhw

This comment has been minimized.

Copy link

@jhw jhw commented Jun 5, 2019

My guess is u have RestApiID probably badly indented, probably under Integration when it should be under Properties - I did the same

@bmschwa

This comment has been minimized.

Copy link

@bmschwa bmschwa commented Jul 11, 2019

When running

sam local start-api --debug

sam believes there's no apis connected to the lambda function (using sam 0.18.0)

@cam8001

This comment has been minimized.

Copy link

@cam8001 cam8001 commented Dec 2, 2019

@manigct10

This comment has been minimized.

Copy link

@manigct10 manigct10 commented Feb 6, 2020

by using this template, i am getting {"message":"Missing Authentication Token"}
because integration response is not enabled, please solve this issue

@manigct10

This comment has been minimized.

Copy link

@manigct10 manigct10 commented Feb 6, 2020

tell me how to add integration response to get the response from lambda

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment