[CloudFormation] WAFv2(SCOPE: CLOUDFRONT)をIaC化する際に発生するリージョン問題について

AWSでCloudFront Distributionに関連付けるWAFv2リソースをCFnテンプレート化する際の注意点についてのメモ

発生する事象

  • CFnテンプレートの書式が正しくても、CFnを実行するリージョンによって以下のエラーが発生する
    1
    2
    3
    Error reason: The scope is not valid., 
    field: SCOPE_VALUE, parameter:
    CLOUDFRONT (Service: Wafv2, Status Code: 400, Request ID: ...

原因: WAFv2のSCOPE: CLOUDFLONT

  • WAFv2はSCOPEによって、us-east-1にしか生成できないことがある

    • CloudFormation Distributionに関連づけるWAFはコンソールであれば、Globalとするが、実体はus-east-1に生成される
    • CFnでは”SCOPE”というプロパティで、WAFv2がCloudFront向けか、各リージョンに生成するか定義する
      • 以下のように定義した場合、cloudFront Distributionにアタッチ可能なWAFv2リソースとなるが、
        1
        Scope: "CLOUDFRONT"
  • SCOPEについてのルールは公式ドキュメントに以下のように書かれていた

    1
    CLOUDFRONT の場合、米国東部 (バージニア北部) リージョン (us-east-1) で WAFv2 リソースを作成する必要があります。
  • CloudFormtationは選択中のリージョンで実行される

    • SCOPE: CLOUDFRONTのWAFv2リソースがあれば、us-east-1で実行する必要がある
    • 同じテンプレートで定義した他のリソース群も、us-east-1に生成されてしまう
      • 払い出せるリージョンが実質ロックされるので、汎用性が欠けたテンプレートになってしまう…

回避策

以下が考えられる

  • テンプレートの分割
    • WAFv2リソースのみ別にする
      • CloudFront Distributionとの関連付けが面倒ではある
  • us-east-1専用テンプレートとしてルール付けする

同様の問題を経験した人も多いはずなので、そのうちAWS側で解消されるかもしれない

参考

関連記事

CloudFrontのアクセスログをLoggingで収集~aws configで改ざん防止

CloudFrontのLoggin機能を有効化して、任意のS3バケットに格納するよう設定します。
だれが何時何をしたのか?確認可能にすることで、後の監査対策となります。
今回の手法はAWSのベストプラクティスの一つなので覚えておきましょう(資格の試験で良く出ます)

今回の構成

CloudFrontのLogging機能

ログ記録の仕組み

  • ClouFrontの設定からLoggingを有効化するだけで、上記の図のように、S3にアクセスログファイルを自動で格納するように設定可能です。CloudFrontを用いるのであれば、基本的に使う機能として覚えてください。

前提条件

実装手順

Log格納用のs3 bucketを生成/Policy設定

  • aws console/s3
  • バケットを作成する
    • 任意の名称を付ける

バケットの作成

権限設定

  • LogをためるにはCloudFrontからのアクセス許可が必要

  • 必要な権限

    • s3:GetBucketAcl
    • s3:PutBucketAcl
  • s3/任意のbucket/アクセス権限タブ/アクセスコントロール

    • S3 ログ配信グループを選択
    • オブジェクトへのアクセス
      • 以下をチェック
        • オブジェクトの一覧
        • オブジェクトの書き込み
      • 保存
    • ロックパブリックアクセスを無効化
  • バケット用のs3 ACLでFULL_CONTROLを付与する必要もあります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "MakeLogs",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E2TINTLAJ7TK2U"
},
"Action": "*",
"Resource": "arn:aws:s3:::reacq-bucket-for-logs/*"
}
]
}
  • その他のS3 Bucketのプロパティ
    • オブジェクトレベルのログ記録
      • 追加料金がかかっても良ければ、CroudTrailデータイベント機能を使用して記録可能

ログ削除時にSNSトピックにより通知させる

S3 bucket内のログの削除イベントを元に、Amazon SNSトピックを利用して危険通知を自動で出せるように設定します

  • SNSトピックを作成する
    • SNSトピックを利用することで設定した宛先に通知を送ることができます
    • 手順
      • AWS Console/Amazon Simple Notification Service
      • トピックの作成
        • トピック名
          • DeleteAlert
        • 次のステップ
        • 表示名
          • Log-Delete-Alert
        • 他の設定はスルーでOK
          • ※AWSを利用する際の原則として、タグにOwnerとPJ名程度は付けておきましょう
        • トピックの作成
      • トピックができたらARNを控えます
        • ARNはAWSのリソースを一意にに藩閥するための番号
        • 他のサービスと連携する時に必要になります
      • 生成したトピックを選択
      • ”サブスクリプションの作成”
        • プロトコル
          • 今回はEメールを選択
          • 例えばSMSで電話番号を設定するば、よくあるWEBサービスのSMS通知を簡単に実現できます
        • エンドポイント
          • 今回はTeamsの開発チームのチャンネルに流したいので、そのメールアドレスを設定(Teamsはチャンネル毎にメールアドレスを取得できます)
        • サブスクリプションの作成を押下
      • 以上でこのSNSトピックが呼び出された際に、サブスクリプションで規定した連絡先に通知がと届くようになります

Amazon SNS サブスクリプション

  • S3側でイベントを規定
    • S3 Bucket/プロパティタブ
    • イベント
      • ログの削除を検知できるようにイベントを作成します
        • 名前
          • DeleteLog
        • イベント
          • 全てのオブジェクトの削除イベント
        • プレフィックス/サフィックスはスルーでOK
        • 送信先
          • SNSトピック
        • SNSトピックのARN
          • 事前に作成しておいたSNSトピックのARNをコピペ

Loggingの有効化

  • aws console/CloudFront
  • 任意のディストリビューションを選択して、GeneralタブのEditを押下
  • Edit Distribution
    • Loggingをonに変更
    • Bucket for Logs
      • 事前に作成したbucketを選択
    • Yes, Edit

Edit Distribution

ログ記録を確認

  • S3バケットを確認するとログの記録が開始されたことを確認できます

Cloud Trail

aws configで改ざんを防止

S3にせっかくログを貯めても、削除されてしまっては無意味であるため、改ざん防止策が必須となります。

  • 改ざん対策
    • aws configでログの格納先であるs3 bucketをトラッキング
    • ログデータの削除/編集を検知

料金

  • アクセスログの料金

    • つまりS3の料金対策だけでOK
      1
      アクセスログの作成は、CloudFront のオプション機能です。アクセスログの作成を有効にしても追加料金はかかりません。ただし、Amazon S3 でのファイルの保存とアクセスについて通常の Amazon S3 料金が発生します (ファイルの削除はいつでもできます)。
  • 対策例

    • ログを非常事態以外は見ない場合
      • Glacier等の廉価版を利用
    • 直近のログは素早く確認したい場合
      • S3のライフサイクルポリシーを利用して、一定期間の経過後にGlacierに移行させる

参考

関連記事

[AWS WAF] CloudFrontへアクセス可能なソースIPを社内イントラに制限

AWS WAFを用いて、CloudFrontへのアクセスを制御する手法を解説します。CloudFrontディストリビューションの生成やS3へのコンテンツのHostingは事前に完了している前提とします。それらの手順は以下の記事にまとめています。

前提とする構成

Serverless Architecture

S3単体であれば、バケットポリシーによるソースIP制限も可能ですが、CloudFrontを挟む場合は、アクセス元となるCloudForntがブロックされてしまいます。そこで、S3がアクセスを許可する対象をCloudFrontに絞り、CloudFront側でIP制限をかける必要があり、AWS WAFを利用することで実現可能です。

AWS WAF(Web Application Firewall)

AWS WAF

  • AWS WAF
    • 名前の通り、Webアプリケーションを守るファイアウォールです
    • 主な機能
      1. SQL インジェクションやクロスサイトスクリプティングなどの一般的な攻撃パターンの防御
        • AWSにおける基本的な防御策の一つであり、CloudFrontとWAFをコンテンツ~ユーザ間に挟むのが定石です
        • 更に守りを固めるのであればAWS Shieldも付けるイメージ
      2. 定義した特定のトラフィックパターンを除外するルールを作成して、トラフィックがアプリケーションに到達する方法を制御
        • 今回利用するのはこちら

手順

WAFで以下のトラフィックパターンを実現します

  • 社内イントラ(複数IP)からのアクセスのみを許可
  • その他をブロック

IP set設定

まず、アクセス可能なIPアドレスをリスト化します

  • IP Sets
    • Create IPsetを選択

IP Sets

  • Crate IP set
    • ip set name
      • 今回は会社のイントラネットのIPを登録するので”intranet”に設定
    • IP addressesに許可したいIPアドレスを列挙
    • Create IP set

Create IP set

WEB ACL設定

次に設定したIP setからのアクセスのみに絞るルールを作ります

  • WEB ACLs/Create web ACLを選択

WEB ACLs

  • WEB ACL設定
    • Resource type
      • CloudFront distributionsを指定
    • 他は任意の名称を設定
      • 今回はip-limit-acl

Describe web ACL and associate it to AWS resources

  • Add rules and rule groups
    • ここでIPをルールとして設定します
    • Add my own rules and rule groupsを選択

Add rules and rule groups

  • Add my own rules and rule groups
    • Rule type
      • IP setを選択
    • Rule
      • 任意の名称を設定
    • IP Set
      • 事前に作ったものを選択
    • Action
      • Allow
    • Add rule

Add my own rules and rule groups

  • Default web ACL action for requests that don’t match any rules
    • Blockに設定しておく

Add rules and rule groups

  • デフォルトのブロックと任意のIP setにアクセスを許可するルールが設定されたことを確認してNext

  • Set rule priority

    • そのままでNext
  • Configure metrics

    • そのままでNext
  • Review and create web ACL

    • 設定に問題がなければCreate web ACL

CloudFrontディストリビューションに適応

  • WEBACL完成後にCloudFrontに適応
    • Associated AWS resourcesタブ
    • Add AWS resources

Associated AWS resources

  • 作成済みのCroudFrontディストリビューションを選択
    • Add

Add AWS Resources

以上でOK。試しにCloudFrontのURLにアクセスすると、許可したIP以外からはブロックされます。

参考

関連記事

その他

AWS CloudFront~S3のアクセス制御まとめ/署名付きURL

  • AWSのCloudFront x S3の構成におけるアクセス制御の手法について解説します
    • ソースIPの絞り方
    • コンテンツへのアクセスを経路をCloudFrontに限定

CroudFrontのアクセス制限

CroudFront Image

  • 2ルートを考える必要があります

    • ①CroudFrontにキャッシュされたコンテンツへのアクセス

      • 署名付き URL または署名付き Cookie の使用が求められるように CloudFront を設定可能です。
      • 以下の制限を指定
        • 最終日時。この日時以降、URLが無効化
          • 解約したユーザーずっとアクセス可能な状態を防げます
        • (オプション) URL が有効になる日時。
        • (オプション) コンテンツへのアクセスに使用可能なコンピュータの IP アドレスまたはアドレス範囲
    • ②オリジンへの直接のアクセス

      • CroudFrontを介した通信に限定する事が可能です
      • オリジン
        • S3やEC2等のコンテンツを実際にHostingしている場所のこと
  • 詳細

CroudFront経由以外のS3バケットへのアクセスをシャットアウトする

  • CroudFrontの大きな役割の一つが攻撃者とコンテンツの間の緩衝材となることです
    • 直接S3へアクセス可能な状態では上記の効果を生めないため、基本的に遮断したほうが良いです

Distributionの作成時に設定

  • Origin Settings
    • Restrict Bucket Access
      • Yesに設定 ⇒ CloudFront経由でのみ閲覧可能に絞る
      • Grant Read Permissions on Bucket
        • Yesに設定 ⇒ S3バケットのPolicyを自動で変更

Distribution作成後に設定

  • AWS Console/CroudFront
  • 対象のDistributionを選択
  • Origins and Origin Groupsタブ
    • 対象のOrigin Domainを選択肢てEditを押下

Origins and Origin Groups

  • Restrict Bucket Access
    • Yesに変更
      • Grant Read Permissions on Bucket
        • Yesに設定 ⇒ S3バケットのPolicyを自動で変更
  • Yes, Edit

Edit Origin

  • バケットポリシーの変化を確認

    • 以下が自動的に追記されていた
      1
      2
      3
      4
      5
      6
      7
      8
      9
      {
      "Sid": "2",
      "Effect": "Allow",
      "Principal": {
      "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity XXXXXXXXXXX"
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::XXXXXXXXXX/*"
      }
  • 注意点

    • 元々書いていたポリシーに追記される形式になるため、どちらもEffectで書かれていれば二通りの通信を許可することになります

CloudFront エッジキャッシュ内のファイルへのアクセス制限

署名付きURLでソースIPを限定する

  • (オプション) コンテンツへのアクセスに使用可能なコンピュータの IP アドレスまたはアドレス範囲。
  • ポリシーステートメントの例
    • 任意のIPアドレスからのみディレクトリ内の全ファイルにアクセス可能
1
2
3
4
5
6
7
8
9
10
11
{ 
"Statement": [
{
"Resource":"http://d111111abcdef8.cloudfront.net/training/*",
"Condition":{
"IpAddress":{"AWS:SourceIp":"192.0.2.0/24"},
"DateLessThan":{"AWS:EpochTime":1357034400}
}
}
]
}

S3 Bucket Policyの記載例

アクセス制限内容

  • ソースIP
    • SourceIpで定めた二点のみ
  • アクセス経路
    • Principalで定めたCroudFrontディストリビューション経由のみ
  • アクション
    • GetObject=読み込みのみ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity XXXXXXXX"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::xxxxxxxxxx/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"XXX.XXX.XX.X/24",
"XXX.XXX.XX.X/24"
]
}
}
}
]
}

参考

s3 ssl化 https化(CloudFront/ACM/Route53)

S3の静的WEBホスティングで公開中のアプリのURLはデフォルトではhttpになります。Cloud Frontを用いてhttpsにしてセキュリティを向上させます。

基礎知識

静的コンテンツ配信を行うAWSアーキテクチャのベストプラクティス

architecture

  • S3でコンテンツをHostingして、ユーザーとの間にCloud FrontとRoute53を挟むのが基本です
    • それぞれの説明は後述します

SSL

  • SSL(Secure Sockets Layer)とは
    • データ通信を暗号化し、盗聴や改ざんを防ぐプロトコル
    • httpsから始まるWEBサイトはSSLを導入しています
    • 非SSL(http)の場合、Googleがデフォルトで警告マークを出すので、サイトやWEB APの信頼度が大幅に下がります

Cloud Front

  • CDN
    • 配信パフォーマンスの向上
    • コスト削減
  • セキュリティの向上

Route53

手順

  • 想定する状況
    • AWS Consoleで設定
    • CloudFormationやSAMで作るケースもあると思います

Cloud FrontとS3を連携

  • まずは以下の構成を作ります
    CloudFront x s3
  • AWS Console/サービス/CloudFront

  • Create Distributionを押下
    Cloud Front Menu

  • 配信方法はWEBを選択
    Delivery Method

ディストリビューションの作成

  • Origin Settings

    • Origin Domain Name
      • Hosting中のs3バケットを選択
    • Restrict Bucket Access
      • YesにするとCloudFront経由でのみ閲覧可能になる
      • Grant Read Permissions on Bucket
        • これを設定しておくとS3のバケット側の設定を自動でやってくれる
  • Default Cache Behavior Settings

    • そのままでもOK
    • Viewer Protocol Policy
      • Redirect HTTP to HTTPS
        • これにしておくとhttpからhttpsへリダイレクトさせてくれる
  • Distribution Settings

    • Alternate Domain Name(CNAMEs)
      • 証明書を取得したドメイン名を設定
        • 複数のドメイン名を使用する場合は、改行区切り
      • ドメインを取得していなければスルー
    • SSL Certificate
      • Defaultの証明書でOK
      • 独自SSLを使用する場合
        • 事前にIAMに証明書をアップロードしておく
    • Default Root Object
      • S3の静的Hostingの設定で指定した、インデックスドキュメント(Angularであればindex.html)を入力
    • Create Distributionを押下
  • 20分程度でStatusがDeployedになるので、完了後にアクセスしてみる

  • URL

    • XXXX以降はディストリビューションのGeneralタブのDamain Nameに表示されているものを確認
      1
      https://xxxxx.cloudfront.net
      image
  • Route53や独自ドメインを利用しないのであれば以上で完了

CloudFrontの注意点:キャッシュコントロール


独自ドメインを活用する場合

  • 前提
    • 独自ドメインを取得してRoute53に登録済み
    • これから取得する人はお名前.com等を使ってみてください

ACM(AWS Certificate Manager)で証明書を作成

  • AWS Console/AWS Certificate Manager/証明書のリクエスト

  • ドメイン名を入力

    • ”この証明書に別の名前を追加”よりドメインの別名を設定

ACM

requst

  • CloudFrontにACMで作成した証明書を設定
  • Ditribution/Generalタブ/Edit
  • SSL Certificate
    • Custom SSL Certificateを選択
    • プルダウンから先ほどACMに登録した証明書を選択
  • 保存

Route53の独自ドメインのエイリアスの向き先を変更する

  • AWS Console/サービス/Route53

  • ホストゾーンから登録済みのドメインを選択

  • 対象の行を選択

    • タイプ:Aのもの
  • レコードセットの編集

    • エイリアス先を変更
      • [CloudFront ディストリビューション] - 対象のドメイン名 を選択
  • レコードセットを保存

  • 確認
    • 以下にアクセスしてみる
      1
      https://{独自ドメイン}

参考

@EventEmitter @Input @Output @ViewChild ACM AMP API Gateway AR AR.js AR.js Studio AWS AWS Amplify AWS Budgets AWS Cost Explorer AWS SDK for JavaScript AddThis Adobe XD Alexa Amazon CloudWatch Amazon Honycode Amazon SNS Android Angular Angular Material AngularFire AppSync Augury C CDN CI/CD Cloud Craft Cloud9 CloudFormation CloudFront CloudTrail Cognito Cost Anomaly Detection Cubase ai Cubasis LE DTM Disqus DynamoDB Elgato HD 60S Firebase Firebase Hosting Former2 Github Github Actions Github.com GithubEnterprise GithubPages Google Chrome Google Cloud Shell GraphQL Hexo Hosting IAM Ionic JSON JavaScript LadioCast Logging LowCode MFA MS Authentication MacBook Pro 16 Mind Node NETDUETTO Netflix Party Netlify Network NoCode Observable PO PdM Promise RPA ReactiveForm Recognition Route53 S3 SAM(Serverless Application Model) SAR SSL SYNCROOM Schematics ScrumInc Serverless Service Siri Sitemap Spark AR Steinberg UR44C Teams Touch Cast Studio Treetable TypeScript UI UI Bakery WAF WAFv2 WEB Page Dev WEB会議 WebAR WebSocketAPI Webhook Windows Power Automate Wireshark aot async/await aws config cloud9 display.land draw.io e2e test filter() forkJoin() google search console hexo-generator-amp iOS iPad Pro iPhone icarus map() mat input mat tree mat-checkbox mat-input mat-selection-list mmhmm ngFor plantUML popIn Aladdin2 then() vscode ”global is not defined” らくがきAR アジャイル アジャイル開発 クロスプラットフォーム ショートカット スクラム スクラム開発 テレワーク ファイル操作 ブラウザ型IDE プロダクトオーナー プロダクトマネージャー プロトタイピング リモートセッション 共同開発 双方向データバインディング 待ち合わせ処理 認定スクラムマスター 静的WEB Hosting 静的WEBサイトHosting
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×