はじめに
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 の活用パターン集」では、いろいろな設定ができることを発見できたので、参考になりました!
この記事が、誰かの役に立てば幸いです。