ACL無効化が推奨されたことでS3のサーバアクセスログ記録のためのアクセス許可はどうなったのか!?確認してみた

ACL無効化が推奨されたことで、アクセス許可にACLを使用していたサーバアクセスログ記録設定でもバケットポリシーを使用するようドキュメントが更新されていました。マネジメントコンソールからの設定でもバケットポリシーが更新されるようになっています。
2021.12.10

はじめに

清水です。re:Invent 2021期間中に発表された数多くのアップデートの中で、個人的に最も印象深いものの1つがAmazon S3のACL無効化機能です。

このアップデートの発表とともに、ACLについては無効化することが推奨となりました。アクセス許可についてはACLを使わずにポリシーで制御するかたちですね。個人的には、ここ最近はS3のアクセス許可についてACLをほとんど使わずポリシーで行っていたため、それほどこのアップデートの影響はない(むしろやはりACLを気にしなくてよくなるのでスッキリ!)と思っていたのですが、1点、ACLを意図せずですが利用している場面がありました。S3のサーバアクセスログ記録のための、ログ出力先となるS3バケットのアクセス許可設定です。 *1 ログ配信のため「S3ログ配信グループ(Log Deliveryグループ)」に権限を付与するかたちで設定を行う必要がありました。AWSマネジメントコンソールからサーバアクセスログ記録の設定を行う場合は自動で設定されていたため、意識せずにACLが設定されていたというケースもあるのではないでしょうか。これがACL無効化が推奨されたことでどのように扱われるのか、気になったので確認してみました。

確認した結果を先にまとめると以下となります。S3のサーバアクセスログ記録のための保存先のS3バケットのアクセス許可として、

  • ドキュメント上ではACLで設定する方法ではなく、バケットポリシーで設定する方法が案内されるようになりました
  • AWSマネジメントコンソールからサーバアクセスログ記録を設定する場合、ACLではなくバケットポリシーが設定されるようになりました

従来のACLを利用したS3サーバアクセスログ記録の設定

まずは従来までのACLを利用したS3サーバアクセスログの配信設定について確認しておきましょう。私の手元にある、S3のサーバアクセスログを出力しているS3バケットのアクセス許可設定について、AWSマネジメントコンソールから確認してみると以下のようになっています。

まずバケットポリシーについては空の状態です。

オブジェクト所有者の箇所は、ACLが有効でオブジェクト所有者がオブジェクトライターという状態です。(ACL無効化のアップデート以前に作成などしてあるS3バケットはこの状態かと思います。)

そしてアクセスコントロールリスト (ACL)の箇所です。バケット所有者の権限のほか、 S3ログ配信グループ (http://acs.amazonaws.com/groups/s3/LogDelivery)に オブジェクトの書き込み、バケットACLの読み込みの権限が付与されていました。

このACL設定により、S3のLog Deliveryグループがアクセスログを書き込んでいたわけです。このACL設定につては明示的に設定していなくても、S3のマネジメントコンソールから「サーバーアクセスのログ記録」を有効にした場合、自動的に設定されたと記憶しています。(後述しますが、2021/12/10時点ではACLではなくバケットポリシーが設定されるようになっています。)

このACLによりLog Deliveryのアクセス制限を行っていた点については、2021/12/10の段階の日本語版ドキュメントの記載でも確認ができます。(まだACL無効化推奨の反映がなされていない状況かと思います。しばらくすれば後述するACL無効化推奨、バケットポリシーによる設定方法が記載されるはずです。)

サーバーアクセスログを使用したリクエストのログ記録 - Amazon Simple Storage Service

ACLを使用しないS3サーバアクセスログ記録の設定

ドキュメント記載のバケットポリシーによるアクセス許可の設定

ACL無効化が推奨された今、S3サーバアクセスログが配信されるバケットのアクセス許可もACL無効で設定しておきたいですよね、英語版ドキュメントを確認すると、バケットポリシーを使用した方法が記載されていました。(まもなく日本語版ドキュメントにも反映されるかと思います!)

Logging requests using server access logging - Amazon Simple Storage Service

"Permissions for log delivery"のリンクをたどると、実際のバケットポリシーの例についても記載があります。service principal logging.s3.amazonaws.comに対して、s3:PutObjectの許可を与えるぐあいですね。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "S3ServerAccessLogsPolicy",
            "Effect": "Allow",
            "Principal": {
                "Service": "logging.s3.amazonaws.com"
            },
            "Action": [
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/EXAMPLE-LOGGING-PREFIX*",
            "Condition": {
                "ArnLike": {
                    "aws:SourceARN": "arn:aws:s3:::SOURCE-BUCKET-NAME"
                },
                "StringEquals": {
                    "aws:SourceAccount": "SOURCE-ACCOUNT-ID"
                }
            }
        }
    ]
}

こちらにバケットポリシーの例をもとに、実際にS3のサーバアクセスログを出力する先(保存先)のS3バケット「s3-logs-no-acl-1」にバケットポリシーを設定してみます。アクセスログ取得対象のS3バケットは「test-bucket-202112-1」で、保存先にも同名のPrefixを指定することとしました。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "S3ServerAccessLogsPolicy",
            "Effect": "Allow",
            "Principal": {
                "Service": "logging.s3.amazonaws.com"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::s3-logs-no-acl-1/test-bucket-202112-1*",
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": "81XXXXXXXX29"
                },
                "ArnLike": {
                    "aws:SourceARN": "arn:aws:s3:::test-bucket-202112-1"
                }
            }
        }
    ]
}

ACL設定については、以下のように無効になっている状態です。

アクセスログの取得対象のS3バケット「test-bucket-202112-1」で、サーバアクセスログ記録を有効にします。このサーバアクセスログ記録の設定はマネジメントコンソールからではなく、AWS CLI経由で行いました。(後述しますが、マネジメントコンソールで設定すると、自動的にポリシーが追記されてしまう挙動のためです。)

$ aws s3api get-bucket-logging \
    --bucket test-bucket-202112-1 # サーバアクセスログ記録設定前

$ cat logging.json # サーバアクセスログ記録設定についての確認
{
    "LoggingEnabled": {
        "TargetBucket": "s3-logs-no-acl-1",
        "TargetPrefix": "test-bucket-202112-1/"
    }
}

$ aws s3api put-bucket-logging \
    --bucket test-bucket-202112-1 
    --bucket-logging-status file://logging.json # サーバアクセスログ記録の設定

$ aws s3api get-bucket-logging 
    --bucket test-bucket-202112-1 # サーバアクセスログ記録設定後
{
    "LoggingEnabled": {
        "TargetBucket": "s3-logs-no-acl-1",
        "TargetPrefix": "test-bucket-202112-1/"
    }
}

以上で設定完了です。しばらくすると、ログ取得対象のS3バケット「test-bucket-202112-1」へのアクセスログが出力されていました。

マネジメントコンソールからサーバアクセスログ記録を有効にした場合

続いて、サーバアクセスログを出力する先(保存先)のS3バケットのバケットポリシーは特に設定せず、AWSマネジメントコンソールのアクセスログを記録するS3バケットの設定から、サーバアクセスログ記録を有効にした場合の挙動を確認してみましょう。ACL無効化機能のアップデート前までは、この操作で自動的に保存先のS3バケットにACLが設定されていました。

ACLを無効にした状態で、ログ出力先となるS3バケット「s3-logs-no-acl-2」を作成しました。バケットポリシーは空の状態です。

ACLは以下の設定(無効状態)となっています。

アクセスログの取得対象のS3バケット「test-bucket-202112-2」で、マネジメントコンソールからサーバアクセスログ記録を有効にします。 バケットポリシーが更新される 旨、記載がありますね。保存先にもバケットと同名のPrefixを指定します。

サーバアクセスログ記録を有効にしたあと、ログ出力先となるS3バケット「s3-logs-no-acl-2」のアクセス許可について再度確認してみます。以下のようなバケットポリシーが設定されていました。

{
    "Version": "2012-10-17",
    "Id": "S3-Console-Auto-Gen-Policy-1639123099432",
    "Statement": [
        {
            "Sid": "S3PolicyStmt-DO-NOT-MODIFY-1639123099337",
            "Effect": "Allow",
            "Principal": {
                "Service": "logging.s3.amazonaws.com"
            },
            "Action": [
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::s3-logs-no-acl-2/*"
        }
    ]
}

ACLまわり(オブジェクト所有者とACL)の項目はサーバアクセスログ記録を有効にする前と変わりありません。ACLが無効の状態となります。

マネジメントコンソールからサーバアクセスログ記録を有効にした場合、これまでのACLの更新ではなく、バケットポリシーが更新される という挙動となりますね。このマネジメントコンソールにより更新されたバケットポリシー、内容としてはドキュメント記載のものと同じく、logging.s3.amazonaws.comのservice principalに対してS3バケットへの書き込み許可を与えるものとなります。ただ細かく見てみると、s3:PutObjectAclの有無などの違いがあるようです。

こちらのバケットポリシーの設定でも(マネジメントコンソールから設定されたものなので当たり前ではありますが)、しばらくするとアクセスログが無事書き込まれていることが確認できました。

マネジメントコンソールによるバケットポリシー更新の細かな挙動

ACLを使用しないS3サーバアクセスログ記録のターゲット(出力先/保存先)バケットのアクセス許可設定について、ドキュメントではバケットポリシーによる設定方法が記載されており、またマネジメントコンソールからサーバアクセスログ記録を有効にする際にはバケットポリシーが更新されるようになっていることが確認できました。

ここではマネジメントコンソールからのバケットポリシーの更新について、少し細かな挙動が気になったので確認した結果をまとめてみます。

ACLが有効なS3バケットを保存先にした場合でもバケットポリシーが更新される

マネジメントコンソールからサーバアクセスログ記録を有効にした場合、ターゲットバケットのバケットポリシーが自動で更新されることを確認しました。これはターゲットのS3バケットでACLが有効になっていても同様のようです。

従来はターゲットのS3バケットで暗黙的にACLが有効であり、ACLの設定が更新されるかたちでした。この挙動から、ターゲットのS3バケットでACLが有効であれば、引き続きACLの設定が更新されるのかな、とも思いましたが、現在では(ACLの有効/無効に関わらず)一律でバケットポリシーが更新されるぐあいです。

以下のように、ACLを有効に設定したS3バケット「s3-logs-using-acl-1」を準備します。バケットポリシーは空の状態です。

この「s3-logs-using-acl-1」をターゲットバケットとして、「test-bucket-202112-3」でサーバアクセスログ記録を有効にしてみます。

出力先ターゲットバケット「s3-logs-using-acl-1」のアクセス許可を確認してみます。以下のようにバケットポリシーが設定され、ACLまわりの変更(これまでのような「S3ログ配信グループ」に対する権限付与)はありませんでした。

バケットポリシーを記載した状態でマネジメントコンソールからサーバアクセスログ記録を有効にすると上書きではなく追記される

もう一つ、バケットポリシーを設定した状態のログ保存用S3バケットをターゲットバケットとして、マネジメントコンソールからからサーバアクセスログ記録を設定した挙動を確認してみました。こちらの場合はバケットポリシーが上書きされるのではなく、既存のポリシーに追記されるという挙動となりました。

以下のように、事前にACL無効のアクセスログ保存用のS3バケット「s3-logs-no-acl-3」にバケットポリシーを設定しておきます。

このあと、アクセスログ取得の対象となるS3バケット「test-bucket-202112-4」でマネジメントコンソールからサーバアクセスログ記録を有効にしてみます。

設定後、ターゲットバケットの「s3-logs-no-acl-3」でバケットポリシーを確認してみましょう。以下のようにすでに設定していたバケットポリシーに加え、ステートメントが追加される、という挙動となりました。

まとめ

これまでACLを使ってアクセス許可を設定していたS3のサーバアクセスログ記録のターゲットバケットについて、ACL無効化が推奨となった現在、バケットポリシーでアクセス許可を設定することがドキュメント上では案内され、またマネジメントコンソールからの自動設定でもバケットポリシーが更新されることを確認してみました。

Amazon S3のリリースからはや15年、システムを止めたり機能を使えなくすることなく、しかしより使いやすいように進化していく姿はすごいなぁという言葉しか出ません。今後作成していくS3バケットはもれなくACLを無効化していきたいと思ったしだいでした。

2021/12/17 追記

もれなくACLを無効化していきたいしだいですが、確認してみたところCloudFrontのアクセスログ保存用S3バケットはACL有効化が2021/12/17の時点で必要でした。注意しましょう。

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

脚注

  1. 「まとめ」にも追記しましたが、CloudFrontのアクセスログ出力先のS3バケットのアクセス許可制限もACLを使用しています。こちらは2021/12/17の段階でACL有効化が必要となっています。(2021/12/17記)