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

こんにちは、大阪オフィスのかずえです。今回は、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制限をかけたくなった時に、このテンプレートがお役に立てば幸いです。