Using Jest with CDK tests

We use Siteimprove to crawl some of our web properties and we also protect those same properties with an AWS Web Application Firewall (WAF). To be on the safe side, we’re going to add Siteimprove’s IPs to an allowlist. We have to extend our WAF definition to include an IPSet and then also extend our test coverage.

That’s a lot of IPs

Siteimprove has 86 crawler IPs. First things first, we create a separate siteimprove.ts file to contain all the IPs:

1
2
3
4
5
export const siteimproveIPs: Array<string> = [
'185.229.145.22',
'93.160.60.22',
...
];

That file can then be ingested just like any other code library:

1
2
3
4
5
6
7
import { siteimproveIPs } from './siteimprove';
...
const ipSet = new CfnIPSet(this, 'AllowListIPs', {
addresses: siteimproveIPs,
ipAddressVersion: 'IPV4',
scope: 'CLOUDFRONT',
});

We can then create a rule to allow any traffic originating from those IPs:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
name: 'AllowList',
priority: 0,
statement: {
ipSetReferenceStatement: {
arn: this.allowList.attrArn,
},
},
action: allow: {},
visibilityConfig: {
cloudWatchMetricsEnabled: true,
metricName: 'AllowList',
sampledRequestsEnabled: true,
}
},

Jesting

The CDK assertions library has a number of useful functions but none does what we actually want: to count the number of IP addresses in the IPSet. We can use Jest’s Expect class to bridge the gap:

1
2
3
4
5
6
expect(stack.allowedIPs).toHaveLength(86);
template.hasResourceProperties("AWS::WAFv2::IPSet", {
Addresses: Match.anyValue(),
IPAddressVersion: 'IPV4',
Scope: 'CLOUDFRONT',
});

The first test is Jest evaluating a property on the actual stack, while the subsequent test looks at the generated template. Admittedly, this won’t catch a situation where one of the IPs changed, but that’s not a use case I’m worried about.