S3の特定パスのみに対して全ての操作が可能なIAMポリシー

2017.03.09

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

西澤です。今回は、S3バケットの特定パスに対するアクセス権限制御について、お客様から質問いただき、正確に理解できていなかったところを調査したので、整理してみます。

このポリシーで実行可能なアクションについて正確に回答できますか?

いきなりですが、クイズです。下記のようなポリシーにより権限付与されたユーザのアクセス範囲を正確に説明することはできますか?

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "s3:*",
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::access-control-on-specific-path/dir_a/*"
        }
    ]
}

今回調べてみる前まで、試さないとよくわからない、というのが正直なところでした。ポリシー設定用のjsonを読んだことがある方なら想像がつくとは思いますが、S3上の特定パスのみへのアクセス権限を制御したい、というのが今回やりたいことです。

オブジェクトの一覧取得ができない

このアクセス権限を有したIAMユーザを使って、特定パス(dir_a/*)へのGet/Put/Deleteができること、特定パス(dir_a/*)以外へのGet/Put/Deleteができないことは、すぐに確認できました。

$ aws s3 cp ./test.txt s3://$BUCKET/dir_a/
upload: ./test.txt to s3://access-control-on-specific-path/dir_a/test.txt

$ aws s3 cp ./test.txt s3://$BUCKET/dir_b/
upload failed: ./test.txt to s3://access-control-on-specific-path/dir_b/test.txt An error occurred (AccessDenied) when calling the PutObject operation: Access Denied

ただし、一覧取得ができませんでした。これは一体どういうことでしょうか?

$ aws s3 ls s3://$BUCKET/dir_a/
An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied

$ aws s3 ls s3://$BUCKET/dir_b/
An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied

ListObjectsなんていうS3のアクションは存在しない

このエラーメッセージを見ると、ListObjectsというアクセス権限を付与すれば良さそうなのですが、公式ドキュメントを見ても、そもそもそのようなS3のアクションは存在していません。

S3のアクションの種類

S3のアクションには、下記の種類があります。

S3のアクションの種類 制御対象 説明
オブジェクトオペレーション オブジェクト オブジェクトの操作
バケットオペレーション バケット バケットそのものの操作
バケットサブリソースオペレーション バケット バケットのサブリソース(プロパティ等)の操作

このうち、後ろの2種類は、バケットに対するアクションです。つまり、前述のポリシーでは、s3:*という全アクション指定をしているものの、arn:aws:s3:::access-control-on-specific-path/dir_a/*という形式でバケットではなくオブジェクトでリソース指定をしている為に、実質的には後ろの2種類のバケット操作系の権限は付与されていないということになります。

ListObjectsするにはs3:ListBucketが必要

今回エラーとなって実行できていないListObjectsをする為には、s3:ListBucket権限が必要なことがわかりました。s3:ListBucketはバケットオペレーションとなる為、バケットをリソースとして権限を付与する必要があります。

  • オブジェクトオペレーション
    • s3:GetObject
    • s3:GetObjectVersion
    • s3:PutObject
    • s3:GetObjectAcl
    • s3:GetObjectVersionAcl
    • s3:PutObjectAcl
    • s3:PutObjectVersionAcl
    • s3:DeleteObject
    • s3:DeleteObjectVersion
    • s3:ListMultipartUploadParts
    • s3:AbortMultipartUpload
    • s3:GetObjectTorrent
    • s3:GetObjectVersionTorrent
    • s3:RestoreObject
    • s3:PutObjectTagging
    • s3:PutObjectVersionTagging
    • s3:GetObjectTagging
    • s3:GetObjectVersionTagging
    • s3:DeleteObjectTagging
    • s3:DeleteObjectVersionTagging
  • バケットオペレーション
    • s3:CreateBucket
    • s3:DeleteBucket
    • s3:ListBucket
    • s3:ListBucketVersions
    • s3:ListAllMyBuckets
    • s3:ListBucketMultipartUploads
  • バケットサブリソースオペレーション
    • s3:GetAccelerateConfiguration
    • s3:PutAccelerateConfiguration
    • s3:GetBucketAcl
    • s3:PutBucketAcl
    • s3:GetBucketCORS
    • s3:PutBucketCORS
    • s3:GetBucketVersioning
    • s3:PutBucketVersioning
    • s3:GetBucketRequestPayment
    • s3:PutBucketRequestPayment
    • s3:GetBucketLocation
    • s3:GetBucketPolicy
    • s3:DeleteBucketPolicy
    • s3:PutBucketPolicy
    • s3:GetBucketNotification
    • s3:PutBucketNotification
    • s3:GetBucketLogging
    • s3:PutBucketLogging
    • s3:GetBucketTagging
    • s3:PutBucketTagging
    • s3:GetBucketWebsite
    • s3:PutBucketWebsite
    • s3:DeleteBucketWebsite
    • s3:GetLifecycleConfiguration
    • s3:PutLifecycleConfiguration
    • s3:PutReplicationConfiguration
    • s3:GetReplicationConfiguration
    • s3:DeleteReplicationConfiguration
  • ポリシーでのアクセス許可の指定 - Amazon Simple Storage Service

特定パスのみListObjectsも可能なポリシー

ということで、ListObjectsも含め、特定パス配下に全ての操作を許す為のポリシーは下記となりました。ポイントは、バケットオペレーションであるs3:List*を、バケットのみ(パス情報は付けない)をリソースとして設定し、Conditionからs3:prefixを利用して特定パスのみに絞るところです。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "s3:*",
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::access-control-on-specific-path/dir_a/*"
        },
        {
            "Action": "s3:List*",
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::access-control-on-specific-path",
            "Condition": {
                "StringLike": {
                    "s3:prefix": "dir_a/*"
                }
            }
        }
    ]
}

s3:List*のところは、s3:ListBucketでも良さそうですが、バージョン管理が有効となっているバケットでは、s3:ListBucketVersionsが必要となる場合もある為、まとめて権限付与する設定としました。

$ aws s3 ls s3://$BUCKET/dir_a/
PRE data/
PRE data2/
PRE data3/
2017-02-24 20:37:45 15 index.html
2017-02-27 08:59:32 15 index2.html
2017-02-27 09:43:43 231 index3.html
2017-03-09 15:09:22 5 test.txt

$ aws s3 ls s3://$BUCKET/dir_b/
An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied

これで上手く制御できそうですね。

まとめ

今回の記事について理解が難しかった方は、個人的に殿堂入りにすべきだと思っている都元さんの記事をぜひお読みいただき、そもそもS3のパスって何なのかっていうところを、まずは理解しておくと良いと思います。

というか、ヘビーにAWSを利用されているユーザに取っては慣れっこになってしまっているのかもしれませんが、ちょっとS3バケットへのアクセス権限制御は難しすぎるという印象が拭えません。将来的にはもっと直感的な権限設定ができるようになると嬉しいですよね。

どこかの誰かのお役に立てば嬉しいです。