S3のアクセスコントロールが多すぎて訳が解らないので整理してみる


この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Amazon S3のアクセスコントロールがわけわからない

いくつもあってわけがわかりませんね。
それぞれ何が出来て何ができないのか、どうゆう時にどれを使うのか、組み合わせて使うとどうなるのか、いい機会なので整理してみたいと思います。

ACL

これはおそらくいちばん古くからある機能です。
permissions
ManagementConsoleではPermissionsというところで設定ができます。
ACLの設定はバケット、もしくはオブジェクト単位で設定する事が出来るのが特徴になっています。
APIを見てみても、putBucketACLとputObjectACLとあることから、Bucket単位でのACLとObject単位でのACLがあることが分かります。 別のアカウントにまたがって設定することも出来ます。

BucketPolicy

S3のBucketに対して、PolicyDocumentを使ってアクセスコントロールを設定出来ます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
{
  "Id": "bucketpolicy-${oacl}-${acl}-${EFFECT}",
  "Statement": [
    {
      "Sid": "Stmt${UNIQ}-1",
      "Action": [
        "s3:GetObject"
      ],
      "Effect": "${EFFECT}",
      "Resource": "arn:aws:s3:::${BUCKET}/*",
      "Principal": {
        "AWS": [
          "${TARGET_PRINCIPAL}"
        ]
      }
    },
    {
      "Sid": "Stmt${UNIQ}-2",
      "Action": [
        "s3:ListBucket"
      ],
      "Effect": "${EFFECT}",
      "Resource": "arn:aws:s3:::${BUCKET}",
      "Principal": {
        "AWS": [
          "${TARGET_PRINCIPAL}"
        ]
      }
    }
  ]
}

こんな感じで、Action, Effect, Principal, Resourceと、これらを組み合わせて柔軟なアクセスコントロールが実現出来ます。
この一個のファイルだけを公開したいとかそういった用途に使うのには向いていないように思います。ObjectACLを使いましょう。
個人的な感覚ですが、bucketACLはBucketPolicyに置き換えたほうが良いなと思っています。

ACLとBucketPolicyどちらが強いのか

気になってしまったので、ACLとBucketPolicyどちらが強いのかを検証したいと思います。
検証の方法は簡単です。 ACLは許可するか、何もしないかの2値です。BucketPolicyは許可する、拒絶する、何もしないの3値です。
ACLはBucketとObjectがありますので、この3つの設定を全通りの組み合わせでやってみます。

BucketACLObjcetACLBucketPolicy結果
許可許可拒否失敗
許可未設定拒否失敗
許可許可許可成功
許可未設定許可成功
許可許可未設定成功
許可未設定未設定失敗
未設定許可拒否失敗
未設定未設定拒否失敗
未設定許可許可成功
未設定未設定許可成功
未設定許可未設定成功
未設定未設定未設定失敗

この結果からもわかるように、[Bucket|Object]ACLよりもBucketPolicyの方が強くなります。 BucketPolicyで設定されていない場合は、ObjcetACL , BucketACLによって制御されています。 
これについては、公式にドキュメントでここここにも書いて有ります。
さらにBucketPolicyではIPアドレスで制御やRefererで制御も出来ます。
直リン禁止とか出来たりします。

IAM(IAMRole)

IAMではPolicyDocumentを使用してアクセスをコントロールします。
IAMとBucketPolicyの違いはユーザ(クライアント)側に紐付いて権限が与えられるということです。
また、現在はPolicyに変数を利用する事が出来るため、ユーザ名に応じたアクセスのコントロールが可能になっています。
例えば、こんな感じです。
policyDocumentに

1
2
3
4
5
6
7
8
9
10
11
12
13
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Effect": "Allow",
            "Resource": ["arn:aws:s3:::BUCKET/${aws:username}/*"]
        }
    ]
}

と記述されていたら、
IAMuser名: akeri の時には s3://BUCKET/akeri/ で始まるオブジェクトにアクセス出来る事になります。
BucketPolicy同様にconditionによって、条件を指定する事も出来ます。
IPアドレスで制御したり、 @see AWS Identity and Access Management

で、IAMとBucketPolicyはどっちが強いの?

先ほどACLとBucketPolicyを試してみたら、BucketPolicyが強かったのですが、今度はIAMとBucketPolicyどっちが強いのかを試してみたいと思います。
さっきと同様に総当りで調べてみます。 今回ACLは何も設定していない状態です。

BucketPolicyIAM結果
拒否拒否失敗
拒否許可失敗
許可拒否失敗
許可許可成功
未設定拒否失敗
未設定許可成功

結果はこんな感じです。
とりあえず、IAMで許可されていないと確実に失敗します。
当たり前といえば当たり前な気がします。
しかし、IAMで許可されていたとしてもBucketPolicyで拒否されているとアクセス出来ませんでした。 とりあえず、ここから わかることは拒否は絶対ということです。
IAMで拒否されていてもBucketPolicyで拒否されていても、失敗します。
成功するのは、IAMで許可されているかつBucketPolicyで拒否されていない(Allowもしくは未設定)の場合でした。
さっきのACLとBucketPolicyではわかりませんでしたが、BucketPolicyが優先されているわけではなくて、Denyが優先されているようです。

まとめ

上記の結果から、S3のACLに関するルールがなんとなく見えてきました。
ACLの基本として、どこかしらでDenyとなっていたら、ほかでAllowだろうとDenyになってしまいます。
Denyに対して、Allowで上書きは出来ません。
それとは逆にBucketPolicyやACLでAllowを設定していても、IAMでDenyであった場合は当然アクセス出来ません。
ここから考えるベストプラクティスというのはパットは出てきませんが、ACLはあるオブジェクト一つだけを公開したい時や、publicにする時に使う以外では使わないのかもしれません。
まとめるとタイトルで言ったものの、あまりまとめられてる感じがしないですね。ごめんなさい。

バケットとして不変的なアクセスコントロールはBucketPolicyで定義し、IAMはユーザ毎に変更になるようなものを設定するのが良いのではと思います。この時にBucketPolicyでDenyを付けてしまうと、IAMでいくら設定してもDenyなので、今の段階で私の考えられるベターな方法は、まずは必要なところだけBucketPolicyで公開します。その公開している範囲ないで更に限定的に拒否したいところにはDenyで上書いてあげる方法が良さそうです。
さらにIAMでは変数が使えるので、グループのPolicyで一括設定もできるので、複数のユーザがいて、あるルールに基づいてアクセスをコントロールしたい場合にはIAMを使いたいですね。

用途をまとめるとこんな感じかなと思います。◯はいいじゃんで、☓は出来ない。△はやってやれないことは無いけど、めんどくさすぎてやりたくない位なゆるい判断基準で付けてます。

ユースケース[Bucket|Object]ACLBucketPolicyIAM
一個のObjectを公開したい
バケット全体を公開したい
特定のユーザにだけ公開したい
IPアドレス制限をかけたい
Bucketの中のPrefixを指定して公開したい
prefixがユーザ毎に可変








+ Recent posts