API Gateway resource policy in Cloudformation with Conditional Nested Property

There is a blog post on building a CloudFormation Template (CFT) for an API Gateway and Lambda integration on the ReachForce blog. Check that out if you are trying to get the basics for these resources in CloudFormation. This post will build off of the previous template.

Problem

We want to add a resource policy to our CFT to whitelist IPs using CloudFormation for our lower environments. There’s plenty of documentation on resource policies in the AWS docs.

This is the policy we’re going to start with:

{ "Version": "2012-10-17",

"Statement": [{

"Effect": "Allow",

"Principal": "*",

"Action": "execute-api:Invoke",

"Resource": "arn:aws:execute-api:us-east-1:<Account ID>:< API ID >/*",

"Condition": {

"IpAddress":

{ "aws:SourceIp": [ "<IP ADDRESS>", "<IP ADDRESS>" ] }

}

}]}

Basically, we’re preventing all requests other than requests from the two listed IPs from hitting our API.

This can be directly attached in the Resource Policy tab under your API in API Gateway.

When everything is completed in the CFT, the Resource Policy should look the same whether it was pasted or built from the CFT.

Here, the json is converted to YAML, but also including a YAML conditional that determines whether or not this is a prod environment. We’re going to use CFT conditions and CFT parameters in order to determine whether or not we add the policy.

This is done because we want the Prod API to be public and restrict the lower environments to certain IPs.

Parameters:

Environment:

Description: Service Environment Variable

Type: String

Default: dev

AllowedValues:

- dev

- aqa

- stage

- prod

Conditions:

Prod: !Equals [ !Ref Environment, prod ]

Resources:

LogEventAPI:

Type: 'AWS::ApiGateway::RestApi'

Properties:

Name: !Join

- ''

- - SFConfig-API-

- !Ref 'Environment'

Policy:

!If

- Prod

- !Ref "AWS::NoValue"

-

Version: '2012-10-17'

Statement:

- Effect: Allow

Principal: "*"

Resource:

- execute-api:/*/*/*

Action: execute-api:Invoke

Condition:

IpAddress:

aws:SourceIp:

- <IP ADDRESS1>

- <IP ADDRESS2>

The policy requires the resource you want to attach to, but referencing the API within itself will result in a circular dependency. You cannot leave it off, so you need to place the below value, which gets converted into the api of choice for all endpoints.

The key to this blog post is:

Resource:

- execute-api:/*/*/*

Conclusion

This should help if you’re trying to attach a resource policy to API Gateway or build a conditional for a nested YAML property. We can continue to build as much of our infrastructure as code by creating a CFT with all of our necessary resources.

Click me

Recent Posts

Subscribe to the Blog