Combination of AWS API Gateway and Lambda functions is a flag example of every “serverless infrastructure”. When deploying API Gateway with CloudFormation there are two different ways you can define your API: via Swagger template or by directly defining your methods in CloudFormation template.

apigateway+lambda

For API Gateway you need at least 3 basic elements:

  • AWS::ApiGateway::RestApi
  • AWS::ApiGateway::Deployment
  • AWS::ApiGateway::Stage

If you want to find out more about what each of those are, check out APIGateway documentation.

To use a Swagger template, simply use the BodyS3Location parameter on the AWS::ApiGateway::RestApi.
To automatically connect your API calls to the Lambda backend, you’ll need to include additional information inside your Swagger file – a x-amazon-apigateway-integration object, documented here: AWS documentation on x-amazon-apigateway-integration.

If you’re defining the methods and resources within CloudFormation template, you need to define the following objects: AWS::ApiGateway::Resource and AWS::ApiGateway::Method.

For an example simple integration, where API Gateway methods are defined within the CloudFormation template, see:
Using troposphere: apigateway_with_lambda.py
Final JSON template: apigateway_with_lambda.json

To make API Gateway work with a Lambda function, you need to define the Lambda with its role (as needed) and a permission (AWS::Lambda::Permission) for API Gateway to execute your Lambda.

Example of defining the permission:

from troposphere import awslambda

awslambda.Permission(
    "APILambdaPermission",
    Action="lambda:InvokeFunction",
    FunctionName=...,
    Principal="apigateway.amazonaws.com",
    SourceArn=Join("", [
        "arn:aws:execute-api:",
        Ref("AWS::Region"),
        ":",
        Ref("AWS::AccountId"),
        ":",
        Ref(api),
        "/*/GET/*"
    ])
)

The same as CloudFormation JSON:

"APILambdaPermission": {
    "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": ...,
        "Principal": "apigateway.amazonaws.com",
        "SourceArn": {
            "Fn::Join": [
                "",
                [
                    "arn:aws:execute-api:",
                    { "Ref": "AWS::Region" },
                    ":",
                    { "Ref": "AWS::AccountId" },
                    ":",
                    { "Ref": "API" },
                    "/*/GET/*"
                ]
            ]
        }
    },
    "Type": "AWS::Lambda::Permission"
}

Because neither Ref nor GetAtt functions can return an ARN for an API Gateway element, you have to build it yourself within the template. It follows this structure:

arn:aws:execute-api:REGION:ACCOUNT_ID:API_ID:API_STAGE:HTTP_METHOD:RESOURCE

In the example above, we allow the Lambda to pass any GET calls to any stage of the API to any resource within the API. You can obviously modify those as needed.

For a full working example of a working application, check out this stack using troposphere: Image Gateway API.

Was this post helpful to you? Yes!


9 Comments

  1. yugesh

    blank page error when clicking api enpointurl, only show blank page

    • Paulina Budzon

      Hi yugesh!
      No sure what you’re refering to – an example from the post, or your own implementation? I’m happy to help either way, but a bit more detail would help 😉

  2. yugesh

    by clicking the endpoint url of api deployed from cloudformation it shows empty page, i have used your code for deployment

    • Paulina Budzon

      Hi yugesh,
      If you use an inspector in your browser or a command-line tool like curl, can you see what response code you’re getting? If you used the example code (from github), it would have asked you to provide a source code for your Lambda (S3 bucket and a Lambda source file/package in that bucket). You’re mosty likely to find an error logged in this Lambda logs – also, check that this Lambda gets executed correctly. If you want to debug in API Gateway directly, you can use the “test” feature in API Gateway console as well, this will show you exactly what’s happening when a request comes in.
      Hope this helps!

  3. yugesh

    it does not support GET method

    • Paulina Budzon

      Hi yugesh. That’s correct. This piece of code is just an example, and I wanted to keep it as short as possible to avoid clouding what’s going on. I chose to show a POST method as an example, since those generally have a payload, which is another setting in API Gateway. If I chose GET or DELETE for the example I couldn’t have shown how to configure the payload details 🙂 Hope this helps!

  4. yugesh

    how can i deploy multiple lambda in one cloudformation stack

    • Paulina Budzon

      Hi yugesh.

      You can have multiple AWS::Lambda::Function resources in one template. If you’re using the example above, you can have more parameters like the LambdaFileName to specify the source code for each Lambda. It’s generally a good idea to have separate roles and permissions for each Lambda as well to better control access to Lambda and other resources.
      You can take a look at this template as well. It’s a bit messy and injects Lambda source directly into CloudFormation template (which makes it easier if your Lambdas are quite short) and it specifies three Lambdas: LambdaBaseFunction, LambdaReleaseFunction and LambdaCleanESFunction.
      Hope this helps!

  5. yugesh

    how can we trigger multiple lambda function with one api gateway


Leave a comment