CloudFrontの標準ログV2の説明中のプレフィックスとサフィックスの関係性を確認してみた
プレフィックスとサフィックスは何に対してどこまで修飾しているのか、どちらを設定すれば良いのか分からない
こんにちは、のんピ(@non____97)です。
皆さんは「プレフィックスとサフィックスは何に対してどこまで修飾しているのか」や「どちらを設定すれば良いのか」分からなくなったことがありますか? 私はあります。
以下のドキュメントをご覧ください。
If you specified a prefix for your S3 bucket, your logs appear under that path. If you don't specify a prefix, CloudFront will automatically append the AWSLogs/<account-ID>/CloudFront prefix for you.
Example: Bucket with a prefix
If you specify the following bucket name with a prefix: amzn-s3-demo-bucket.s3.amazonaws.com/MyLogPrefix
Your logs will appear under the following path: amzn-s3-demo-bucket.s3.amazonaws.com/MyLogPrefix/logs
Example: Bucket without a prefix
If you specify the bucket name only: amzn-s3-demo-bucket.s3.amazonaws.com
Your logs will appear under the following path: amzn-s3-demo-bucket.s3.amazonaws.com/AWSLogs/123456789012/CloudFront/logs
a prefix for your S3 bucket
やBucket with a prefix
、Bucket without a prefix
、MyLogPrefix
とprefix
という単語が並んでいます。
何も前提知識がない状態でa prefix for your S3 bucket
やBucket with a prefix
、Bucket without a prefix
だけだとS3バケットの前方に何か文字列を付与する = プレフィックスを指定するように見える場合もあるでしょう。
ただし、MyLogPrefix
という単語があることから、ここで登場するプレフィックスという意味はS3バケットのログオブジェクトに対するプレフィックスであることが分かります。
こちらのドキュメントもご覧ください。
S3SuffixPath
Use this to reconfigure the S3 object prefix to contain either static or variable sections. The valid variables to use in the suffix path will vary by each log source. To find the values supported for the suffix path for each log source, use the DescribeConfigurationTemplates operation and check the allowedSuffixPathFields field in the response.
S3SuffixPath
やthe suffix path will vary by each log source
とsuffix
という単語が並んでいます。
また、サフィックスの説明のためにS3 object prefix
とprefix
も登場してきました。こちらの説明からS3SuffixPath
はオブジェクトに設定されるプレフィックスであることが分かります。
二つの関係性を図で表すと以下のようになります。
はい、プレフィックスとサフィックスはどこで切るべきなのでしょうか。
CloudFrontの標準ログV2を設定するにあたっては二つの違いを理解する必要があります。
理解できていなければ、以下記事のようにCloudFormationやAWS CDKで設定する際にカスタムリソースを使おうとしてしまうでしょう。
いきなりまとめ
- Delivery Destinationの
DestinationResourceArn
はS3バケット自体を指すだけではなく、S3バケット内のオブジェクトのプレフィックスを含めた形で指定することも可能 S3SuffixPath
はDelivery Destinationで指定したS3バケットのARN(ログプレフィックスを含む)に対するサフィックス- ログオブジェクトに対するサフィックスではなく、プレフィックス
- 標準ログV2の変数は
S3SuffixPath
でのみ行うことが可能 PutDeliveryDestination
でログプレフィックスを指定しなかったことによって自動設定されるAWSLogs/{account-id}/CloudFront/
はS3SuffixPath
として扱われる- CloudFormationやAWS CDKをしようして標準ログV2を設定する場合は、
DestinationResourceArn
でS3バケットのサフィックスを指定しよう- 指定できるサフィックスは一階層まで
ドキュメントを改めて見てみる
ドキュメントを改めてみてみましょう。
まず、以下です。
The S3 bucket name can only use the regex pattern [\w-]. For more information, see the PutDeliveryDestination API operation in the Amazon CloudWatch Logs API Reference.
If you specified a prefix for your S3 bucket, your logs appear under that path. If you don't specify a prefix, CloudFront will automatically append the AWSLogs/<account-ID>/CloudFront prefix for you.
文中ではa prefix for your S3 bucket
にはなっていますが、文章の流れ的にa prefix for objects in your S3 bucket
と理解して読むと、PutDeliveryDestination
でS3バケットのログオブジェクトのプレフィックスを指定しない場合は、AWSLogs/<account-ID>/CloudFront prefix
というログプレフィックスが付与されると書いてあります。
類似の説明は以下でも記載されています。
For the Destination, select the resource for your service. If you haven’t already created your resource, you can choose Create or see the following documentation.
- For CloudWatch Logs, enter the Log group name.
- For Firehose, enter the Firehose delivery stream.
- For Amazon S3, enter the Bucket name.
Tip
To specify a prefix, enter the prefix after the bucket name, such as amzn-s3-demo-bucket.s3.amazonaws.com/MyLogPrefix. If you don't specify a prefix, CloudFront will automatically add one for you. For more information, see Send logs to Amazon S3
PutDeliveryDestination
はS3バケットのログの配信先を指定するAPIです。
つまり、自動的にログプレフィックスが付与されることを避けるには、配信先のS3バケットを指定するタイミングで、ログオブジェクトのプレフィックスを指定する必要があります。
続いて、CreateDelivery
やUpdateDeliveryConfiguration
で指定できるsuffixPath
について言及しているドキュメントを確認します。
suffixPath
This string allows re-configuring the S3 object prefix to contain either static or variable sections. The valid variables to use in the suffix path will vary by each log source. To find the values supported for the suffix path for each log source, use the DescribeConfigurationTemplates operation and check the allowedSuffixPathFields field in the response.
はい、ここでは変数が使用できると記載があります。現時点で使用できる変数は以下のとおりです。
{DistributionId}
{yyyy}
{MM}
{dd}
{HH}
つまり、変数を使って表現したい箇所以降はsuffixPath
として指定する必要があります。
以下のように変数を含むケースを使って整理します。
PutDeliveryDestination
やCreateDelivery
、UpdateDeliveryConfiguration
の各APIで指定可能な範囲は以下のとおりです。
AWSLogs
が重複していますね。
逆に変数を含まないアカウントIDとCloudFront
は重複していません。何故ならこちらはPutDeliveryDestination
で指定することはできないためです。
以下のようにサフィックス部分に/
が含むとエラーになります。
> aws logs put-delivery-destination \
--name S3-destination \
--delivery-destination-configuration destinationResourceArn=arn:aws:s3:::websitestack-cloudfrontaccesslogbucketconstruct221-bwzpr29ygir6/AWSLogs/<AWSアカウントID>/CloudFront/
An error occurred (ValidationException) when calling the PutDeliveryDestination operation: Delivery Destination Configuration prefix contains characters that are not allowed.
> aws logs put-delivery-destination \
--name S3-destination \
--delivery-destination-configuration destinationResourceArn=arn:aws:s3:::websitestack-cloudfrontaccesslogbucketconstruct221-bwzpr29ygir6/AWSLogs/<AWSアカウントID>/
An error occurred (ValidationException) when calling the PutDeliveryDestination operation: Delivery Destination Configuration prefix contains characters that are not allowed.
> aws logs put-delivery-destination \
--name S3-destination \
--delivery-destination-configuration destinationResourceArn=arn:aws:s3:::websitestack-cloudfrontaccesslogbucketconstruct221-bwzpr29ygir6/AWSLogs/
An error occurred (ValidationException) when calling the PutDeliveryDestination operation: Delivery Destination Configuration prefix contains characters that are not allowed.
> aws logs put-delivery-destination \
--name S3-destination \
--delivery-destination-configuration destinationResourceArn=arn:aws:s3:::websitestack-cloudfrontaccesslogbucketconstruct221-bwzpr29ygir6/AWSLogs
{
"deliveryDestination": {
"name": "S3-destination",
"arn": "arn:aws:logs:us-east-1:<AWSアカウントID>:delivery-destination:S3-destination",
"deliveryDestinationType": "S3",
"deliveryDestinationConfiguration": {
"destinationResourceArn": "arn:aws:s3:::websitestack-cloudfrontaccesslogbucketconstruct221-bwzpr29ygir6/AWSLogs"
}
}
}
「CreateDelivery
、UpdateDeliveryConfiguration
で全ての範囲を指定できるなら、PutDeliveryDestination
は付与しなくとも良いのでは」と考えるかもしれません。
しかし、私個人的には以下の範囲で指定したいです。
CloudFormationやAWS CDKで標準ログV2を管理するとなった場合、CreateDelivery
、UpdateDeliveryConfiguration
で全ての範囲を指定すると、Delivery作成時と更新時とでS3SuffixPath
の冪等性がなくなってしまいます。こちらの挙動は以下記事をご覧ください。
そうした場合、AWSLogs
はPutDeliveryDestination
で指定したいところです。
やってみた
検証環境
実際にやってみましょう。
検証環境は以下のとおりです。
検証環境は全てAWS CDKでデプロイしました。使用したコードは以下GitHubリポジトリに保存しています。
こちらのベースとなったコードの詳細な説明は以下記事をご覧ください。
AWS CDKのコードの紹介
AWS CDKのコードは以下のとおりです。
語るところはほとんどありませんが、destinationResourceArn
の末尾にAWSLogs
を付与しています。
const cloudFrontStandardLogDeliverySourceName = `cf-${this.distribution.distributionId}`;
const cloudFrontStandardLogDeliveryDestinationName = `cf-${this.distribution.distributionId}-s3`;
const logPrefix = this.getStandardLogV2Prefix(props.logFilePrefix);
const cloudFrontStandardLogDeliverySource =
new cdk.aws_logs.CfnDeliverySource(
this,
"CloudFrontStandardLogDeliverySource",
{
name: cloudFrontStandardLogDeliverySourceName,
resourceArn: this.distribution.distributionArn,
logType: "ACCESS_LOGS",
}
);
const cloudFrontStandardLogDeliveryDestination =
new cdk.aws_logs.CfnDeliveryDestination(
this,
"CloudFrontStandardLogDeliveryDestination",
{
name: cloudFrontStandardLogDeliveryDestinationName,
outputFormat: "parquet",
destinationResourceArn: `${props.cloudFrontAccessLogBucketConstruct.bucket.bucketArn}/AWSLogs`,
}
);
new cdk.aws_logs.CfnDelivery(this, "CloudFrontStandardLogDelivery", {
deliverySourceName: cloudFrontStandardLogDeliverySource.name,
deliveryDestinationArn:
cloudFrontStandardLogDeliveryDestination.attrArn,
s3EnableHiveCompatiblePath: false,
s3SuffixPath: logPrefix,
});
動作確認
デプロイします。
マネジメントコンソールを確認すると、意図した通りに設定されていそうです。
AWS CLIからも確認しておきましょう。
> aws logs describe-delivery-destinations
{
"deliveryDestinations": [
{
"name": "cf-E21YV8QMTCNCR6-s3",
"arn": "arn:aws:logs:us-east-1:<AWSアカウントID>:delivery-destination:cf-E21YV8QMTCNCR6-s3",
"deliveryDestinationType": "S3",
"outputFormat": "parquet",
"deliveryDestinationConfiguration": {
"destinationResourceArn": "arn:aws:s3:::websitestack-cloudfrontaccesslogbucketconstruct221-bwzpr29ygir6/AWSLogs"
}
}
]
}
> aws logs get-delivery --id Lra8WpHC8os6orul
{
"delivery": {
"id": "Lra8WpHC8os6orul",
"arn": "arn:aws:logs:us-east-1:<AWSアカウントID>:delivery:Lra8WpHC8os6orul",
"deliverySourceName": "cf-E21YV8QMTCNCR6",
"deliveryDestinationArn": "arn:aws:logs:us-east-1:<AWSアカウントID>:delivery-destination:cf-E21YV8QMTCNCR6-s3",
"deliveryDestinationType": "S3",
"recordFields": [
"date",
"time",
"x-edge-location",
"sc-bytes",
"c-ip",
"cs-method",
"cs(Host)",
"cs-uri-stem",
"sc-status",
"cs(Referer)",
"cs(User-Agent)",
"cs-uri-query",
"cs(Cookie)",
"x-edge-result-type",
"x-edge-request-id",
"x-host-header",
"cs-protocol",
"cs-bytes",
"time-taken",
"x-forwarded-for",
"ssl-protocol",
"ssl-cipher",
"x-edge-response-result-type",
"cs-protocol-version",
"fle-status",
"fle-encrypted-fields",
"c-port",
"time-to-first-byte",
"x-edge-detailed-result-type",
"sc-content-type",
"sc-content-len",
"sc-range-start",
"sc-range-end"
],
"fieldDelimiter": "\t",
"s3DeliveryConfiguration": {
"suffixPath": "<AWSアカウントID>/CloudFront/{DistributionId}/{yyyy}/{MM}/{dd}/{HH}",
"enableHiveCompatiblePath": false
}
}
}
適当にアクセスすると、意図したプレフィックスでログオブジェクトが出力されていました。
冪等性があるか確認するためにCfnDelivery
の一部を変更して再度デプロイします。
> npx cdk diff --no-change-set
Bundling asset WebsiteStack/ContentsDeliveryConstruct/RewriteToWebpLambdaEdge/Code/Stage...
cdk.out/bundling-temp-3bc47000a941290e417f7fa8779fe410819da0a3007ce331064035a1c428d836/index.mjs 731b
⚡ Done in 3ms
Stack WebsiteStack
Resources
[~] AWS::Logs::Delivery ContentsDeliveryConstruct/CloudFrontStandardLogDelivery ContentsDeliveryConstructCloudFrontStandardLogDelivery2C76C0AA
└─ [~] S3EnableHiveCompatiblePath
✨ Number of stacks with differences: 1
> npx cdk deploy
Bundling asset WebsiteStack/ContentsDeliveryConstruct/RewriteToWebpLambdaEdge/Code/Stage...
cdk.out/bundling-temp-3bc47000a941290e417f7fa8779fe410819da0a3007ce331064035a1c428d836/index.mjs 731b
⚡ Done in 8ms
✨ Synthesis time: 7.69s
WebsiteStack: start: Building 51ed1ace36f0a4dfc4b70730ee1604c6a7210b3a3635ecff8dc23d08a55dbd08:<AWSアカウントID>-us-east-1
WebsiteStack: success: Built 51ed1ace36f0a4dfc4b70730ee1604c6a7210b3a3635ecff8dc23d08a55dbd08:<AWSアカウントID>-us-east-1
WebsiteStack: start: Publishing 51ed1ace36f0a4dfc4b70730ee1604c6a7210b3a3635ecff8dc23d08a55dbd08:<AWSアカウントID>-us-east-1
WebsiteStack: success: Published 51ed1ace36f0a4dfc4b70730ee1604c6a7210b3a3635ecff8dc23d08a55dbd08:<AWSアカウントID>-us-east-1
WebsiteStack: deploying... [1/1]
WebsiteStack: creating CloudFormation changeset...
WebsiteStack | 0/3 | 16:24:45 | UPDATE_IN_PROGRESS | AWS::CloudFormation::Stack | WebsiteStack User Initiated
WebsiteStack | 0/3 | 16:24:50 | UPDATE_IN_PROGRESS | AWS::Logs::Delivery | ContentsDeliveryConstruct/CloudFrontStandardLogDelivery (ContentsDeliveryConstructCloudFrontStandardLogDelivery2C76C0AA)
WebsiteStack | 1/3 | 16:24:52 | UPDATE_COMPLETE | AWS::Logs::Delivery | ContentsDeliveryConstruct/CloudFrontStandardLogDelivery (ContentsDeliveryConstructCloudFrontStandardLogDelivery2C76C0AA)
WebsiteStack | 2/3 | 16:24:53 | UPDATE_COMPLETE_CLEA | AWS::CloudFormation::Stack | WebsiteStack
WebsiteStack | 3/3 | 16:24:54 | UPDATE_COMPLETE | AWS::CloudFormation::Stack | WebsiteStack
✅ WebsiteStack
✨ Deployment time: 41.16s
Stack ARN:
arn:aws:cloudformation:us-east-1:<AWSアカウントID>:stack/WebsiteStack/aeeadb90-d96b-11ef-a0e7-0afff9169823
✨ Total time: 48.86s
AWS CLIで確認します。
> aws logs get-delivery \
--id Lra8WpHC8os6orul \
--query 'delivery.s3DeliveryConfiguration'
{
"suffixPath": "<AWSアカウントID>/CloudFront/{DistributionId}/{yyyy}/{MM}/{dd}/{HH}",
"enableHiveCompatiblePath": true
}
suffixPath
は変わっていなさそうですね。
この状態でアクセスすると、Apache Hive形式の意図したプレフィックスでオブジェクトが出力されていました。
IaCで設定する場合は必ずDelivery Destination定義時にS3バケットのサフィックスを指定しよう
CloudFrontの標準ログV2の設定で出てくるプレフィックスとサフィックスの関係性を確認してみました。
S3SuffixPath
がDelivery Destinationで指定したS3バケットとサフィックスの更にサフィックスとなるのがポイントですね。
個人的にはサフィックスとプレフィックスが入り混じると混乱するので、どちらかに寄せて欲しいですね。(S3SuffixPath
の説明がS3 object prefix
ですし)
IaCで設定する場合は必ずDelivery Destination定義時にS3バケットのサフィックスを指定しましょう。自動付与のプレフィックスで痛い目に遭います。
この記事が誰かの助けになれば幸いです。
以上、クラウド事業本部 コンサルティング部の のんピ(@non____97)でした!