Enabling global API Gateway stage logging using CloudFormation

July 18, 2017 by Paulina BudzoƄ

Enabling logging in API Gateway for your stage is fairly easy. You go into the Console, setup a role for API Gateway to use for logging, find the stage and enable logs. It will enable logging for all methods within that stage. Doing the same configuration using CloudFormation is not completely obvious though, as the stage object’s MethodSettings property seems to allow you to only do that for a specific resource and method.

In short, this is what we are trying to accomplish within the settings for the whole Stage: api-gateway-stage-logging

MethodSetting in CloudFormation requires a specific ResourcePath and HttpMethod, which seems to suggest, you need to specify those properties for every path and method in your API. Luckily, that’s not entirely true. While you can use this property for a very specific resource and method, you can also use it for ALL resources and method.

To do that, using troposphere, you can specify it like this:

1
2
3
4
5
6
7
8
9
MethodSettings=[
    apigateway.MethodSetting(
            DataTraceEnabled=True,
            HttpMethod="*",
            LoggingLevel="INFO",
            ResourcePath="/*",
            MetricsEnabled=True
        )
],

or directly in JSON:

1
2
3
4
5
6
7
8
9
    "MethodSettings": [
              {
                "DataTraceEnabled": true,
                "HttpMethod": "*",
                "LoggingLevel": "INFO",
                "MetricsEnabled": true,
                "ResourcePath": "/*"
              }
    ]

In order for that to work, you also need to create a Role for API Gateway to write to logs and let API Gateway know what that role is:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from awacs import aws, sts
from troposphere import GetAtt
from troposphere import apigateway, iam

cloudwatch_role = iam.Role(
    "CloudWatchRole",
    Path="/",
    AssumeRolePolicyDocument=aws.Policy(
        Statement=[
            aws.Statement(
                Effect=aws.Allow,
                Action=[sts.AssumeRole],
                Principal=aws.Principal(
                    "Service", ["apigateway.amazonaws.com"]
                )
            )
        ]
    ),
    ManagedPolicyArns=[
        "arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs"
    ],
)

api_gateway_account = apigateway.Account(
    "APIGatewayAccount",
    CloudWatchRoleArn=GetAtt(cloudwatch_role, "Arn")
)

You only have to set the above once (i.e. in one CloudFormation stack in a region within your AWS account), as the API Gateway account setting is global for the whole region.

Posted in: CloudFormation