0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Amazon CloudFrontおよびAWS WAFを用いてエッジサービスを構築する

Posted at

はじめに

この記事は”AWS Hands-on for BeginnersAmazon CloudFrontおよびAWS WAFを用いて エッジサービスの活用方法を学ぼう”を
参考に記事にしました。

今回構築するアーキテクチャ

今回構築するアーキテクチャは以下のようになっている。

AWS Cloud (5).png

AWSグローバルインフラストラクチャとエッジサービスについて

AWS クラウドは、全世界 26 の地域にある 84 のアベイラビリティーゾーンにまたがっており、オーストラリア、カナダ、インド、イスラエル、ニュージーランド、スペイン、スイス、およびアラブ首長国連邦 (UAE) に 24 アベイラビリティーゾーンと 8 AWS リージョンを追加する計画が発表されている。(2022年8月現在)

AWSのサービスは大きく2つに分けられ、「エッジサービス」と「リージョンサービス」がある。

エッジサービスはエッジロケーションで提供されるサービスであり、「Amazon Route 53」、「AWS Global Accelerator」、「Amazon CloudFront」、「AWS WAF」、「AWS Shield」がある。

一方、リージョンサービスはリージョンエリアで提供されるサービスであり、「Amazon EC2」、「Amazon VPC」、「Amazon RDS」、「Amazon S3」などがある。

エッジサービスを導入することで解決できる課題として以下がある。

  • サーバーから遠い場所にいるユーザーの高レイテンシーでのサービス提供
  • 突発的な大量のリクエストに対する対応
  • DDos攻撃やウェブアプリケーションに対する攻撃
    などがある。

AWSのエッジサービスとコンテンツデリバリーネットワークについて

コンテンツデリバリーネットワークであるCloudFrontを用いた流れ図を以下に示している。
図から分かる通り、2回目以降はCloudFrontがコンテンツをキャッシュしており、オリジンサーバーにリクエストを送らず、ユーザーにレスポンスを返すことができており、レスポンス速度を向上させることができる。
AWS Cloud (6).png

とはいえ、全てのコンテンツをキャッシュしていいわけではないので、「静的コンテンツ」のみをキャッシュしていいように設定する必要がある。
「静的コンテンツ」・・・ユーザーのリクエストによって変わらないコンテンツのこと
「動的コンテンツ」・・・ユーザーのリクエストによって変わるコンテンツのこと

Amazon CloudFrontハンズオン1

S3の設定を行う

CloudFrontの設定の前にS3に静的コンテンツを格納する。
マネジメントコンソールでリージョンをバージニア北部に設定→S3を検索→バケットを作成を選択。
以下のように設定し、バケットを作成した。

バケット名:hfb-taiboy
リージョン:バージニア北部

次にS3に静的コンテンツをアップロードする。
ディレクトリ配置は以下のようになっている。

root/
 ┣index.html
 ┣static/
   ┣image/cloudfront.png
   ┣js/script.js
   ┣css/styles.css

index.html
<!DOCTYPE html>
<html>
  <head>
    <link rel="icon" type="image/x-icon" href="static/image/cloudfront.png">
    <link href="static/css/styles.css" rel="stylesheet" type="text/css">
    <script src="static/js/script.js"></script>
  </head>
  <body>
    <form id="form1" action="#">
        <ul>
            <li>
              <img src="static/image/cloudfront.png" width="100" height="100">
            </li>
            <li>
              <p>Input Message</p>
              <textarea id="input_message" rows="4" cols="40"></textarea>
            </li>
            <li>
                <input type="button" onclick="func1()" value="Send" />
                <input type="button" onclick="func2()" value="All Clear"  />
            </li>
            <li>
                <br />
                <p>Output Message</p>
                <textarea id="output_message" rows="4" cols="40"></textarea>
            </li>
          </ul>
    </form>
  </body>
</html>
script.js
function func1() {
  var apiurl = 'https://' + document.domain + '/api?input_text=' + document.getElementById("input_message").value;
  var request = new XMLHttpRequest();

  request.open('GET', apiurl, true);
  request.responseType = 'text';
  request.onload = function () {
      var data = this.response;
      document.getElementById("output_message").innerHTML = data;
  };
  request.send();
}

function func2() {
    document.getElementById("input_message").value = '';
    document.getElementById("output_message").innerHTML = '';
}

CloudFrontの設定

CloudFrontの設定の大枠はディストリビューションといい、そのなかに「ビヘイビア」と「オリジン」がある。
このハンズオンでは、ビヘイビアはパスの設定、オリジンはバックエンドとなるオリジンを指定するものと考える。

マネジメントコンソールからCloudFrontを選択し、ディストリビューションを作成をクリックする。

オリジン設定

オリジンドメインネーム:hfb-taiboy
S3バケットアクセス:はい
オリジンアクセスアイデンティティ:新しいOAIを作成
バケットポリシー:はい

※S3バケットアクセス:クラウドフロントからS3バケットにアクセスするためのポリシーを有効にする。
スクリーンショット 2022-08-11 11.33.24.png

ビヘイビア設定

以下のように設定した。
ビューワープロトコルポリシー:redirect HTTP to HTTPS(HTTPSの通信のみに限りたいため)
キャッシュポリシー:Caching Disbabled(キャッシュさせない設定にしてみる。)

image.png

ディストリビューション設定

デフォルトルートオブジェクト:index.html(こうすることで URLの最後にindex.htmlがなくてもアクセスできるようになる。)

ディストリビューション設定で「カスタムドメイン」や「SSL証明書」を設定することができる。(ピンクの枠)

image.png

ドメインへアクセス

CloudFrontに表示されているドメインにアクセスする。
開発者ツールのNetworkタブを開く→画像を選択し、x-cacheの項目を見る

Miss from CloudFrontと書いており、CloudFrontでキャッシュがヒットしていないことが分かる。
なので、オリジンサーバーがCloudFrontを経由してレスポンスを返したということになる。

※x-cacheとはユーザーのリクエストがキャッシュにヒットしたかどうかを表す。

image.png

Amazon CloudFront設定2

CloudFrontにキャッシュを持たせる。

Cacheポリシーの設定項目

TTL settings:キャッシュ時間のコントロールが可能

  • デフォルトTTL:オリジンがキャッシュコントロールヘッダーを指定しない場合に利用
  • 最小TTL:CloudFront側でキャッシュすべき最小TTL
  • 最大TTL:CloudFront側でキャッシュすべき最大TTL

Cache Key Contents:キャッシュのKeyが設定可能

  • Headers:キャッシュのKeyとなるHTTPヘッダーを指定
  • Cookies:キャッシュのKeyとなるクッキーを指定
  • Query strings:キャッシュのKeyとなるクエリストリングを指定

CloudFrontのコンソール画面から→ポリシー→新しいポリシーを作成

名前:hfb-cachepolicy

これだけ入力し、ポリシーを作成をクリック

ポリシーができたらCloudFrontに設定する。
ディストリビューション→先ほどのディストリビューションを選択→ビヘイビアタブ→新しいビヘイビアを作成

パスパターン:static/*
ビューワープロトコルポリシー:Redirect HTTP to HTTPS
キャッシュポリシー:hfb-cachepolicy(先ほど作成したポリシー)

作成ボタンをクリック

以下のように設定できた。
static/*のリクエストはキャッシュポリシーhfb-cachepolicyを実行し、それ以外はcacheDisableポリシーを実行する。

image.png

webアプリを更新して、開発者ツールの画像を選択してみると、x-cacheの部分に「Hit from cloudfront」とあるので、うまくキャッシュされていることが分かる。

image.png

Amazon CloudFront 設定3(動的コンテンツの配信)

Amazon API Gateway とAWS Lambdaを用いた動的コンテンツとなる、APIの実装を行う。

Lambda関数を作成

マネジメントコンソールからLambdaを開く→新しい関数を作成(右上のリージョンが「バージニア北部になっているか確認する。」)

関数名: h4b-function
ランタイム: Python3.8
と設定し、関数を作成する。

以下のコードを貼り付ける。

lambda.py
import boto3

def lambda_handler(event, context):
    translate = boto3.client(service_name='translate', use_ssl=True)
    result = translate.translate_text(Text=event['queryStringParameters']['input_text'], SourceLanguageCode="ja", TargetLanguageCode="en").get('TranslatedText')
    return {
        'statusCode': 200,
        'body': result
    }

次にこのラムダ関数に紐づいているロールにtranslateReadonlyポリシーをアタッチする。
設定→アクセス権限→ポリシーをアタッチ→検索窓にtranslateと検索し、translateReadonlyポリシーをアタッチする。

APIGatewayを構築する

マネジメントコンソールから「APIGateway」と入力する。→リージョンが「バージニア北部」なのを確認する。→APIを作成するをクリック。→RESTAPIをクリック

プロトコル:新しいAPI
名前:h4b-api
エンドタイプ:リージョン
と設定した。

次に、
アクションをクリックし、メソッドを作成→プルダウンからGETを選び、横のチェックをクリック。

統合タイプ:Lambda関数
Lambdaプロキシ統合を使用にチェック
Lambdaリージョン:us-east-1(バージニア北部なので)
Lambda関数:h4b-function

に設定。

次にこのAPIに渡すクエリストリングを設定するため、メソッドリクエストを編集する。
URLクエリ文字列パラメータのタブからクエリ文字列の追加をクリックする。→「input_text」を入力し、チェックする。

次に、アクションからAPIのデプロイを選択
デプロイされるステージ:[新しいステージ]
ステージ名:api
と設定した。

URLの呼び出しのURLをクリックし、「?input_text=こんにちは世界」をURLの最後に付け加えることでHello Worldと返る。

ここまでくると、APIGatewayはうまく設定できた。

動的コンテンツをCloudFrontへ紐づける

AmazonAPIGatewayをCloudFrontに紐づける。
AmazonAPIGatewayでは「input_text」というクエリ文字列パラメータを設定したことから、CloudFront側でもそのクエリ文字列を設定しないといけない。

ユーザーからのリクエストは一旦、CloudFrontが受け取るため、「ヘッダー」「クッキー」「クエリストリングス」の情報はCloudFrontにて、フィルタリングされた状態でオリジンサーバーに送られる。なので、デフォルト設定のままだと、ユーザーが付与したクエリストリングスはオリジンサーバーには渡らないことになる。
ユーザーが付与したクエリストリングスをオリジンに送りたい場合はCloudFrontのフィルタリングにてホワイトリストを追加する必要があり、この設定を「オリジンリクエストポリシー」という。このオリジンリクエストポリシーはビヘイビアの設定項目の一部として行う。

オリジンリクエストポリシーの作成

マネジメントコンソールからCloudFrontと検索する。→ポリシーを選択しオリジンリクエストポリシーのタブを選択する。→オリジンリクエストポリシーを作成をクリック。
以下のように設定した。

image.png

オリジンの設定

ここまで来たら、ディストリビューションズに移り、自分が設定したCloudFrontに設定をアタッチする。
今回はAPIGatewayを新しいオリジンとして追加していきたいので、オリジンのタブを選択し、オリジンの作成をクリックする。

オリジンドメインネーム:https://「ご自身のドメイン」.us-east-1.amazonaws.com/
オリジンプロトコルポリシー:HTTPS only

ビヘイビアの設定

このオリジンにアクセスするためのビヘイビアを設定する。

パスパターンはAPIGatewayのステージ名「api」とし、オリジンとオリジングループはAPIGWのドメインをコピペした。
ビューワープロトコルをHTTPSのみの「Redirect HTTP to HTTPS」とした。今回は動的コンテンツのため、キャッシュポリシーを「CashingDisabled」にし、
オリジンリクエストポリシーを先ほど作成した「h4b-originrequestpolicy」を選択した。
CloudFrontのマネジメントコンソールからビヘイビアタブを選択し、ビヘイビアを作成をクリック
以下のように設定した。

image.png
image.png

キャッシュコンテンツの確認

クラウドフロントのドメインネームを検索窓に貼り付け、アプリケーションを確認する。
下の画像から動的コンテンツのx-cacheがMiss from cloudfrontになっていることがわかる。

スクリーンショット 2022-08-15 12.07.27.png

image.png

AWS WAFをAmazon CloudForntに紐づける

マネジメントコンソールからAWS WAFを検索(このときリージョンがグローバルになっていることを確認。)し、create WEB ACLをクリック。

name:h4b-waf
Resourse type:CloudFront distoributions

スクリーンショット 2022-08-16 11.04.00.png

以上を設定したら、下へスクロールし、Associated AWS resourcesの項目でAdd AWS resourcesをクリック。

先ほど作成したCloudFrontを選択し、Addをクリックする。

スクリーンショット 2022-08-16 11.04.24.png

ここまでできたら、Nextボタンをクリック。
次にルールを設定する画面になるので、Add rules をクリックし、自分独自のルールを設定するので、「Add my own rules and rule group」を選択する。

name:h4b-rule
if a request: matches trhe statement
Inspect: Originates from a country in
country codes: Japan
Action:Block

Ip address to use to determine the country originの項目では、Source IP addressを選択しているが、IP address in headerにすると、ソースIPアドレス以外からIPアドレスを引っ張ることができ、例えばXFF(X-Forwarded-For)の中のIPアドレスを引っ張ることもできる。

X-Forwarded-Forとは、HTTPヘッダフィールドの1つであり、ロードバランサなどの機器を経由してWebサーバに接続するクライアントの送信元IPアドレスを特定する際のデファクトスタンダード。

日本からのアクセスをブロックしてみる。

スクリーンショット 2022-08-16 11.05.42.png

スクリーンショット 2022-08-16 11.07.14.png

ここまで入力したらAdd ruleをクリック。その次のプライオリティーやメトリクスはデフォルトのまま設定した。
サマリーの画面で、問題ないことを確認し、Create WEB ACLをクリック。

CloudFrontに上部の設定が反映されているか確認する。ドメインにアクセスしてみると、以下のようなページが表示されるため、
設定が正しくできていることがわかる。

スクリーンショット 2022-08-16 11.10.55.png

次にマネージドルールを追加する。再度、AWS WAFと検索し、Wab ACLsのタブをクリックする。このとき、リージョンがグローバルになっていることを確認する。
先ほど作ったWebACLsを選択し、Rulesタブをクリック。右上のAddRuleからAdd managed rule groupsを選択する。AWS managed ruleからCore rule setを選択する。この設定のまま、Add rulesをクリックする。プリオリティーもそのままでSaveをクリック。これでマネージドルールが設定できた。

リソースの削除手順

Amazon CloudFrontの削除

AWS WAFの削除

Amazon API Gatewayの削除

AWS Lambdaの削除

Amazon S3の削除

Amazon CloudFrontの削除

該当のディストリビューションを選択し、無効にする。直接、削除はできない。
しばらくして、ステータスが無効、状態がデプロイになったら、ページを更新し、削除を選択する。
次にキャッシュポリシー、オリジンリクエストポリシーも削除する。
ポリシータブを押して自身が作成したポリシーを削除。オリジンリクエストポリシーのタブに移動し、これも自身が作成した ポリシーを削除する。

Amazon S3の削除

該当のバケットを選択し、まず、「空にする」を選択後、削除する。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?