LoginSignup
7
1

More than 1 year has passed since last update.

S3 + CloudFront + WAFv2 をCDKで構築した時にregion等でハマった話

Last updated at Posted at 2021-04-13

「CloudFront経由でS3にアクセスする + WAFv2でアクセス制限をかける」リソース一式を構築するAWS CDKのサンプルです.

  • WAFv2リソースはus-east-1リージョンのスタックとして
  • S3バケットとCloudFrontはそれ以外のリージョンのスタックとして(検証ではap-northeast-1を使用)

deployする方法と,実装でハマったポイントをまとめました.
CDKは,2021.04.13時点での最新バージョンである,1.98.0を使用しました.

動機

  • S3でホスティングしている既存ウェブサイト(ap-northeast-1)に独自ドメインを割り当てたかったが,バケット名がドメイン名と異なっており,CloudFrontの導入が必要となった.

  • CloudFront経由でのアクセスに,IPベースでのアクセス制限をかける必要があり,WAFでのアクセス制御も必要となった.

  • 既存リソースはCDKで管理されており,新たに追加するリソースもCDKの管理下にしたかった.

Overview

CDK サンプルコード

architecture.png

01-waf stack

WAFv2 WebACLを管理するスタックです.

CloudFormation - WAFv2 - Scopeに書かれているように,WAFv2のACLをCloudFrontに関連付けたい場合,US East (N. Virginia) Region (us-east-1)へWAFv2リソースを作成する必要があります.そこで,app.tsで明示的にリージョンを指定しています.

const wafStack = new WafStack(app, '01-waf', {
  // (省略)
  env: {
    account: stackEnv.account,
    region: "us-east-1", // ここ
  },
  // (省略)
});

実装当初,この制限に気づかず,deployエラーでハマりました.(WAFv1の場合,リージョン制限は無いようです.)
後述のスタックで作成するCloudFrontとの関連付けには,作成したWebACLのARNが必要となります.
ここでは,SSM Parameter StoreにWebACL ARNを格納しました(これを参照する方法は後述).

02-web-dist stack

  • コンテンツを格納するS3バケット
  • S3バケットを向き先としたCloudFront distribution

を管理するスタックです.技術検証のため,01-waf スタックと別リージョンにしています.

S3バケット,CloudFront web distributionを定義し,先に作成したWAFv2 ACLと関連付けていくのですが,
ここでの問題は,US East (N. Virginia) RegionのParameter Storeに格納されているWebACL ARNを参照しなければならない点です.
cross-regionの参照は通常の方法では不可能なため,こちらを参考にカスタムリソースを使った参照クラスを実装して解決しました.

ハマったポイント

  • WAFv2 リソースのリージョン制限

WAFv2のWebACLをCloudFrontに関連付ける場合,ACLをus-east-1に作成する必要がありました.

  • CDKでの他リージョンのSSM Parameter Store参照
  const param = ssm.StringParameter.valueForStringParameter(this, `param-name`);

の方法で参照できるのは,そのスタックの同一リージョンのParameter Storeのみです.
cross-region参照するため,カスタムリソースを使った方法の情報にたどり着くまで苦労しました...

  • CDKでのCloudFrontへのWAF WebACLの関連付け

@aws-cdl/aws-wafv2モジュールにCfnWebACLAssociationというクラスがあり,最初,これを使えばよいかと思ったのですが,こちらで関連付けできるのは,API Gateway REST API等,CloudFront distribution以外の場合でした.
CloudFrontと関連付ける場合は,CloudFrontWebDistribution側で,WebACLを指定する必要があります.
webACLのプロパティ名はwebACLIdとなっていますが,WAFv2を使う場合WebACLのARNを指定する点にも注意してください.

    this.distribution = new cloudfront.CloudFrontWebDistribution(
      this, "website-distribution",
      {
        webACLId: webAclArn,
        // 以下省略
      }
    );

ACLの中身

本サンプルでは,IPアドレスベースの制限としています.アクセスを許可するIPアドレスは,
cdk.context.jsonに記述して,CDK context valueとしてインポートしています.
サンプル公開用では,ダミーのIPアドレスを記述しているので,検証したいIPアドレスに書き換えてください.

{
  "allowed_ips": [
    "10.0.0.0/16"
  ]
}

Reference

本スタック実装にあたり参考にさせていただいたサイトを,トピック別に掲載しました.

WAFを使ったCloudFrontへのアクセス制限

CDKを使ったWAFリソースのdeploy

AWS WAFの解説

WAF WebACL for CloudFrontの作成リージョンに関する注意

AWS CDKで他のリージョンのssm parameter storeを参照する方法

7
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1