Open5

AWS CloudFront

mocknmockn

目的

AWS CloudFrontの仕様や実装上の注意点等について記載する

mocknmockn

CloudFrontについて

概要

  • CloudFrontとは
    • グローバルに配置された、キャッシュサーバー。
    • CDN(コンテンツキャッシュサービス)
  • ディストリビューション
    • Cloud Frontのオブジェクト。(EC2のインスタンス的な)
    • ドメイン毎に割り振られるCloudFrontの設定。
    • デフォルトでは「xxxx.cloudfront.net」が ディストリビューション のドメイン名とし
      て割り当てられる。
    • CNAME エリアスを利用して代替 (独自) ドメイン名の指定が可能。
  • オリジン
    • 配信するコンテンツの元のサーバ。
    • 静的コンテンツ、動的コンテンツの両方がキャッシュ可能。
    • 静的:S3、動的:ELB、API Gateway、EC2など。
    • オンプレやほかのクラウドなど独自のオリジンを設定することも可能。
  • ビヘイビア
    • キャッシュのルール。

機能・特徴

キャッシュコントロール

  • "Cache-Control max-age"を指定して最大・最小TTLを設定する。
    • デフォルトは24時間
  • キャッシュファイルの無効化(キャッシュ削除)
    • パスを指定もしくはワイルドカードで削除が可能。
    • エッジキャッシュからファイルを無効にします。ビューワーが次にファイルをリクエストしたときに、CloudFront はオリジンに戻ってファイルの最新バージョンをフェッチします。
  • 動的コンテンツキャッシュ
    • オリジンサーバに対してHeader、Cookie、Query Stringといった情報をフォワードすることで対応可能。カスタムヘッダーにも対応。

ポリシー

  • Behavior 単位で個別に設定する必要があったが、Policy の実装によって同一内容を再利用することが容易になる。
  • Cache Policy
    • キャッシュの保持期間 と キャッシュキーに関する設定を行う。
  • Origin Request Policy
    • CloudFrontからオリジンサーバーにリクエストを送る場合に、利用者から送信された Header, Cookie, クエリを付与して送信するか否かを設定する。
    • Cache Policyで指定している各値に加えて、ここで定義された値をオリジンサーバーに転送する。
    • Origin Request Policy に設定していない値であっても Cache Policy に含まれている値は自動的にオリジンサーバーへと送信される。キャッシュキーには使わないが、オリジンサーバーに送信したい値を定義する。
    • Origin Request Policy に Authorization ヘッダを含めることはできない。Authorization ヘッダをオリジンに渡したければ Cache Policy の Header に whitelist として Authorization を含めることで解決可能
      • もしくは、 AllViewer のポリシー を利用すると Authorization ヘッダを含めて全てのヘッダを送付できる。

セキュリティ

  • HTTPS 対応 (強制リダイレクト / HTTPS のみ許可)

  • SSL 証明書

    • cloudfront.net ドメインの SSL 証明書は標準で利用可能。
    • SNI / 専用IPアドレス / Certification Manager(ACM)。
    • ACMを利用するとカスタムドメインに対して無料で証明書が発行できる。
  • オリジン暗号化通信

    • カスタムオリジンのみエッジとオリジン間の暗号通信方式を制御できる。
  • オリジンカスタムヘッダー

    • オリジンサーバ毎に固定でヘッダーの追加もしくはクライアントからのリクエストヘッダーの上書きが可能
    • Shared-Secret
      • CloudFront とオリジン間で任意のヘッダーおよびヘッダー値を取り決め、オリジン側でヘッダー値のチェックを行うことで、カスタムオリジンは CloudFrontからのアクセスのみに制御する
    • リクエストヘッダーの調整
      • Cross-Origin Request Sharing(CORS) 通信時に、クライアントブラウザーのバージョンなどにより、ブラウザが適切なヘッダーを付与しない場合に、強制的に設定。
  • 署名付き URL/Cookie (有効期間指定)

    • 署名のないリクエストをブロックする。
    • Behavior単位で指定可能。
    • URLかCookieを選択可能。
  • AWS WAF 連携

    • AWS WAF で定義した Web ACL を CloudFront ディストリビューションに適用
      • CloudFront をサービスの前段に配置することでサイトの保護を実現
      • AWS:XSS / GEO 制限 / IP アドレス制限 / サイズ制限 / SQLインジェクション / ヘッダー, クエリ, リクエストボティの文字列, 正規表現マッチング
  • AWS Shield による DDoS 攻撃対策

    • DDoS 攻撃を緩和するサービス。デフォルトで有効になっており無料で利用できる。

ロギング・分析

  • Access Log
    • 任意のS3 Bucketに出力。
    • Athea -> QuickSight でデータ可視化・分析可能
  • CloudFront Reports & Analytics
    • Cache Statistics / Popular Objects / Usage /Top Referrers / Viewers
    • CloudFront の利用状況における傾向分析として利用。
    • Monitoring / Alarms
      • リアルタイムでディストリビューションへのアクセス状況 / Lambda@Edge 関数のリアルタイム監視として利用。

エッジコンピューティング

  • CloudFront Functions
    • CloudFront エッジロケーションで軽量の JavaScript コードを実行できるようにするサーバーレススクリプトプラットフォームのこと。
    • Lambda@Edge
  • CloudFront FunctionsとLambda@Edgeの違い
    • Lambda@EdgeはRegional Edge Cacheで実行されるが、CloudFront FunctionsはEdge Locationで実行される。CloudFront Functionsの方がエンドユーザーにより近いところで処理を行えるため高速にレスポンスができる。
    • CloudFront Functionsはメモリや実行時間などの上限が厳しい。
    • CloudFront Functionsは1秒あたり数百万規模までスケーリングする事がで切るが、Lambda@Edgeのデフォルトの同時実行数は1000で、必要に応じて事前に上限緩和申請を行って同時実行数を緩和する必要がある。
  • 使い分け
    • CloudFront Functions:シンプル/軽い処理(Headerの書き換え、Cookieの挿入など)
    • Lambda@Edge:複雑/重い処理(画像変換、DBや外部サービス、APIへのアクセスなど)

コスト

課金形態

  • 従量課金
  • 無料枠あり
    • 1 か月あたり 1 TB のインターネットへのデータ転送
    • 1 か月あたり 10,000,000 件の HTTP または HTTPS リクエスト
    • 1 か月あたり 200 万件の CloudFront Functions呼び出し
    • 無料の SSL 証明書の利用

課金対象

  • メイン
    • 送信データ転送 (インターネット/送信元)
      • Amazon CloudFront エッジロケーションから転送されたデータの量です。
      • Amazon S3 や Elastic Load Balancing などの AWS のサービスから転送されるデータは課金対象外。
    • HTTP/HTTPS リクエスト
      • リクエストの数とタイプ (HTTP または HTTPS)、およびリクエスト元の地理的リージョンです。
  • オプション
    • CloudFront Functions
      • 100 万件の呼び出しあたり 0.10 USD (1 回の呼び出しごとに 0.0000001 USD)。
    • Lambda@Edge
      • リクエスト 100 万件あたり 0.60 USD (リクエスト 1 件あたり 0.0000006 USD)。
    • 無効化リクエスト
      • 毎月、無効化をリクエストした最初の 1,000 パスまでは追加料金がありません。それ以降は、無効化をリクエストしたパスごとに 0.005 USD の料金が発生します。
    • フィールドレベル暗号化リクエスト
      • フィールドレベル暗号化は、追加の暗号化を必要とするリクエストの数に基づいて課金されます。
      • 標準の HTTPS リクエスト料金に加えて、CloudFront がフィールドレベル暗号化を使用して暗号化した 10,000 件のリクエストごとに 0.02 USD が課金されます。
    • 専用 IP の独自 SSL
      • 専用 IP バージョンの独自 SSL 証明書のサポートを使用する CloudFront ディストリビューションに関連付けられた独自 SSL 証明書ごとに、毎月 600 USD をお支払いいただきます。
      • この月額料金は時間で比例配分されます。

利用手順

コンテンツ配信設定の流れ

  1. Amazon S3 バケット, ALB, EC2, オンプレミスにある独自の HTTP サーバーなどのオリジンサーバーを設定
  2. ファイルをオリジンサーバーにアップロード
  3. CloudFront ディストリビューションを作成
  4. CloudFront がドメイン名を割り当て
  5. ディストリビューションの構成を全てのエッジロケーションに送信

参考

mocknmockn

構築

CloudFront

設定対象

  1. ディストリビューション
  2. ポリシー
  3. 関数(CloudFront Functions)

1. ディストリビューション

  • ドメイン
    • デフォルトを使用。*.cloudfront.net
  • 標準ログ記録・cookieログ記録
    • オン
  • セキュリティ
    • WAF有効化
    • 地域制限なし
  • オリジン
    • S3
      • Js
    • API Gateway
      • Lambda
    • AppRunner
  • ビヘイビア
    • 全体
      • デフォルト:S3
      • 優先順位:AppRunner > API Gateway > S3 > デフォルト
    • ポリシー
      • キャッシュポリシー
        • AppRunner / API Gateway / S3: Managed-CachingDisabled
          • 動的コンテンツ向けのリクエストに対応。(キャッシュできない)
      • オリジンリクエストポリシー
        • AppRunner:Managed-CORS-CustomOrigin
        • API Gateway / S3:なし
      • レスポンスヘッダーポリシー
        • AppRunner:response-headers-policy-apprunner(カスタムポリシー)
          • オリジンの設定
        • API Gateway / S3:なし
  • エラーページ
    • 403エラー

3. 関数(CloudFront Functions)

API Gatewayで

Cfnテンプレート

template.yaml

```  - AppRunner
  - API Gateway
  - S3
  - キャッシュポリシー
  - 
- エラーページ
  - 403エラー

### 2. ポリシー

### 3. 関数(CloudFront Functions)


### Cfnテンプレート
```yaml: template.yaml

参考

https://dev.classmethod.jp/articles/cloudfront-update-content-quickly-using-short-ttl/
https://qiita.com/okubot55/items/8290b6c1f59efcff1cb9
https://www.cloudbuilders.jp/articles/1114/
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/using-managed-cache-policies.html#managed-cache-policy-caching-disabled
https://qiita.com/t-kigi/items/6ea9d2656c49b8e40af4

mocknmockn

API Gateway連携

https://zenn.dev/issy/articles/zenn-apigw-overview
https://zenn.dev/megazone_japan/articles/1d85bcf485e310
https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-property-api-endpointconfiguration.html
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-api-endpoint-types.html

  • エンドポイントタイプがリージョンとエッジ最適化ではリクエストヘッダの形式(大文字小文字)が変わり、想定外の動作をすることがあるので注意。
    • エンドポイントタイプが異なってもヘッダの形式が変わらないこともあるため、余計にわかりずらい。
    • CloudFrontやAPI Gatewayの設定が環境間で同じでも挙動がかわってしまうことに遭遇した。
  • AWS SAMでAPI Gatewayをデプロイするとデフォルトでエッジ最適化になっていることが原因。
    • エンドポイントタイプを指定するには、EndpointConfiguration: REGIONALをテンプレートに追加する。API通信のレイテンシーやプライベート通信かどうかにも関係してくるので、基本的には明示的に定義を記載したほうが良さそう。
  API:
    Type: AWS::Serverless::Api
    Properties:
      Name: sam-test-get-api
      EndpointConfiguration: REGIONAL
      StageName: dev
mocknmockn

CloudFront Functions

Cfnテンプレート

AWSTemplateFormatVersion: '2010-09-09'
Description: add-security-headers-cloudfront-function

Resources:
  # CloudFront Functions を定義
  AddSecurityHeaderFunction:
    Type: AWS::CloudFront::Function
    Properties: 
      AutoPublish: false 
      FunctionConfig:
        Comment: add-security-headers-cff
        Runtime: cloudfront-js-1.0
      # 関数のコードは直接記述
      FunctionCode: |
        function handler(event) {
            var response = event.response;
            var headers = response.headers;
            headers['strict-transport-security'] = { value: 'max-age=63072000; includeSubdomains; preload'}; 
            headers['content-security-policy'] = { value: "default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'"}; 
            headers['x-content-type-options'] = { value: 'nosniff'}; 
            headers['x-frame-options'] = {value: 'DENY'}; 
            headers['x-xss-protection'] = {value: '1; mode=block'}; 

            return response;
        }
      Name: add-security-headers-cff

  MyCloudFrontDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Enabled: true
        DefaultCacheBehavior:
          TargetOriginId: "myS3Origin"
          ViewerProtocolPolicy: "redirect-to-https"
          CachePolicyId: "658327ea-f89d-4fab-a63d-7e88639e58f6"
          # DistributionとCloudFront Functionsを紐付け
          FunctionAssociations:
            - EventType: viewer-request
              FunctionARN: !GetAtt MyCloudFrontFunction.FunctionARN
        Origins:
          - Id: "myS3Origin"
            DomainName: "mybucket.s3.amazonaws.com"
            S3OriginConfig:
              OriginAccessIdentity: ""

参考

https://qiita.com/hayao_k/items/52f1cb03cf7c235a6929
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-cloudfront-function.html
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-distribution-defaultcachebehavior.html#cfn-cloudfront-distribution-defaultcachebehavior-functionassociations
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-distribution-functionassociation.html