Skip to content

Instantly share code, notes, and snippets.

@balintsera
Last active December 6, 2021 14:54
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save balintsera/7c45340ad31d1856d6cdb1fd9a09fc7c to your computer and use it in GitHub Desktop.
Save balintsera/7c45340ad31d1856d6cdb1fd9a09fc7c to your computer and use it in GitHub Desktop.
Lambda Proxy Integration with Cloudformation tamplate
apiGateway:
Type: "AWS::ApiGateway::RestApi"
Properties:
Name: "example-api-gw"
Description: "Example API"
ProxyResource:
Type: "AWS::ApiGateway::Resource"
Properties:
ParentId: !GetAtt apiGateway.RootResourceId
RestApiId: !Ref apiGateway
PathPart: '{proxy+}'
apiGatewayRootMethod:
Type: "AWS::ApiGateway::Method"
Properties:
AuthorizationType: NONE
HttpMethod: ANY
Integration:
IntegrationHttpMethod: POST
Type: AWS_PROXY
IntegrationResponses:
-
StatusCode: 200
Uri: !Sub
- "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations"
- lambdaArn: !GetAtt "lambdaFunction.Arn"
ResourceId: !Ref ProxyResource
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: "Node.js Express REST API with a package called aws-serverless-express"
FunctionName: !Ref "lambdaFunctionName"
Handler: lambda.handler
Runtime: nodejs8.10
MemorySize: 128
Role: !GetAtt "lambdaIAMRole.Arn"
Timeout: 60
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}/*/*/*"
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"
- PolicyDocument:
Version: "2012-10-17"
Statement:
- Action:
- "logs:CreateLogGroup"
- "logs:CreateLogStream"
- "logs:PutLogEvents"
- "ec2:CreateNetworkInterface"
- "ec2:DescribeNetworkInterfaces"
- "ec2:DeleteNetworkInterface"
Effect: "Allow"
Resource: "*"
PolicyName: "lambdaVPC"
lambdaLogGroup:
Type: "AWS::Logs::LogGroup"
Properties:
LogGroupName: !Sub "/aws/lambda/${lambdaFunctionName}"
RetentionInDays: 90
@balintsera
Copy link
Author

This is an actually working lambda proxy integration stack. Every request that goes into the API Gateway resource (https://example.com/staging) are forwarded to the lambda, that is being built upon Express and a package called aws-serverless-express that helps the integration. I couldn't found a working example with this exact configuration.

@simonguldstrand
Copy link

Interesting, I will try if this example helps me, many thanks for writing it. However where is the "apiGatewayStageName" resource?

@balintsera
Copy link
Author

Just replace the !Ref with a simple string like "staging" or "development" or add it as a parameter at the top of the template somehow like this:

Parameters: 
  apiGatewayStageName: 
    Type: String
    Default: "dev"
    AllowedValues: 
      - dev
      - staging
      - prod
    Description: Enter dev, staging, prod.

I probably forgot to add it to this gist but I can't find the original.

@simonguldstrand
Copy link

simonguldstrand commented Mar 18, 2020

Hi again,

I read some other examples on this topic.

What do you say towards this combination, is it needed or is it completely unnecessary?

`ApiGatewayRootMethod:
Type: 'AWS::ApiGateway::Method'
Properties:
HttpMethod: ANY
ResourceId: !GetAtt ApiGateway.RootResourceId
RestApiId: !Ref ApiGateway
AuthorizationType: NONE
Integration:
IntegrationHttpMethod: ANY
Type: HTTP_PROXY
Uri: !Sub
- "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaArn}/invocations"
- LambdaArn: !GetAtt "LambdaFunction.Arn"
PassthroughBehavior: WHEN_NO_MATCH
IntegrationResponses:
- StatusCode: "200"

ApiGatewayProxyMethod:
Type: "AWS::ApiGateway::Method"
Properties:
AuthorizationType: "NONE"
HttpMethod: "ANY"
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"
PassthroughBehavior: WHEN_NO_MATCH
IntegrationResponses:
- StatusCode: "200"
ResourceId: !Ref ApiGatewayProxyResource
RestApiId: !Ref ApiGateway`

Sorry but I cant get the code markdown to work..

@onassar
Copy link

onassar commented Feb 4, 2021

Getting a formatting error when pasting your template:

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