Skip to content

[aws-cdk-study] Sample stack of AWS S3 + CloudFront + WAFv2 deployed by aws-cdk

Notifications You must be signed in to change notification settings

rikubuilds/aws-cdk-cloudfront-s3-hosting

Repository files navigation

S3 + CloudFront + WAFv2 をCDKで構築するサンプル

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

  • WAFv2リソースはus-east-1リージョンに
  • その他のリソースはそれ以外のリージョンに(検証ではap-northeast-1を使用)

deployする方法と,実装でハマったポイントをまとめました.

CDKは,2021.04.13時点での最新バージョンである,1.98.0を使用しました.

動機

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

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

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

Overview

architecture

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の参照は通常の方法では不可能なため,今回は,こちらを参考に,カスタムリソースを使った参照クラスを実装して解決しました.

ハマったポイント

  1. WAFv2 リソースのリージョン制限

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

  2. CDKで他リージョンのSSM Parameter Storeを参照する方法

const param = ssm.StringParameter.valueForStringParameter(this, `param-name`);

の方法で参照できるのは,そのスタックの同一リージョンのParameter Storeのみです.

cross-region参照するため,カスタムリソースを使った方法の情報にたどり着くまで苦労しました...

  1. CDKでCloudFrontへのWAF WebACLの関連付ける方法

    @aws-cdl/aws-wafv2モジュールにCfnWebACLAssociationというクラスがあり, 最初,これを使えばよいかと思ったのですが, こちらで関連付けできるのは,API Gateway REST API等,CloudFront distribution以外の場合でした.

    CloudFrontと関連付ける場合は,CloudFrontWebDistribution側で,WebACLを指定する必要があります.

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

webACLのプロパティ名はwebACLIdとなっていますが,WAFv2を使う場合WebACLのARNを指定する点にも注意してください.

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を参照する方法

About

[aws-cdk-study] Sample stack of AWS S3 + CloudFront + WAFv2 deployed by aws-cdk

Resources

Stars

Watchers

Forks

Packages

No packages published