はじめに
CloudFrontのWAFv2設定をIaCしたので簡単にまとめてみます。
つくりかた
① waf.ymlのスタック作成(下記IaC参照)
② 「出力」からWebACLのARNをコピー
③ cloudfront.ymlのスタック作成時にコピーしてきたARNを入力(下記IaC参照)
IaC
waf.yml
AWSTemplateFormatVersion: "2010-09-09"
Description: WAF for Cloud Front
Parameters:
ProjectName:
Description: Type of this ProjectName.
Type: String
Resources:
# ------------------------------------------------------------#
# WebACL for CloudFront
# ------------------------------------------------------------#
WebACL:
Type: AWS::WAFv2::WebACL
Properties:
Name: !Sub "${ProjectName}WebACL"
Scope: CLOUDFRONT
DefaultAction:
Block: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: webaclcloudfront
Rules:
- Name: !Sub "${ProjectName}aclrules"
Priority: 0
Action:
Allow: {}
Statement:
IPSetReferenceStatement:
Arn: !GetAtt WAFIPSet.Arn
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: !Sub "${ProjectName}aclrules"
# ------------------------------------------------------------#
# IPSet for WAF
# ------------------------------------------------------------#
WAFIPSet:
Type: AWS::WAFv2::IPSet
Properties:
Name: !Sub "${ProjectName}"
Scope: CLOUDFRONT
IPAddressVersion: IPV4
# アクセスを許可するIPアドレスを指定
Addresses:
- "--.--.--.--/32"
- "--.--.--.--/32"
Outputs:
WebACLArn:
Value: !GetAtt WebACL.Arn
cloudfront.yml
AWSTemplateFormatVersion: "2010-09-09"
Description: Create S3 and CloudFront
Parameters:
ProjectName:
Description: Type of this ProjectName.
Type: String
BucketName:
Description: Type of this BacketName.
Type: String
WebACLArn:
Type: String
Resources:
# ------------------------------------------------------------#
# S3 Policy for CloudFront
# ------------------------------------------------------------#
BucketPolicy:
Type: "AWS::S3::BucketPolicy"
Properties:
Bucket: !Ref Bucket
PolicyDocument:
Statement:
- Action:
- "s3:GetObject"
Effect: Allow
Resource: !Sub "arn:aws:s3:::${BucketName}/*"
Principal:
AWS: !Sub "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ${CloudFrontOriginAccessIdentity}"
# ------------------------------------------------------------#
# S3 Bucket
# ------------------------------------------------------------#
Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${BucketName}
PublicAccessBlockConfiguration:
BlockPublicAcls: True
BlockPublicPolicy: True
IgnorePublicAcls: True
RestrictPublicBuckets: True
AccessControl: Private
# ------------------------------------------------------------#
# CloudFront Distribution
# ------------------------------------------------------------#
AssetsDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
WebACLId: !Sub ${WebACLArn}
Origins:
- Id: S3Origin
DomainName:
Fn::GetAtt: Bucket.DomainName
S3OriginConfig:
OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}"
Enabled: true
DefaultRootObject: index.html
Comment: !Sub ${AWS::StackName} distribution
DefaultCacheBehavior:
TargetOriginId: S3Origin
ForwardedValues:
QueryString: false
ViewerProtocolPolicy: redirect-to-https
CustomErrorResponses:
- ErrorCode: 403
ResponsePagePath: /
ResponseCode: 200
ErrorCachingMinTTL: 0
CloudFrontOriginAccessIdentity:
Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
Properties:
CloudFrontOriginAccessIdentityConfig:
Comment: !Sub ${AWS::StackName}
つまづいたこと
- WAFv2を利用する際はリージョンをus-east-1(バージニア)に指定する必要があった
- cloudformationの画面でリージョンを変更してからスタックの作成をする必要がある
- スタックの作成順はWAF→CloudFront
- WAFにはCloudFrontを参照できるプロパティがないため、先にWAFを作成しCloudFront側から関連付ける必要がある(AWS::CloudFront::DistributionのDistributionConfigで関連付けています)
おわりに
コンソールで環境を立てた際は難しさを感じなかったのですが、思ったより時間がかかってしまいました。
公式ドキュメントを読みながら必要な項目を確認し、まずは自分で雛形を作ることが大事でした。
参考