弁護士ドットコム株式会社 Creators’ blog

弁護士ドットコムがエンジニア・デザイナーのサービス開発事例やデザイン活動を発信する公式ブログです。

S3 ブロックパブリックアクセス(バケット設定)の再勉強

S3 ブロックパブリックアクセス (バケット設定)の再勉強この記事は、弁護士ドットコム株式会社の Advent Calendar 2024 の 13 日目の記事です。


皆さん、こんにちは。弁護士ドットコム、技術戦略本部・ SRE 室のテイです。今回は、S3 のブロックパブリックアクセスについて十分に理解できていないと感じたため、Security Hub で S3 のブロックパブリックアクセスに関する修復作業を行う際に自信が持てませんでした。そこで、各パターンを実際に試しながら、S3 のブロックパブリックアクセスについてあらためて勉強しました。

ブロックパブリックアクセスについて

ブロックパブリックアクセスには、以下の 4 つのオプションがあります。

  1. 新しいアクセスコントロールリスト (ACL) を介して付与されたバケットとオブジェクトへのパブリックアクセスをブロックする

    • パブリックアクセス可能な ACL がついたオブジェクトを新規追加できなくなります
    • 既存のオブジェクトの権限を変更しません
  2. 任意のアクセスコントロールリスト (ACL) を介して付与されたバケットとオブジェクトへのパブリックアクセスをブロックする
    • バケットとオブジェクトへのパブリックアクセスを許可するすべての ACL を無視して、パブリックアクセスを拒否するという事です
  3. 新しいパブリックバケットポリシーまたはアクセスポイントポリシーを介して付与されたバケットとオブジェクトへのパブリックアクセスをブロックする

    • バケットとオブジェクトへのパブリックアクセスを許可する新しいバケットポリシーとアクセスポイントポリシーをブロックします
    • バケットポリシーを変更するとき、より広い範囲に変更しようとすると失敗します
      パブリックアクセスがすべてブロックする設定

      チェックが有効になっている状態で、バケットポリシーにパブリックアクセス可能な設定を適用しようとすると、エラーが発生します。 バケットポリシーの設定 バケットポリシーが編集できるようなパブリックアクセスの設定

      チェックを無効にすると、バケットポリシーでパブリックアクセス可能な設定を保存できるようになります。 バケットポリシーが設定できるようになった

  4. 任意のパブリックバケットポリシーまたはアクセスポイントポリシーを介したバケットとオブジェクトへのパブリックアクセスとクロスアカウントアクセスをブロックする

    • バケットポリシーで公開になっていたとしても無視してパブリックアクセスをブロックすることです

S3 へアクセスしてみる

そもそも「パブリックアクセス」とはどのようなものでしょうか。 たとえば、S3 オブジェクトの URL をブラウザで直接開くことは明らかにパブリックアクセスに該当しますが、他にはどのようなパターンが考えられるでしょうか。

そこで、テスト用の S3 バケットを作成し、以下のアクセス方法について試してみます。 - オブジェクト URL を使用したブラウザでのアクセス - ローカルマシンからの API アクセス - 他アカウントからの API アクセス - S3 Presigned URL(署名付き URL)を使ってブラウザアクセス - 自アカウント内の AWS サービスによるアクセス - VPC 内サービス(例:EC2)からの API アクセス - VPC 外サービス(例:CloudShell)からの API アクセス - CloudFront 経由での S3 オリジンへのアクセス - Public の場合 - OAC(Origin Access Control)の場合 - CloudFront のアクセスログ出力

オブジェクト URL を使ってブラウザでアクセス

(1) ブロックなし + バケットポリシーなし

ブロックパブリックアクセスを無効(オフ)にし、バケットポリシーを空の状態にして、アクセスを試してみます。 ブロックなし + バケットポリシーなし

結果:AccessDenied
AccessDenied


(2) ブロックなし + バケットポリシーあり

以下のバケットポリシーを追加し、アクセスを試してみます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::[S3 バケット名]/*"
        }
    ]
}

ブロックなし + バケットポリシーあり

結果:画像が正常に表示されました
ポリシーがない場合、暗黙的な拒否によりアクセスは拒否されることが確認されました。


(3) ブロックあり + バケットポリシーあり

4. 任意のパブリックバケットポリシーまたはアクセスポイントポリシーを介したバケットとオブジェクトへのパブリックアクセスとクロスアカウントアクセスをブロックする

こちらのオプションを有効にして、アクセスを試してみます。
ブロックあり + バケットポリシーあり

結果:AccessDenied
AccessDenied バケットポリシーでアクセスが許可されているにもかかわらず、アクセスがブロックされました。


(4) ブロックあり + バケットポリシーなし

最後、バケットポリシーを削除して、アクセスを試してみます。
ブロックあり + バケットポリシーなし

結果:AccessDenied
AccessDenied アクセスできない要素が重なっているため、アクセスできません。

以上から、オブジェクト URL を使ってブラウザでアクセスした場合、パブリックアクセスであることが確認できます。

ローカルマシンからの API アクセス

ブロックパブリックアクセスの設定をすべて有効にし、バケットポリシーが空白の状態で、ローカルマシンから AWS CLI を使ってアクセスしてみます。 ブロックパブリックアクセスの設定をすべて有効にし、バケットポリシーが空白の状態

結果:アクセスができました
アクセスができた

インターネット経由でのアクセスですが、パブリックアクセスではないということが確認できます。
IAM ロールによる認証でアクセスしているため、バケットポリシーがなくてもアクセス可能です。

他アカウントからの API アクセス

ブロックパブリックアクセスをすべて有効にします。 他の AWS アカウント B からのアクセスを許可するバケットポリシーが設定されている状態で、AWS アカウント B の CloudShell から AWS CLI を使ってアクセスしてみます。 ブロックパブリックアクセスをすべて有効にしてバケットポリシーが設定されている状態

結果:アクセスができました
アクセスができた ブロックは設定されているもののアクセス可能であるため、パブリックアクセスではないようです。

S3 Presigned URL(署名付き URL)を使ってブラウザアクセス

aws s3 presignコマンドを使用して、署名付き URL を生成します。生成した URL に対して、ブロックが無効な状態有効な状態の両方でアクセスを試みます。

$ aws s3 presign --expires-in 600 s3://[S3 バケット名]/ACmilan.jpg

結果:どちらもアクセスができました。
URL にはアクセスキーや署名が入っているので、AWS アカウント認証を持っているのとひとしい権限を持つ状態になり、パブリックアクセスではないようです。

自アカウント内の AWS サービスによるアクセス

VPC 内サービス(例:EC2)からの API アクセス

同じ VPC 内に、EC2 と S3 用の VPC エンドポイントを作成して「ブロックあり + バケットポリシーなし」の状態でアクセスを試してみます。

結果:アクセスができました
パブリックアクセスではないことが確認できます。

VPC 外サービス(例:CloudShell)からのAPIアクセス

「ブロックあり+バケットポリシーなし」の状態で CloudShell を起動してアクセスをためしてみます。

結果:アクセスができました 同様にパブリックアクセスではないことが確認できます。

CloudFront 経由での S3 オリジンへのアクセス

CloudFront に IAM ロールは設定しません。ブラウザを使用して、CloudFront 経由で S3 のオブジェクトにアクセスします。

Public の場合

Cloudfront のオリジン編集

Public に指定した場合、S3 バケットポリシーには"Principal": "*"のポリシーを追加する必要があります。 ブロックパブリックアクセスが有効な場合に、アクセスを試みます。 ブロックパブリックアクセスをすべて有効にしてバケットポリシーが設定されている状態

結果は AccessDenied になり、アクセスができません。


次はブロックパブリックアクセスが無効な場合、アクセスをためしてみます。
ブロックパブリックアクセスをすべて無効にしてバケットポリシーが設定されている状態

結果:アクセスができました

Public に指定した場合、その名のとおり、パブリックアクセスであることが確認できます。

OAC(Origin Access Control)の場合

Cloudfront のオリジン編集

ポリシーをコピーし、S3 のバケットポリシーに貼り付けます。
バケットポリシーの設定

ブロックパブリックアクセスが有効な場合と無効な場合の両方で、アクセスを試みます。

結果:どちらの場合でもアクセスできました。

OAC(Origin Access Control)を使用した場合、パブリックアクセスではないことが確認できます。

CloudFront のアクセスログ出力

S3 バケットが作成されると、ACL(アクセス制御リスト)は無効化された状態になります。
S3 バケットの ACL 設定

そのため、CloudFront のアクセスログを有効化する際には、以下のようなメッセージが表示されます。 CloudFront 設定時のエラーメッセージ

ログファイルを S3 バケットに出力するため、ACL を有効にします。
S3 バケットの ACL の有効化設定

その後、ブロックパブリックアクセスが有効な場合と無効な場合の両方で、アクセスを試みます。

結果:どちらの場合でもアクセスできました。
アクセスができた

アクセスログの出力は、パブリックアクセスではないことが確認できます。

結論

  • オブジェクト URL を使ってブラウザでアクセス
    • パブリックアクセス:⭕
  • ローカルマシンからの API アクセス
    • パブリックアクセスではない:❌
  • 他アカウントからの API アクセス
    • パブリックアクセスではない:❌
  • S3 Presigned URL(署名付き URL)を使ってブラウザアクセス
    • パブリックアクセスではない:❌
  • 自アカウント内 AWS サービスによるアクセス
    • EC2 など VPC 内サービスからの API アクセス
      • パブリックアクセスではない:❌
    • CloudShell など VPC 外からの API アクセス
      • パブリックアクセスではない:❌
  • CloudFront から S3 オリジンへのアクセス
    • Public の場合
      • パブリックアクセス:⭕
    • OAC(オリジンアクセスコントロール)の場合
      • パブリックアクセスではない:❌
  • CloudFront のアクセスログ出力
    • パブリックアクセスではない:❌

以上で、S3 のブロックパブリックアクセスに関する動作検証を終わります。皆さんの参考になれば嬉しいです。