この投稿はGlobal Mobility Serviceのアドベントカレンダーの25日目です。
AWSでの今年の失敗を振り返りたいと思います。
S3のパブリック公開でやらかしました。
要約
S3のバケットポリシーによるパブリック公開はオブジェクトの権限によってパブリックじゃない時もあるので気をつけよう
失敗について
失敗までの経緯
S3のパブリック公開を調べてみると公式ドキュメントで以下の内容が見つかります。
匿名ユーザーへの読み取り専用アクセス許可の付与
次のポリシー例では、任意のパブリック匿名ユーザーに s3:GetObject アクセス許可を付与します。(これによって許可されるアクセスとオペレーションの一覧については、「ポリシーでのアクセス許可の指定」を参照してください。) このアクセス許可はオブジェクトデータを誰でも読み取り可能にするので、バケットをウェブサイトとして設定し、バケット内のオブジェクトをすべての人が読み取れるようにする場合に便利です。
これを見て、以下のようなバケットポリシーをパブリック公開したいバケットに設定しておけば大丈夫と思ってしまいました。
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"PublicRead",
"Effect":"Allow",
"Principal": "*",
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::examplebucket/*"]
}
]
}
ちなみに、このバケットポリシーを設定するとAWSコンソール上でパブリックであることがアピールされるので、なんとなくこれで大丈夫だと思ってしまいます。
失敗したケース
普段利用しているAWS環境はマルチアカウントになっています。
本ケースでは、以下のように別アカウント間でS3にオブジェクトを配置するという流れでした。
BアカウントからAアカウントのバケットにPutObjectするのに、以下のようなバケットポリシーを適用しました。
特定のロールにPutObjectを許可するポリシーです。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::hi1280-public/*"
},
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::012345678901:role/AAccountAccessRole"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::hi1280-public/*"
}
]
}
あとは、Bアカウントの環境からAWS CLIを使ってPutObjectをするだけの簡単なお仕事だと思って、オブジェクトを配置して安心していました。
が、のちに公開したはずのオブジェクトが見れないという連絡が来て焦りました。
実はこのようなケースの場合、PutObjectでオブジェクトを置いてもパブリック公開されません。
その当時は全く見ていなかったのですが、公式ドキュメントにちゃんと書かれていました。
注記
バケットとオブジェクトの所有者が同じ場合、オブジェクトへのアクセスは、バケットコンテキストで評価されるバケットポリシーで許可することができます。
つまり、バケットポリシーのみでパブリック公開できるのは、バケットが存在するAWSのアカウントと同じユーザやロールがオブジェクトを配置した時のみでした。
どうすれば良いのか
さらにこのような記述があります。
所有者が異なる場合、オブジェクトの所有者はオブジェクト ACL を使用してアクセス許可を付与する必要があります。
AWSのアカウントが異なる場合は、オブジェクトを配置したユーザやロールがACLでオブジェクトに対してアクセス権限を付与しなければいけなかったのです。
AWS CLIを使う場合、以下のコマンドです。
$ aws s3api put-object-acl --bucket bucket-name --key my_object --acl public-read
これで無事にオブジェクトをパブリック公開することができます。
まとめ
油断大敵。確認を怠らないようにしなければと思いました。
皆様におかれましては、このような失敗が起きないようにS3におけるアクセス権限には十分にお気をつけください。
おわりに
AWSはやっぱりよく分からないので色々学びあえるエンジニアを募集しています。