CloudFrontでIP制限するためのWAFをCloudFormationで作成してみた

CloudFrontでIP制限を実現する方法の一つがIP制限ルールを設定したWAFをCloudFrontに紐づけることです。今回はそのWAFをCloudFormationで作成してみました。
2019.09.24

こんにちは、大阪オフィスのかずえです。今回は、IP制限をするWAFをCloudFormationで書いてみた、という内容です。

なぜやるのか

一言で言うと、CloudFrontにもIP制限をかけたかったからです。

とあるシステムの検証環境の作成を行なっていました。検証環境ですので、基本的に社内の人間しかアクセスしません。逆に外部からアクセスされるのは不都合です。というわけでアプリケーション全体にIP制限をかけたいと思いました。

ALBやEC2にはセキュリティグループを使ってアクセス元のIP制限を簡単にかけることが可能です。ですがこのアプリケーションではCloudFrontも使っておりました。CloudFrontではセキュリティグループを使うことはできません。IP制限をしたかったら、以下のいずれかしかなさそうです。(他の方法をご存知の方いらっしゃったら教えてください!)

  1. CloudFrontにWAFを紐付けて、WAFで特定IPのみ許可するルールを設定する
  2. Lambda@EdgeでIP制限する処理を書く
  3. (オリジンがALBの場合、)リスナールールでX-Fowarded-forヘッダーのルールを設定する。ただしX-Fowarded-for値は偽装できるので前述の2案に比べると確実性は落ちる。また、ネガティブキャッシュが残る可能性がある。(許可IP以外からアクセスされて403が返されたページに、その後許可IPからのアクセスがあった場合、キャッシュが効いて403を返してしまう)

というわけで、今回は1.のWAFを使う方法をCloudFormationでやってみました。

設定内容詳細

以下エントリで設定詳細が解説されていますので、こちらを参照ください。

AWS WAFを使って接続できるIPアドレスを制限してみた

CloudFormation テンプレート

では本題のCloudFormationテンプレートです。アクセス許可するCIDRは2セット設定できるようにしています。

---
AWSTemplateFormatVersion: '2010-09-09'
Description: create WAFWebACL that allows accesses from white list CIDR
Parameters:
NameTagPrefix:
Type: String
Default: test
Description: Prefix of Name tags.
WAFWebACLMetricName:
Type: String
Default: testWebACL
MinLength: 1
MaxLength: 128
AllowedPattern: '[a-zA-Z0-9]*'
CIDR1:
Type: String
Description: White List CIDR ¥#1
AllowedPattern: '^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}[1-9]?([0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/(8|16|24|32)$'
CIDR2:
Type: String
Description: White List CIDR ¥#2
AllowedPattern: '^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}[1-9]?([0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/(8|16|24|32)$'
Resources:
WhiteListCIDRSet:
Type: AWS::WAF::IPSet
DeletionPolicy: Retain
Properties:
Name: 'White List CIDR Set'
IPSetDescriptors:
- Type: IPV4
Value: !Ref CIDR1
- Type: IPV4
Value: !Ref CIDR2
WAFIPRule1:
Type: AWS::WAF::Rule
DeletionPolicy: Retain
Properties:
Name: 'WAF IP Rule #1'
MetricName: WAFRule1
Predicates:
- DataId:
Ref: WhiteListCIDRSet
Type: IPMatch
Negated: 'false'
WAFWebACL:
Type: AWS::WAF::WebACL
DeletionPolicy: Retain
Properties:
Name: !Sub "${NameTagPrefix}-WebACL"
DefaultAction:
Type: BLOCK
MetricName: !Ref WAFWebACLMetricName
Rules:
- Action:
Type: ALLOW
Priority: 1
RuleId:
Ref: WAFIPRule1
Outputs:
WAFWebACLID:
Value: !Ref WAFWebACL
Export:
Name: !Sub ${NameTagPrefix}-WAFWebACLID

いつかCloudFrontにIP制限をかけたくなった時に、このテンプレートがお役に立てば幸いです。