各種AWSサービスのアクセスログ保存のためのS3バケットアクセス制御をまとめてみた
こんにちは。AWS事業本部トクヤマシュンです。
AWSサービスで日々大量に記録されるアクセスログについて、
ストレージ費用は抑えたいけど、いざという時のために取っておきたい。
そんな時は、まずS3に保存するのが一般的です。
AWSにはアクセスログの保存先にS3を指定可能なサービスがいくつか存在します。
しかし、AWSサービス毎にログ保存用のS3バケットに必要なアクセス制御設定は異なります。
GUIでアクセスログを設定する場合にはあまり意識しなくても良いのですが、TerraformやCloudFrontで構築する際には自分でS3バケットのアクセス制御設定が必要です。
構築の度に調べるのにいい加減うんざりしてしまったので、いくつかのサービスについてアクセスログ保存用のS3バケットの設定をまとめます。
構築用のTerraformコードも記載しているので、参考にしてみてください。
S3アクセス制御設定まとめ表
いくつかのAWSサービスとアクセスログ保存先のS3バケットのアクセス制御設定をまとめたのが次の表です。AWSサービスはアクセスログを取る機会が多いと思われるサービスを対象としています。
なお前提として、AWSサービスのアカウントとアクセスログを保存するS3バケットの所持アカウントは同一としています。
以降は各AWSサービスでの設定を見ていきます。
CloudFrontアクセスログ保存バケット設定
Amazon CloudFrontのアクセスログを保存するS3バケットには、ACLの設定が必要です。
2022/6/14時点では、CloudFrontアクセスログを保存するS3バケットのアクセス制御はACLで実施するよう案内されています。
ただ、re:Invent 2021期間中に発表されたS3のACL無効化機能に代表されるように、Amazon S3のACLは無効化が推奨されていますので、近い将来変更される予感がします。
この辺りの詳細は下記ブログをご参照ください。
制御パーミッションの付与対象はawslogsdeliveryアカウントID
で、下記のActionを許可します。
- バケットACL
- FULL_CONTROL
- オブジェクトACL
- 読み取りアクセス許可
- 書き込みアクセス許可
awslogsdeliveryアカウントID
はグローバルで共通のアカウントです。
CloudFrontのアクセスログはこのアカウント上から自アカウントのS3バケットに書き込まれます。
GUIからアクセスログを設定すると自動でACLが追加されるため、ふとした時にS3バケットのパーミッションを確認すると、知らないアカウントからのアクセス許可が設定されていて驚くことがあります。
怪しいアカウントではないので安心してください。
ACL設定の詳細は、こちらの公式ドキュメント内のACL for the bucket
、ACL for each log file
をご覧ください。
Terraformコード(CloudFrontアクセスログバケット作成)
Terraformでバケット作成を行うコードを記載しますので、参考まで。
resource "aws_S3_bucket" "log_cloudfront" { bucket = "<バケット名>" ##バケット所有者(自身のAWSアカウントの許可設定)の許可設定 grant { id = data.aws_canonical_user_id.current_user.id type = "CanonicalUser" permissions = ["FULL_CONTROL"] } ##awslogsdeliveryアカウントIDの許可設定 grant { id = "c4c1ede66af53448b93c283ce9448c4ba468c9432aa01d700d3878632f77d2d0" type = "CanonicalUser" permissions = ["FULL_CONTROL"] } }
ALBアクセスログ保存バケット設定
Application Load Balancerのアクセスログを保存するS3バケットには、バケットポリシーの設定が必要です。
制御パーミッションの付与対象(principal)は2つあります。
1つは外部アカウントElastic Load BalancingアカウントID
で、s3:PutObject
アクションを許可します。
ALBのアクセスログは外部アカウントElastic Load BalancingアカウントID
上から自アカウントのS3バケットに書き込まれます。
外部アカウントからアクセスログが書き込まれるのはCloudFrontと同様ですね。
ただし、Elastic Load BalancingアカウントID
はリージョン毎に異なります。
また、ALBとログ用バケットは同じリージョンである必要があります。
複数リージョンに設定する場合は注意しましょう。
もう1つはサービスlogdelivery.elb.amazonaws.com
で、s3:GetBucketAcl
アクションを許可します。
バケットポリシーの詳細は、こちらの公式ドキュメントをご覧ください。各リージョンのElastic Load BalancingアカウントID
の値も記載されています。
Terraformコード(ALBアクセスログバケットポリシー作成)
Terraformでのバケットポリシー作成用のコードを記載しますので、参考まで。
## Elastic Load Balancing アカウント ID data "aws_elb_service_account" "tf_elb_service_account" {} ## S3 Bucket Policy data "aws_iam_policy_document" "log_alb" { statement { effect = "Allow" actions = [ "s3:PutObject" ] resources = [ "<S3バケットのARN>/*" ] principals { type = "AWS" identifiers = [ data.aws_elb_service_account.tf_elb_service_account.arn ] } } statement { effect = "Allow" actions = [ "s3:GetBucketAcl" ] resources = [ "<S3バケットのARN>" ] principals { type = "Service" identifiers = [ "logdelivery.elb.amazonaws.com" ] } } }
TerraformではData Source:aws_elb_service_account
を使うことで実行リージョンに応じたElastic Load BalancingアカウントIDを取得可能です。
AWS WAFのS3アクセス制御設定
AWS WAFのアクセスログを保存するS3バケットにはバケットポリシーの設定が必要です。
AWS WAFのアクセスログのS3出力は、2021年11月のアップデートによって可能になりました。
ALBとは違って制御パーミッションの付与対象(principal)は1つで、サービスdelivery.logs.amazonaws.com
です。
このサービスに対してs3:PutObject
アクションとs3:GetBucketAcl
アクションを許可します。
logsというサービス名前空間の通り、裏ではCloudWatchLogsが動作し、ログを出力しています。
このようにCloudWatchLogsがS3に直接ログ送信を行うサービスはいくつかあります。
こちらのCloudWatchLogsのドキュメント
内の表のうち、Amazon S3
の列に✔︎記載のサービスが該当しますので、覚えておくとどこかで役に立つかもしれません。
なお、AWS WAFのアクセスログを出力するS3バケットの制約として、ログバケット名がaws-waf-logs-
から始まる必要がありますので、注意してください。
バケットポリシーの詳細は、こちらの公式ドキュメントをご覧ください。
Terraformコード(AWS WAFアクセスログバケットポリシー作成)
Terraformでのバケットポリシー作成用のコードを記載しますので、参考まで。
## S3 Bucket Policy data "aws_iam_policy_document" "log_waf" { statement { effect = "Allow" actions = [ "s3:PutObject" ] resources = [ "<ログバケットのARN>/*" ] principals { type = "Service" identifiers = [ "delivery.logs.amazonaws.com" ] } condition { test = "StringEquals" variable = "aws:SourceAccount" values = [ "<自アカウントのID>" ] } condition { test = "StringEquals" variable = "s3:x-amz-acl" values = [ "bucket-owner-full-control" ] } condition { test = "ArnLike" variable = "aws:SourceArn" values = [ "arn:aws:logs:<リージョン>:<アカウントID>:*" ] } } statement { effect = "Allow" actions = [ "s3:GetBucketAcl" ] resources = [ "<ログバケットのARN>" ] principals { type = "Service" identifiers = [ "delivery.logs.amazonaws.com" ] } condition { test = "StringEquals" variable = "aws:SourceAccount" values = [ "<自アカウントID>" ] } condition { test = "ArnLike" variable = "aws:SourceArn" values = [ "arn:aws:logs:<リージョン>:<アカウントID>:*" ] } } }
S3アクセスログ保存バケット設定
Amazon S3バケットのアクセスログを保存する別のS3バケットには、バケットポリシーの設定が必要です。
以前はACLでの設定が主流でしたが、現在は非推奨となっており、公式ドキュメントにもその記載があります。
詳細は下記ブログをご参照ください。
制御パーミッションの付与対象(principal)はAWS WAFと同じく1つで、サービスlogging.s3.amazonaws.com
です。
このサービスに対して、s3:PutObject
アクションのみを許可します。
なお、S3バケットのアクセスログを同じバケットに保存する設定はNGです。アクセスログ出力の無限ループが発生してしまいます。
バケットポリシーの詳細は、こちらの公式ドキュメントをご覧ください。
Terraformコード(S3バケットアクセスログバケットポリシー作成)
Terraformでのバケットポリシー作成用のコードを記載しますので、参考まで。
## S3 Bucket Policy data "aws_iam_policy_document" "log_s3" { statement { effect = "Allow" actions = [ "s3:PutObject" ] resources = [ "<S3バケットのARN>/*" ] principals { type = "Service" identifiers = [ "logging.s3.amazonaws.com" ] } } }
他サービスのアクセスログ保存バケット設定
2022/6/14現在、下記サービスにはアクセスログをS3バケットに保存するデフォルトの仕組みはありません。
何らかの仕組みを作り込むことが必要ですので、リンク先を参照しつつ検討しましょう。
- Amazon API Gateway
- Kinesis Data FirehoseからS3に出力できます。
- 参考:Firehoseに対応したAPI Gatewayのアクセスログ設定を試してみた
- AWS AppSync
- CloudWatchlogsに出力することは可能。そこからKinesis Data FirehoseなどでS3に出力できます。
- 参考:CloudWatch LogsのログデータをKinesis Data Firehose経由でS3に出力する
- AWS Amplify
- Amplify Consoleの静的webサイトアクセスログはコンソール画面から2週間ダウンロード可能。Lambdaなどを利用してS3に出力できます。
- 参考:Amplify ConsoleのアクセスログをS3にアップロードする(EventBridge+Lambda)
趣味のスパイスカレー
突然ですが、私の趣味はスパイスカレー作りです(半月ぶり二度目)
前回ブログから自作カレーを投稿しています。
相変わらず本筋とは全然関係ありませんが、お付き合いいただけますと幸いです。
- 豆豉豚キーマ
- レンズ豆のダル
- トマトとセロリのカチュンバル
豆豉を使った中華風豚キーマカレーを作りました。
辛さと痺れが程よく効いていて、ご飯が進みます!
カシューナッツの食感も程よいアクセントとなって◎でした。
最後に
このサービスのアクセスログってS3バケットにどうやって保存するんだっけ・・・??と毎回なっていたので、まとめてみました。
本ブログがどなたかの助けになれば幸いです。それでは。