1
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?

はじめに

CloudFront + S3 環境で初期構築した際、設定されてると便利だなと思ったことをまとめました。
あわせて参考記事も紹介しますので、試してみてください。

CloudFront Functions(関数)について

この記事では CloudFront Functions を利用します。
設定方法は以下を参考にしてください。

1. サブディレクトリのドキュメントルート指定

S3 の静的ウェブサイトホスティングがルートオブジェクト (https://www.example.com/) にのみインデックスドキュメントを適用し、CloudFront がサブディレクトリ (https://www.example.com/hoge/) の index.html を自動解決せず、Not Found となります。(AWS仕様上の挙動)
以下を CloudFront Functions で設定し解決しました。

function handler(event) {
  var request = event.request;
  var uri = request.uri;

  if (uri.endsWith("/")) {
    // Check whether the URI is missing a file name.
    request.uri += "index.html";
  } else if (!uri.includes(".")) {
    // Check whether the URI is missing a file extension.
    request.uri += "/index.html";
  }

  return request;
}

2. CloudFront のキャッシュ削除

S3 バケット内のオブジェクトが変更された場合に、S3イベントトリガーで Lambda を起動し CloudFront のキャッシュを削除します。
設定方法は以下の記事が分かりやすかったです。
https://qiita.com/hirai-11/items/0aede046a26cc66778ad

3. 監視編

Cloud Watch Alarm を設定すると便利!
各アラームの CloudFormation テンプレート(YAML)を記載します。

3-1. CloudFront の 4XX と 5XX エラー通知

CloudFront で 400 番台と 500 番台のエラーが発生した時にアラームを通知します。
※ AWS Notification - Subscription Confirmation メールが届きますので承認してください。

details cloudfront-alarm.yaml(折り畳んでます)
AWSTemplateFormatVersion: '2010-09-09'
Description: 'CloudWatch Alarm for CloudFront 4xx and 5xx errors'

Parameters:
  NotificationEmail:
    Type: String

  DistributionId:
    Type: String

Resources:
  # SNSトピックの作成
  SnsTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: CloudFront-Errors-Topic

  # SNSトピックのサブスクリプション(メール通知)
  SnsSubscription:
    Type: AWS::SNS::Subscription
    Properties:
      Protocol: email
      TopicArn: !Ref SnsTopic
      Endpoint: !Ref NotificationEmail

  # CloudFront 4xxエラーのアラーム
  CloudFront4xxErrorAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName: CloudFront-4xx-Errors
      AlarmDescription: Alarm when CloudFront returns 4xx errors
      MetricName: 4xxErrorRate
      Namespace: AWS/CloudFront
      Statistic: Average
      Period: 300  # 5分間
      EvaluationPeriods: 1
      Threshold: 5  # エラーレート5%以上で通知
      ComparisonOperator: GreaterThanThreshold
      Dimensions:
        - Name: DistributionId
          Value: !Ref DistributionId
        - Name: Region
          Value: Global
      AlarmActions:
        - !GetAtt SnsTopic.TopicArn
      OKActions:
        - !GetAtt SnsTopic.TopicArn
      TreatMissingData: notBreaching

  # CloudFront 5xxエラーのアラーム
  CloudFront5xxErrorAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName: CloudFront-5xx-Errors
      AlarmDescription: Alarm when CloudFront returns 5xx errors
      MetricName: 5xxErrorRate
      Namespace: AWS/CloudFront
      Statistic: Average
      Period: 300  # 5分間
      EvaluationPeriods: 1
      Threshold: 5  # エラーレート5%以上で通知
      ComparisonOperator: GreaterThanThreshold
      Dimensions:
        - Name: DistributionId
          Value: !Ref DistributionId
        - Name: Region
          Value: Global
      AlarmActions:
        - !GetAtt SnsTopic.TopicArn
      OKActions:
        - !GetAtt SnsTopic.TopicArn
      TreatMissingData: notBreaching

YAMLパラメーターの解説

パラメーター名 解説
NotificationEmail 通知先メールアドレス
DistributionId 監視する CloudFront の DistributionId

3-2. S3 の 4XX と 5XX エラー通知

S3 で 400 番台と 500 番台のエラーが発生した時にアラームを通知します。
※ AWS Notification - Subscription Confirmation メールが届きますので承認してください。

details s3-alarm.yaml(折り畳んでます)
AWSTemplateFormatVersion: '2010-09-09'
Description: 'CloudWatch Alarm for S3 4xx and 5xx errors'

Parameters:
  NotificationEmail:
    Type: String

  BucketName:
    Type: String

Resources:
  # SNSトピックの作成
  SnsTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: S3-Errors-Topic

  # SNSトピックのサブスクリプション(メール通知)
  SnsSubscription:
    Type: AWS::SNS::Subscription
    Properties:
      Protocol: email
      TopicArn: !Ref SnsTopic
      Endpoint: !Ref NotificationEmail

  # 4xxエラーのアラーム
  S34xxErrorAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName: S3-4xx-Errors
      AlarmDescription: Alarm when S3 returns 4xx errors
      MetricName: 4xxErrors
      Namespace: AWS/S3
      Statistic: Sum
      Period: 300  # 5分間
      EvaluationPeriods: 1
      Threshold: 5  # 5回以上のエラーで通知
      ComparisonOperator: GreaterThanThreshold
      Dimensions:
        - Name: BucketName
          Value: !Ref BucketName
      AlarmActions:
        - !GetAtt SnsTopic.TopicArn
      OKActions:
        - !GetAtt SnsTopic.TopicArn
      TreatMissingData: notBreaching

  # 5xxエラーのアラーム
  S35xxErrorAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName: S3-5xx-Errors
      AlarmDescription: Alarm when S3 returns 5xx errors
      MetricName: 5xxErrors
      Namespace: AWS/S3
      Statistic: Sum
      Period: 300  # 5分間
      EvaluationPeriods: 1
      Threshold: 5  # 5回以上のエラーで通知
      ComparisonOperator: GreaterThanThreshold
      Dimensions:
        - Name: BucketName
          Value: !Ref BucketName
      AlarmActions:
        - !GetAtt SnsTopic.TopicArn
      OKActions:
        - !GetAtt SnsTopic.TopicArn
      TreatMissingData: notBreaching

YAMLパラメーターの解説

パラメーター名 解説
NotificationEmail 通知先メールアドレス
BucketName 監視する S3 バケット名

3-3. S3 の容量通知

S3 で指定容量を超過した時にアラームを通知します。
※ AWS Notification - Subscription Confirmation メールが届きますので承認してください。

details s3-bucket-size-alarm.yaml(折り畳んでます)
AWSTemplateFormatVersion: 2010-09-09
Description: 'CloudWatch Alarm for S3 Bucket Size'

Parameters:
  NotificationEmail:
    Type: String

  BucketName:
    Type: String

  S3BucketSize:
    Type: Number

Resources:
  # SNSトピックの作成
  SnsTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: S3-Bucket-Size-Errors-Topic

  # SNSトピックのサブスクリプション(メール通知)
  SnsSubscription:
    Type: AWS::SNS::Subscription
    Properties:
      Protocol: email
      TopicArn: !Ref SnsTopic
      Endpoint: !Ref NotificationEmail

  # バケットサイズ超過のアラーム
  S3BucketSizeAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName: S3-Bucket-Size-Errors
      AlarmDescription: Alarm when S3 BucketSizeBytes alarm
      MetricName: BucketSizeBytes
      Namespace: AWS/S3
      Statistic: Average
      Period: 86400  # 24時間
      Threshold: !Ref S3BucketSize
      EvaluationPeriods: 1
      ComparisonOperator: GreaterThanThreshold
      Dimensions:
        - Name: BucketName
          Value: !Ref BucketName
        - Name: StorageType
          Value: StandardStorage
      AlarmActions:
        - !GetAtt SnsTopic.TopicArn
      OKActions:
        - !GetAtt SnsTopic.TopicArn
      TreatMissingData: notBreaching

YAMLパラメーターの解説

パラメーター名 解説
NotificationEmail 通知先メールアドレス
BucketName 監視する S3 バケット名
S3BucketSize 監視する バケットの容量(Byte)

4. おまけ

4-1. Basic 認証

検証環境など不特定多数に見せたくない時 Basic 認証を設定して認証情報を知ってる人だけ見れるようにします。
以下を CloudFront Functions で設定します。
※ token 値は、echo -n user:pass | base64 コマンドで作成可能ですが、セキュリティの観点から、CloudFront Functions の KeyValueStores などより安全な方法で管理することを推奨します。

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

  // echo -n user:pass | base64
  var authString = "Basic <token値>";

  if (
    typeof headers.authorization === "undefined" ||
    headers.authorization.value !== authString
  ) {
    return {
      statusCode: 401,
      statusDescription: "Unauthorized",
      headers: { "www-authenticate": { value: "Basic" } }
    };
  }

  return request;
}

4-2. IP 制限

AWS WAF を導入せずとも CloudFront Functions のみで IP 制限を設定することができます。
以下 xxx.xxx.xxx.xxx 部分を接続許可する IP に変更し、CloudFront Functions を設定します。

function handler(event) {
  var request = event.request;
  var clientIP = event.viewer.ip;
  // 許可するIPを指定
  var IP_WHITE_LIST = ["xxx.xxx.xxx.xxx", "xxx.xxx.xxx.xxx"];
  var allowIP = IP_WHITE_LIST.includes(clientIP);

  if (allowIP) {
    return request;
  } else {
    var response = {
      statusCode: 403,
      statusDescription: "Forbidden",
    };
    return response;
  }
}

まとめ

はじめて CloudFront + S3 を触った時にいろいろ調べたのですが、まとめて紹介しているページが見当たらなかった(探し方が悪い?)ので、自分なりにまとめてみました。
また、参考サイトに記載しました「CloudFront Functions の活用パターン集」では、いろいろな設定ができることを発見できたので、参考になりました!
この記事が、誰かの役に立てば幸いです。

参考サイト

1
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
1
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?