更新履歴
- 2018/06/19
 PrincipalではなくConditionで指定する方法を追記。
 そちらの方法であればセッション名を特定できなくても実現できます。
やりたいこと
S3バケットポリシーで、特定のIAMロールだけがバケットにアクセス出来るようにする。
言い換えれば、特定IAMロール以外のアクセスはDenyする。
「IAMポリシーで制限すれば?」という考え方もあると思いますが、IAM(ユーザーやグループやロール)には S3FullAccess S3ReadOnly などの大雑把な権限を付与しがちですし、制限したいS3バケットが新たに作られるたびに全てのポリシーを見直さないといけなくなります。バケット側で制御するほうが確実です。
結論から
2通り方法がありますが、Principal(NotPrincipal) のほうは制限事項があります。
特段の理由がない限りは、Condition を使用する方法でよいのではないでしょうか。
S3バケットポリシー設定前に注意事項
今回やりたいことに限った話ではなく、一般的な話として。
バケットポリシーは、バケットポリシーを設定する権限も制限します。
Deny を設定するときに書き方を誤ってしまうと「自分で修正できない」「root以外誰も触れない」という状況に陥ることもあります。
慎重に、よく確認して実施しましょう。
設定方法
IAMロールを指定する方法として、 Principal(NotPrincipal) を使用する方法と Condition を使用する方法の2通りあります。
NotPrincipal でIAMロールを指定する方法
制限事項
- セッションARNが必要であるため、セッション名を特定できない場合にはこの方法は利用できません。
- 同じ理由で、セッション名の追加更新が多いケースでもそのたびにバケットポリシーの変更が必要になるため、不便です。
S3バケットポリシー例
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Deny",
			"NotPrincipal": {
				"AWS": [
					"arn:aws:iam::<アカウントID>:role/<ロール名>",
					"arn:aws:sts::<アカウントID>:assumed-role/<ロール名>/<セッション名>"
				]
			},
			"Action": "s3:Put*",
			"Resource": [
				"arn:aws:s3:::<バケット名>",
				"arn:aws:s3:::<バケット名>/*"
			]
		}
	]
}
- 
<xxx>で括ったアカウントIDなどは、それぞれの環境に合わせて設定してください。
- この例では禁止(Deny)するアクションは "put*"に限定しています。
 そのままコピペ&加工して設定にミスがあったときに誰も修正できなくなると困るため。
 対象者によるバケットポリシー更新(上書き保存)はできませんが、削除ならできます。
説明
- 特定IAMロール以外("NotPrincipal")のアクセスはDeny("Effect": "Deny")します。
- 
NotPrincipalには、以下2つを両方を書く必要があります。
 どちらか一方だけではNGです。- 使用するロールARN ... "arn:aws:iam::<アカウントID>:role/<ロール名>"
- 使用しているセッションARN ... "arn:aws:sts::<アカウントID>:assumed-role/<ロール名>/<セッション名>"
 
- 使用するロールARN ... 
- バケットポリシーの PrincipalNotPrincipalにワイルドカード*は使用できません。
 設定しようとするとInvalid principal in policyエラーになります。
 なのでセッション名まで指定可能なIAMロールの使い方でないと、今回やりたい制御はできません。
- ちなみに マネジメントコンソールでIAMユーザーがSwitchRoleした場合のセッションARNは下記の通り。
 "arn:aws:sts::<アカウントID>:assumed-role/<ロール名>/<ユーザー名>"
 元のユーザー名がセッション名になります。
Condition でIAMロールを指定する方法
S3バケットポリシー例
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:Put*",
            "Resource": [
                "arn:aws:s3:::<バケット名>",
                "arn:aws:s3:::<バケット名>/*"
            ],
            "Condition": {
                "StringNotLike": {
                    "aws:userid": "<IAMロールID>:*"
                }
            }
        }
    ]
}
- 
<xxx>で括ったバケット名などの情報は、それぞれの環境に合わせて設定してください。
- この例では禁止(Deny)するアクションは "put*"に限定しています。
 そのままコピペ&加工して設定にミスがあったときに誰も修正できなくなると困るため。
 対象者によるバケットポリシー更新(上書き保存)はできませんが、削除ならできます。
説明
- 
PrincipalではなくConditionでIAMロールを指定します。
 StringNotLikeで比較することで「それ以外」を対象として、アクセスを Deny("Effect": "Deny")します。
- 
Condition.StringNotLikeではワイルドカード*を使用できます。
 セッション名を限定する必要がありません。
- IAMロールID ≠ IAMロール名 です。
 IAMロールIDはマネジメントコンソールから確認することができません。awscli などのget-roleで確認してください。
 例) $ aws iam get-role --role-name <ロール名>
