特定IAMユーザー&IAMロール以外のS3バケットへのアクセスを拒否するバケットポリシー

記事タイトルとURLをコピーする

こんにちは!
エンタープライズクラウド部技術2課の日高です。

本日は、特定IAMユーザー&IAMロール以外のS3バケットへのアクセスを拒否するバケットポリシーの記載方法についてまとめます。

はじめに(困っていたこと)

お客様から次のようなご要望をいただきました。

  • 特定のIAMユーザーとIAMロールのみがS3バケットにアクセスできるように制限をかけたい。
  • 承認されたユーザー以外はS3バケットの情報を一切閲覧できないようにしたい。

AWSの「グローバル条件コンテキストキー」を使用した"Condition"句によりアクセス制限が可能だと予想していましたが、具体的にどのように"Condition"句を設定すれば良いのかが分からず、この点について調査を進めました。

解決方法

S3バケットポリシー

結論から申し上げると、下記のS3バケットポリシーを利用することで、アクセスを特定の条件下で制限することが可能です。

IAMユーザーとIAMロールの両方にアクセス権を付与する必要がある場合、「aws:username」ではIAMユーザーのみしか制限できないため「aws:userId」を使用しました。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::<バケット名>",
                "arn:aws:s3:::<バケット名>/*"
            ],
            "Condition": {
                "StringNotLike": {
                    "aws:userId": [
                        "<UserId>",
                        "<RoleId>:*"
                    ]
                }
            }
        }
    ]
}

※<バケット名>を制限したいバケットの名前に、をアクセスを許可したいIAMユーザーのユーザーIDとIAMロールのロールIDにそれぞれ置き換えてください。ユーザーIDとロールIDの調べ方については後ほど説明します。

S3バケットポリシーの解説

  • 「バージョン」は、ポリシー言語がリリースされた日付、「2012-10-17」を指します。
  • ポリシーの「ステートメント」は、そのルールを具体的に定める部分です。

ステートメントには次のような指示が含まれます:

  • 「効果」は、「Deny」と設定されており、指定した操作を禁止することを意味します。
  • 「プリンシパル」は、「*」と設定されており、すべてのユーザーが対象です。
  • 「アクション」は、「s3:*」と設定されており、S3のすべての操作が対象です。
  • 「リソース」は、「arn:aws:s3:::<バケット名>」と「arn:aws:s3:::<バケット名>/*」が指定されており、特定のバケットとその中のすべてのオブジェクトが対象です。
  • 「条件」は、「StringNotLike」というキーを使用し、特定のユーザーID(「aws:userId」)が指定した値に合致しない場合に限り、この禁止ルールが適用されます。

つまり、このポリシーは全ユーザーに対し、特定のS3バケット及びその内容物への全操作を禁止しますが、一部のIAMユーザーやIAMロール(条件で指定されたUserIdやRoleIdを持つ者)はこの規則から除外されるバケットポリシーになっています。

これにより、指定されたユーザーやロールのみにアクセスを許可し、他のユーザーのアクセスを防ぐことで、バケットのセキュリティを強化しています。

UserIdの調べ方

下記の、AWS CLIを実行することで調べることができます。(<ユーザー名>は対象のIAMユーザー名に置き換えてください。)

aws iam list-users --query 'Users[?UserName==`<ユーザー名>`].UserId' --output text

aws iam list-users(何もオプションをつけずに)を実行すると、下記のように全てのユーザーの情報が表示されてしまいます。 ※UserNameやUserIdはでたらめな値にしています。

{
"Users": [
        {
            "Path": "/",
            "UserName": "aaaaaaaaaaaa",
            "UserId": "AIDAUMRDAFDAHXEQ4DAF3G",
            "Arn": "arn:aws:iam::××××××××××:user/aaaaaaaaaaaa",
            "CreateDate": "2022-07-05T02:07:33+00:00",
            "PasswordLastUsed": "2023-09-07T05:32:52+00:00"
        },
        {
            "Path": "/",
            "UserName": "bbbbbbbbbbbb",
            "UserId": "FADJF3DALDKFA2DAFJFA",
            "Arn": "arn:aws:iam::××××××××××:user/bbbbbbbbbbbb",
            "CreateDate": "2023-08-08T06:45:37+00:00",
            "PasswordLastUsed": "2023-08-08T06:46:35+00:00"
        }
    ]
}

そのため--query 'Users[?UserName==<ユーザー名>].UserId' で、指定したIAMユーザーのUserIdだけ表示されるようにフィルタリングしています。

  • コマンドの実行結果
 % aws iam list-users --query 'Users[?UserName==`aaaaaaaaaaaa`].UserId' --output text

AIDAUMRDAFDAHXEQ4DAF3G

RoleIdの調べ方

下記の、AWS CLIを実行することで調べることができます。(<ロール名>は対象のIAMロール名に置き換えてください。)

aws iam get-role --role-name <ロール名> --query 'Role.RoleId' --output text

aws iam get-role --role-name Test-Role(フィルタリングしないで)を実行すると、下記のように色々な情報が表示されてしまいます。

{
    "Role": {
        "Description": "Test Role",
        "AssumeRolePolicyDocument":"<URL-encoded-JSON>",
        "MaxSessionDuration": 3600,
        "RoleId": "AROA1234567890EXAMPLE",
        "CreateDate": "2019-11-13T16:45:56Z",
        "RoleName": "Test-Role",
        "Path": "/",
        "RoleLastUsed": {
            "Region": "us-east-1",
            "LastUsedDate": "2019-11-13T17:14:00Z"
        },
        "Arn": "arn:aws:iam::123456789012:role/Test-Role"
    }
}

そのため--query 'Role.RoleId' で、指定したIAMロールーのRoleIdだけ表示されるようにフィルタリングしています。

  • コマンドの実行結果
 % aws iam get-role --role-name Test-Role --query 'Role.RoleId' --output text

AROA1234567890EXAMPLE

まとめ

意外と調べてみると時間がかかったので、ブログにまとめてみました。
本記事だ誰かの助けになれば幸いです。

日高 僚太(執筆記事の一覧)

EC部ソリューションアーキテクト2課 / AWS認定資格 12冠

2022年IT未経験で新卒入社しました。
最近はダーツとサウナが気になっています!
記事に関するお問い合わせや修正依頼⇒ hidaka@serverworks.co.jp