CloudFront のアクセスログを S3 に保管する場合は、オブジェクト所有者を「希望するバケット所有者」にして、バケットポリシーとIAMポリシーで制御できるようにしよう

CloudFront のアクセスログの保存先 S3 バケットは、ACL 有効化が必須になっています。オブジェクト所有者を「希望するバケット所有者」にすると、オブジェクトの所有者とバケットの所有者が同一になり、オブジェクトのアクセスをバケットポリシーと IAM ポリシーで管理できるようになります。
2023.04.24

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

猫とアポロチョコと Systems Manager が好きな m.hayakawa です。

今回は S3 のバケット ACL と CloudFront のアクセスログの保存先の S3 バケットの設定に関する記事となります。

現在、S3 のバケット ACL は無効化が推奨されており、バケットの作成時のデフォルトではバケット ACL 無効化が選択されております。

すべての新しいバケットの ACL を無効にし、オブジェクト所有権を執行します。 - Amazon Simple Storage Service

Amazon S3 バケットで ACL を無効にすることをお勧めします。これを行うには、S3 オブジェクトの所有権のバケット所有者強制設定を適用します。この設定を適用すると、ACL が無効になり、バケット内のすべてのオブジェクトを自動的に所有し、完全に制御できるようになります。

しかしながら、バケット ACL を有効化しなければいけないケースがあります。

CloudFront のアクセスログの保存先 S3 バケットは ACL を有効化する必要がある

CloudFront のアクセスログの記録先の S3 バケットは ACL 有効化が必須となっています。

標準ログ (アクセスログ) の設定および使用 - Amazon CloudFront

ドキュメント日本語訳

S3オブジェクトの所有権がバケットオーナー強制に設定されているAmazon S3バケットを選択しないでください。この設定は、バケットとその中のオブジェクトに対するACLを無効にし、CloudFrontがバケットにログファイルを配信するのを防ぎます。

CloudFront のアクセスログの記録は、AWS 内部のアカウントであるawslogsdeliveryが行います。

そのため、バケット ACL でawslogsdeliveryからのアクセスを有効にする必要があります。

なお、CloudFront のディストリビューション設定で、ロギングを有効にした場合、CloudFront はバケットの ACL を更新し、awslogsdelivery アカウントに FULL_CONTROL のアクセス許可を付与するため、手動でバケット ACL を更新する必要はありません。

オブジェクト所有者について

バケット ACL を有効化している場合、オブジェクト所有者の設定は 2 通りあります。

オブジェクトライター

従来の形になります。この場合、CloudFront のアクセスログとして保存されるオブジェクトの所有者は、バケットの所有者ではなく、awslogsdeliveryとなります。そのため、バケットポリシーと IAM ポリシーでは制御ができなくなります。

クロスアカウントでアクセスをする際は、CloudFront のアクセスログが保存されている S3 バケットが所属しているアカウントの IAM ロールにスイッチする必要があります。また、スイッチ先のロールでは、S3 バケットのアクセスを許可する IAM ポリシーの付与が必要となります。

希望するバケット所有者

この場合、オブジェクト所有者とバケットの所有者が同一となるため、バケットポリシーと IAM ポリシーで制御をすることが可能となります。

クロスアカウントでアクセスを許可する場合は、バケットポリシーに別アカウントの IAM エンティティ(ユーザーやロール)からのアクセスを明示的に許可する必要があります。

{
    "Version": "2012-10-17",
    "Id": "ExamplePolicy01",
    "Statement": [
        {
            "Sid": "ExampleStatement01",
            "Effect": "Allow",
            "Principal": [
                "AWS": "arn:aws:iam::<別アカウントID>:user/<ユーザー名>",
                "AWS": "arn:aws:iam::<別アカウントID>:role/<ロール名>"
            ],
            "Action": [
                "s3:GetObject",
                "s3:GetBucketLocation",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::ExampleBucket/*",
                "arn:aws:s3:::ExampleBucket"
            ]
        }
    ]
}

その後、アクセス元の IAM ユーザー/ロールには S3 に対するアクセス権限を追加します。例えば、読み込み権限のみで良ければ、AWS 管理ポリシーのAmazonS3ReadOnlyAccessが考えられます。

ACL 無効化にした場合と同じ方法で制御できるため、今後はこの方法を行うことが望ましいでしょう。

すでに保存済みのオブジェクトのオブジェクト ACL はどうやって編集すればいいの?

すでにオブジェクトライターの状態で CloudFront のログを S3 に書き込んでしまった場合、オブジェクト所有者とバケットの所有者が異なるため、バケットポリシーと IAM ポリシーではアクセス制御ができません。

そのため、下記コマンドを用いてオブジェクトの上書きコピーを行うことで、オブジェクト所有者とバケットの所有者を同一にすることが可能です。

aws s3 cp s3://<バケット名>/<上書きを行うオブジェクトのプレフィックス> s3://<バケット名>/<上書きを行うオブジェクトのプレフィックス> --recursive --acl bucket-owner-full-control

まとめ

通常の場合は、S3 のバケット ACL は無効化することが推奨されています。しかしながら、現時点で CloudFront のアクセスログ保存先バケットは ACL を有効化する必要があります。

この場合、バケットポリシーと IAM ポリシーでアクセス制御できるようにするため、ACL は有効化とし、オブジェクト所有者設定を「希望するバケット所有者」とすることが望ましいです。

オブジェクト所有者設定を「オブジェクトライター」のままにしてしまったオブジェクトについては、オブジェクトの上書きコピーをすることで、オブジェクト所有者とバケットの所有者を同一にする処理が必要です。

参考資料

標準ログ (アクセスログ) の設定および使用 - Amazon CloudFront

オブジェクトの所有権の制御とバケットの ACL の無効化。 - Amazon Simple Storage Service

例 4: バケット所有者が所有権のないオブジェクトへのクロスアカウントアクセス許可を付与する - Amazon Simple Storage Service

Amazon S3 の AWS マネージドポリシー - Amazon Simple Storage Service

関連する DevelopersIO の記事

CloudFrontのアクセスログ保存用S3バケットにはACL有効化が必要なので注意しよう | DevelopersIO

S3 のオブジェクト ACL を有効化にするケースまとめ | DevelopersIO

S3 のオブジェクトACLの無効化が推奨となったので、改めて IAM ポリシーと S3 バケットポリシーの評価論理をまとめてみた | DevelopersIO