25
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CloudFront と S3を利用した静的コンテンツ配信

25
Posted at

はじめに

こんにちは、やくもです。
今回はCloudFrontとS3を使った静的ウェブサイトの配信についてです。
この辺は業務でもがっつり触ったこともあまり無いですが、試験では頻繁に出るイメージなので実際に触ってみて色々知見を得ることができました。

なぜCloudFrontとS3 なのか

静的コンテンツ配信だとこの組み合わせは王道(?)とよく言われています。
S3単体でも静的サイトのホスティングは可能ですが、CloudFrontを組み合わせることでより高速に安全にコンテンツの配信を行うことができます。
具体的なメリットは以下になります。

  • 高速なコンテンツ配信: エッジロケーションからのキャッシュ配信により、世界中どこからでも低レイテンシでアクセス可能
  • コスト削減: S3 へのリクエスト数を削減し、データ転送コストも最適化
  • セキュリティ向上: S3 バケットを非公開にし、CloudFront 経由のみアクセスを許可

今回作ったもの

今回はシンプルな静的 Web サイトを CloudFront と S3 で配信する環境を構築しました。

image.png

  • S3 バケットは完全非公開(パブリックアクセス全ブロック)
  • Origin Access Control(OAC)による安全なアクセス制御
  • HTTPS 通信の強制
  • キャッシュによる高速配信

構築手順

それでは、実際に環境を構築していきます。

S3バケットの作成

まず、静的コンテンツを格納する S3 バケットを作成します。

バケットのパブリックアクセスがオフになっていることを確認します。

image.png

バケット作成後、以下のようになります。

image.png

コンテンツの作成とアップロード

動作確認のため、実際に表示するHTMLファイルを作成、格納します。

index.htm
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CloudFront + S3 デモサイト</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 50px auto;
            padding: 20px;
            background-color: #f5f5f5;
        }
        .container {
            background-color: white;
            padding: 30px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        h1 {
            color: #232F3E;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>CloudFront + S3 で配信中!</h1>
        <p>このサイトは Amazon CloudFront と S3 で配信されています。</p>
        <p>高速で安全なコンテンツ配信が実現できました!</p>
    </div>
</body>
</html>

作成した上記のhtmlファイルをS3にアップロードします。

image.png

CloudFrontの設定

次に、CloudFront Distribution を作成します。

今回は無料プランで実施しています。

image.png

オリジンの作成や設定を行います。
先ほど作成したバケットを指定します。

image.png

デフォルトルートオブジェクトでindex.htmlを入力

image.png

また、そのほかのオプションでWAFなどの設定を有効にできますが今回はすべてデフォルトにしておきます。

S3バケットのポリシー設定

CloudFront から S3 へのアクセスを許可するため、S3 バケットポリシーを設定します。
と思ったのですが、上記のオリジン追加時に自動的にバケットポリシーは書き変わるようです。
設定されるポリシーの例は以下になります。

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipal",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::hogehoge/*",
            "Condition": {
                "ArnLike": {
                    "AWS:SourceArn": "arn:aws:cloudfront::hogehoge/gehogeho"
                }
            }
        }
    ]
}

アクセスしてみる

それでは実際にアクセスして動作を確認します。
作成したディストリビューションの画面を開き、「ディストリビューションドメイン名」をコピーしブラウザで開きます。
image.png

以下のようにS3に用意していたコンテンツが表示されれば成功です。

image.png

エラーが発生する場合

アクセス時、以下のようにアクセスエラーが発生する場合があります。原因は大体以下です。

  • バケットポリシーの権限不足
  • 指定したファイル名の誤り
  • デフォルトルートオブジェクトの指定誤り

image.png

キャッシュの確認

2回目以降のアクセスでは、CloudFront のキャッシュから配信されます。開発者ツールで以下を確認できます。
このヘッダーが表示されれば、キャッシュから高速に配信されていることが確認できます。

image.png

セキュリティのベストプラクティス

CloudFront と S3 を使用する際のセキュリティ対策についても少しまとめておきます。

1. Origin Access Control (OAC) の使用

今回の構築で設定した OAC により、S3 バケットへの直接アクセスを完全に遮断しています。
OACを利用することによってリソースをパブリックにせず、CloudFront経由のアクセスを強制できます。

2. HTTPS 通信の強制

設定で「Redirect HTTP to HTTPS」、もしくは「HTPPS only」を選択することで、自動的にHTTPSでの通信が強制され通信が暗号化されます。

image.png

3. セキュリティヘッダーの追加

CloudFront Functions を使用して、レスポンスにセキュリティヘッダーを追加できます。
今回はAWSサンプルを用意してくれていたので、そちらを使用してみました。必要に応じて機能拡張などしてみて下さい。

function handler(event) {
    var response = event.response;
    var headers = response.headers;

    // Set HTTP security headers
    // Since JavaScript doesn't allow for hyphens in variable names, we use the dict["key"] notation 
    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 the response to viewers 
    return response;
}

適用後、再度CloudFrontにアクセスして、セキュリティヘッダが追加されていることを確認します。

image.png

4. AWS WAF の導入(オプション)

り高度なセキュリティが必要な場合、AWS WAFも導入できます。
少しコストがネックになってくるので、今回は使っていません...

さいごに

CloudFront と S3 を組み合わせることで、高速・安全・低コストな静的コンテンツ配信環境を構築してみました。
試験勉強の知識だけでなく、改めて使ってみないとわからない学びも多かったのでやってみてよかったです。この記事がみなさんの参考になれば幸いです。

参考

25
11
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
25
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?