こんにちは。クイックSREチームのみっちーです。
今日は、S3のbucket policy についての記事です。
前回の記事で「S3 bucket policy」については少し触れましたが、今回はもう少し内容を掘り下げていこうと思います。
おまけで、いくつかサンプル設定も載せたので、ぜひ最後まで読んでみて下さい✧(・ㅂ・)و
今回の記事は、こんな人向けです。
「これからS3にアクセス制限を実施しよう!」と思っている人。
「S3 bucket policy が意図した動作をしてくれない」と嘆いている人。
「とりあえずサンプルが欲しい」と思っている人。
目次
1. S3で出来るアクセス制限の方法(種類)
bucket policyの話に入る前に、
まずはS3で出来る「アクセス制限の方法(種類)」についてのおさらいです。
S3では大きく分けて、以下の3種類の方法でアクセス制限をする事ができます。
それぞれの設定は独立していて、併用が可能です。
S3 bucket policy を利用した方法 ※ 今回はこれについての説明です
- bucketのアクセス「ルール」を細かく記載する。
- JSON形式で記載。
メリット
- 「特定IPアドレスのみ許可」 したり、 「特定アカウントと特定IPのみを許可」 と言った、やや複雑なルールも書ける。
デメリット
- 「ルール」の評価優先度にクセがある(詳細は後述)ため、慣れるまでは扱いが難しい。
ACL(Access Control List) を利用した方法
- bucketにアクセスできる「ユーザ」を設定する。
「特定アカウントのみ許可」 や、 「全ユーザ公開(public read)」 など。
メリット
- 設定が簡単。
管理コンソールから、「アカウント名と、許可する動作にチェックを入れるだけ」でOK。
デメリット
- 設定が簡単な反面、単純な設定しか出来ない。
IAM を利用した方法
- aws IAMサービスを利用してアクセス制限をする。
- bucketにアクセスできる「IAMユーザ」を設定する。
- JSON形式で記載。
メリット
- 異なるアカウント管理下にあるS3 bucketを参照したりする設定が出来る。
- IAMの書き方がS3 bucket policyとほぼ同じで、どちらかを覚えれば応用が効く。
デメリット
- IAMの使い方を覚える必要がある。
- 通常、S3上のオブジェクトを公開するだけなら使う必要はない。
2. bucket policy の書き方
「ルール(Effect)」と「評価優先度」
S3 bucket policyは、「評価優先度の異なる3つのルール(Effect)」を組み合わせてアクセス制限を実装します。
この「評価優先度」の部分にクセがあるため、扱いにくいと感じる方もいるかと思います。
ポイントは3つ!!!
より「評価優先度」の高いルール(Effect)が適用される。
適用されたルール(Effect)よりも「評価優先度」が低いルール(Effect)は、破棄(非適用)される。
前述の「評価優先度」により、「ルール(Effect)」の記載順序は無関係であること。
※上の方に書いたから優先になる訳ではない。
S3 bucket policy が解釈できる「ルール(Effect)」の種類
Clearly Deny
- 評価優先度:高
- これは「Deny」だよ、と明記する場合。
- 評価優先度「中」以下のEffectよりも優先適用される。
Clearly Allow
- 評価優先度:中
- これは「Allow」だよ、と明記する場合。
- 評価優先度「低」のEffectよりも優先適用される。
Default Deny
- 評価優先度:低
- 特に「Deny」も「Allow」も記載されていない箇所に対して、default で適用されるEffect。
3. bucket policyのサンプル
文章だけだと分かりにくいので、実際にサンプル設定を使って説明をしていきます。
なおここに載せてあるサンプル設定は、必ず検証してから自己責任でご利用ください。
サンプル01 :
「特定のIPアドレス」からのみアクセス許可したい。
解説
この場合は、「Clearly Allow」と「Default Deny」を使用します。
まずは、以下のように「Effect」に「Allow」と記載します。※「Clearly Allow」
{ "Sid": "Allow-from-specific-IP-only", ← 分かればなんでも良いです。 "Effect": "Allow", ←「Allow」を記載します。 "Principal": { "AWS": "*" },
続けて、「Condition」の項目で許可したいIPアドレスを記載すればOKです。
"Action": "s3:GetObject", ← 閲覧権限のみを付与。 "Resource": "arn:aws:s3:::<your S3 bucket name>/*", "Condition": { "IpAddress": { "aws:SourceIp": [ "xxx.xxx.xxx.xxx/yy", ← アクセス元のIPをCIDR形式で記載します。 "xxx.xxx.xxx.xxx/yy" ← 複数書くときは、","で区切って記載します。 ] } } }
ここに記載の無いIPアドレスについては、
条件不一致 =「Default Deny」として処理されます。
サンプル01 の設定まとめ
この設定は、まとめると以下のような形になります。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Allow-from-specific-IP-only", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::<your S3 bucket name>/*", "Condition": { "IpAddress": { "aws:SourceIp": [ "xxx.xxx.xxx.xxx/yy", "xxx.xxx.xxx.xxx/yy" ] } } } ] }
備考
他にも、以下のように「Clearly Deny」でこのIP以外は拒否という形でもOKです。
ただしこの場合は、「Clearly Allow」と組合せることが出来ない(Clearly Denyが優先され、Clearly Allowは破棄される)ので、拡張性に乏しくなります。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Allow-from-specific-IP-only", "Effect": "Deny", "Principal": { "AWS": "*" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::<your S3 bucket name>/*", "Condition": { "NotIpAddress": { ←「指定IP以外を拒否する」 "aws:SourceIp": [ "xxx.xxx.xxx.xxx/yy", "xxx.xxx.xxx.xxx/yy" ] } } } ] }
サンプル02 :
「特定のIPアドレス」と「CloudFront」からのアクセスのみ許可したい。
解説
この場合も、「Clearly Allow」と「Default Deny」を使用します。
ポイントは、「Clearly Allow」を2つ使うことです。
「Clearly Allow」は複数束ねると「OR条件」として使えます。
先程と同様に、まずは「Clearly Allow」で許可したいIPアドレスを記載します。
次に、同じく「Clearly Allow」で、CloudFrontのOrigin Access Identityを記載します。
{ "Sid": "Allow-from-specific-IP-only", "Effect": "Allow", "Principal": { "AWS": "*" }, ・・・略) { "Sid": "Allow-from-CloudFront", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <your CloudFront Origin-Access-Identity>" ←これは別途CloudFrontを操作してIDの取得をしてください。 }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::<your S3 bucket name>/*" }
こうすることで、Allow の OR条件として判定されます。
そして最後に、上記にマッチしないアクセス全てを「Default Deny」で拒否します。
注意点としては、「Clearly Deny」でIP制限を書かないことです。
理由は「Clearly Deny」の優先度が最も高いため、指定したIP以外はアクセスできなくなるからです。
サンプル02 の設定まとめ
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Allow-from-specific-IP-only", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::<your S3 bucket name>/*", "Condition": { "IpAddress": { "aws:SourceIp": [ "xxx.xxx.xxx.xxx/yy", "xxx.xxx.xxx.xxx/yy" ] } } }, { "Sid": "Allow-from-CloudFront", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <your CloudFront Origin-Access-Identity>" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::<your S3 bucket name>/*" } ] }
サンプル03 :
「特定のIPアドレス」と「CloundFront」および「AWS CLI」からのみアクセス許可したい。
解説
サンプル02の条件に加えて、「AWS CLI ※」での操作を可能とする設定です。
※ ”aws s3 sync” コマンド等のことです。
S3の閲覧やオブジェクトのダウンロードは、通常はブラウザ経由が多いと思いますが、
AWS CLIを利用してオブジェクトコピーをしたりする開発者は多いと思います。
そういう場合に、AWS CLIでの操作だけはS3の全権限を付与した設定のサンプルです。
{ "Sid": "Allow-full-control-for-API", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<your account No>:<user name>" }, "Action": "s3:*", ←S3の全操作権限を付与 "Resource": [ "arn:aws:s3:::<your S3 bucket name>/*", "arn:aws:s3:::<your S3 bucket name>" ] }
これも基本はさっきと同じで、
「Clearly Allow」で許可したい条件を記載し、それ以外はDefaultDenyで拒否しています。
サンプル03 の設定まとめ
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Allow-from-CloudFront", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <your CloudFront Origin-Access-Identity>" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::<your S3 bucket name>/*" }, { "Sid": "Allow-from-specific-IP-only", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::<your S3 bucket name>/*", "Condition": { "IpAddress": { "aws:SourceIp": [ "xxx.xxx.xxx.xxx/yy", "xxx.xxx.xxx.xxx/yy" ] } } }, { "Sid": "Allow-full-control-for-API", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<your account No>:<user name>" }, "Action": "s3:*", "Resource": [ "arn:aws:s3:::<your S3 bucket name>/*", "arn:aws:s3:::<your S3 bucket name>" ] } ] }
いかがでしたか。
S3 bucket policyの設定がうまく行かなくて悩んでいる方の助力になれば幸いです。
今後もAWS関連の記事を書いていこうと思っているので、興味を持って頂けたらぜひまた読んでみて下さい!
それでは~ (・о・) /