オリジナルが一年ほど更新されてないしワイも fork して自分用の作っちゃうかなあ、という気持ちになりつつある。
全体公開されているバケットでアクセス制御したい
S3 バケットが全体公開されている状態で、 bucket-antivirus-function
でスキャンした結果付与される av-status
タグによって、バケット内オブジェクトへのアクセスを制御したい。 具体的なバケットの状態は以下 (複数なのは、開発・統合・検証・本番の 4 環境存在するため)。
README のバケットポリシー
リポジトリの example では Deny
のものしかないため、今回の要件である S3 オブジェクトを直接ブラウザから参照させるが達成できない。
全体公開する
そーいう使い方はするなという AWS からの圧も感じるが、Cloudfront で配信するようなアクセスは絶対に発生しない作りなので、あえて静的配信でいく。 明示的に許可するには、以下のようなルールが必要になる。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::バケット名/*" } ] }
しかしこれでは av-status
タグの内容に関わらず公開されてしまう。 ので、ここに Condition
を追加してこうしてみた。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::バケット名/*", "Condition": { "StringEquals": { "s3:ExistingObjectTag/av-status": "CLEAN" } } ] }
これで av-status
タグが CLEAN
のオブジェクトだけパブリックアクセスできるやろ! Condition
を満たさないオブジェクトは暗黙的な拒否で AccessDenied になるはずや!
拒否される時と拒否されない時がある
なんでや! (なんでや!)
マネジメントコンソールにログインして作業していたのですが、ログインしているアカウントでポリシーを設定したバケットに対して、マネジメントコンソール経由でアップロードしたファイルは制御できていたのですが、既存のファイル (scan_bucket.py
で手動酒キャン済み) が Condition
の制御から漏れてしまうようでした。
えー、もしかして IAM とかクロスアカウント制御的なヤツなの……? と思ったのですが「単体のワークスペースだしなー」と悩んだ末、これ暗黙的な拒否に期待するのがダメなのでは? という結論に至り。
最終的なバケットポリシー
ポリシー内の明示的な拒否は、すべての許可に優先します。
とのことなので、最初に拒否する条件を書いておいて、マッチしなかったら全体公開する条件が参照されるようにすればいいんじゃねえの?
ということで、明示的に拒否と許可を記載することにしました。 一応 example を尊重して Deny の Action
にタグ変更追加してあるけど、これも不要かもしれないっすね。
{ "Version": "2008-10-17", "Statement": [ { "Effect": "Deny", "Principal": "*", "Action": ["s3:GetObject", "s3:PutObjectTagging"], "Resource": "arn:aws:s3:::バケット名/*", "Condition": { "StringEquals": { "s3:ExistingObjectTag/av-status": "INFECTED" } } }, { "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::バケット名/*", "Condition": { "StringEquals": { "s3:ExistingObjectTag/av-status": "CLEAN" } } } ] }
これで、
- アクセス対象オブジェクトの
av-status
タグがINFECTED
ならアクセス拒否 - の条件に当てはまらなければ、オブジェクトの
av-status
タグがCLEAN
ならアクセス許可
- の条件に当てはまらなければ、オブジェクトの
が達成できました。 やったぁ。 けど Allow 時の "s3:ExistingObjectTag/av-status": "CLEAN"
で制御されないパターンあるって自分で書いてるし、 Condition
は削除しちゃってもいいかもしれないっすね。
ちなみに AWS のポリシーは書いた順番で評価するのではなく、 Deny -> Allow の順で評価されるのと、 Statement
配列は OR 条件らしいです。 クラスメソッドくんいつもありがとー!