この記事は、弁護士ドットコム株式会社の Advent Calendar 2024 の 13 日目の記事です。
皆さん、こんにちは。弁護士ドットコム、技術戦略本部・ SRE 室のテイです。今回は、S3 のブロックパブリックアクセスについて十分に理解できていないと感じたため、Security Hub で S3 のブロックパブリックアクセスに関する修復作業を行う際に自信が持てませんでした。そこで、各パターンを実際に試しながら、S3 のブロックパブリックアクセスについてあらためて勉強しました。
- ブロックパブリックアクセスについて
- S3 へアクセスしてみる
- 結論
ブロックパブリックアクセスについて
ブロックパブリックアクセスには、以下の 4 つのオプションがあります。
新しいアクセスコントロールリスト (ACL) を介して付与されたバケットとオブジェクトへのパブリックアクセスをブロックする
- パブリックアクセス可能な ACL がついたオブジェクトを新規追加できなくなります
- 既存のオブジェクトの権限を変更しません
- 任意のアクセスコントロールリスト (ACL) を介して付与されたバケットとオブジェクトへのパブリックアクセスをブロックする
- バケットとオブジェクトへのパブリックアクセスを許可するすべての ACL を無視して、パブリックアクセスを拒否するという事です
新しいパブリックバケットポリシーまたはアクセスポイントポリシーを介して付与されたバケットとオブジェクトへのパブリックアクセスをブロックする
- バケットとオブジェクトへのパブリックアクセスを許可する新しいバケットポリシーとアクセスポイントポリシーをブロックします
バケットポリシーを変更するとき、より広い範囲に変更しようとすると失敗します
チェックが有効になっている状態で、バケットポリシーにパブリックアクセス可能な設定を適用しようとすると、エラーが発生します。
チェックを無効にすると、バケットポリシーでパブリックアクセス可能な設定を保存できるようになります。
任意のパブリックバケットポリシーまたはアクセスポイントポリシーを介したバケットとオブジェクトへのパブリックアクセスとクロスアカウントアクセスをブロックする
- バケットポリシーで公開になっていたとしても無視してパブリックアクセスをブロックすることです
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
(2) ブロックなし + バケットポリシーあり
以下のバケットポリシーを追加し、アクセスを試してみます。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::[S3 バケット名]/*" } ] }
結果:画像が正常に表示されました
ポリシーがない場合、暗黙的な拒否によりアクセスは拒否されることが確認されました。
(3) ブロックあり + バケットポリシーあり
4. 任意のパブリックバケットポリシーまたはアクセスポイントポリシーを介したバケットとオブジェクトへのパブリックアクセスとクロスアカウントアクセスをブロックする
こちらのオプションを有効にして、アクセスを試してみます。
結果:AccessDenied
バケットポリシーでアクセスが許可されているにもかかわらず、アクセスがブロックされました。
(4) ブロックあり + バケットポリシーなし
最後、バケットポリシーを削除して、アクセスを試してみます。
結果: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 の場合
Public に指定した場合、S3 バケットポリシーには"Principal": "*"
のポリシーを追加する必要があります。
ブロックパブリックアクセスが有効な場合に、アクセスを試みます。
結果は AccessDenied になり、アクセスができません。
次はブロックパブリックアクセスが無効な場合、アクセスをためしてみます。
結果:アクセスができました
Public
に指定した場合、その名のとおり、パブリックアクセスであることが確認できます。
OAC(Origin Access Control)の場合
ポリシーをコピーし、S3 のバケットポリシーに貼り付けます。
ブロックパブリックアクセスが有効な場合と無効な場合の両方で、アクセスを試みます。
結果:どちらの場合でもアクセスできました。
OAC(Origin Access Control)を使用した場合、パブリックアクセスではないことが確認できます。
CloudFront のアクセスログ出力
S3 バケットが作成されると、ACL(アクセス制御リスト)は無効化された状態になります。
そのため、CloudFront のアクセスログを有効化する際には、以下のようなメッセージが表示されます。
ログファイルを S3 バケットに出力するため、ACL を有効にします。
その後、ブロックパブリックアクセスが有効な場合と無効な場合の両方で、アクセスを試みます。
結果:どちらの場合でもアクセスできました。
アクセスログの出力は、パブリックアクセスではないことが確認できます。
結論
- オブジェクト URL を使ってブラウザでアクセス
- パブリックアクセス:⭕
- ローカルマシンからの API アクセス
- パブリックアクセスではない:❌
- 他アカウントからの API アクセス
- パブリックアクセスではない:❌
- S3 Presigned URL(署名付き URL)を使ってブラウザアクセス
- パブリックアクセスではない:❌
- 自アカウント内 AWS サービスによるアクセス
- EC2 など VPC 内サービスからの API アクセス
- パブリックアクセスではない:❌
- CloudShell など VPC 外からの API アクセス
- パブリックアクセスではない:❌
- EC2 など VPC 内サービスからの API アクセス
- CloudFront から S3 オリジンへのアクセス
- Public の場合
- パブリックアクセス:⭕
- OAC(オリジンアクセスコントロール)の場合
- パブリックアクセスではない:❌
- Public の場合
- CloudFront のアクセスログ出力
- パブリックアクセスではない:❌
以上で、S3 のブロックパブリックアクセスに関する動作検証を終わります。皆さんの参考になれば嬉しいです。