IAM ロールのタグの値と S3 バケット名の部分一致で操作できる S3 バケットを制限してみた

IAM ロールのタグの値と S3 バケット名の部分一致で操作できる S3 バケットを制限してみた

Clock Icon2024.07.07

IAM ユーザーを一つのアカウントに集約して、他の AWS アカウントにスイッチロールする運用をしている環境において(Jump アカウント構成において)、IAM ロールの特定のタグの値と S3 バケット名の部分一致で操作できる S3 バケットを制限するポリシーを試してみました。

イメージ図は下記です。スイッチロール先の IAM ロールに Project タグを付け、その値とバケット名の部分一致で操作できるバケットを制限します。IAM ポリシーは共通であるため、複数のロールに使いまわしができます。複数のシステムが同じアカウントに混在している環境では管理が容易になることが期待できます。

amazon-s3-abac-1

Project タグの値が aaa である IAM ロールにフォーカスした場合のイメージ図です。バケット名に aaa が含まれないバケットにはアクセスできません。

amazon-s3-abac-2

スイッチロール先アカウントの IAM ロールにアタッチする IAM ポリシー例は次のようになります。IAM ロールには Project をキーとするタグを付ける例です。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:List*",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::prd-${aws:PrincipalTag/Project}-*",
                "arn:aws:s3:::prd-${aws:PrincipalTag/Project}-*/*"
            ]
        }
    ]
}

以降では、ユーザー管理アカウント(Jump アカウント)とスイッチロール先アカウントの設定をして動作を試してみます。

ユーザー管理アカウント(Jump アカウント)の設定

次の名前で IAM ユーザーを作成します。

  • IAM ユーザー名 test-abac-user

作成した IAM ユーザー、もしくは IAM ユーザーが所属するグループに次のポリシーをアタッチします。

{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "*"
    }
}

今回は ABAC の動作確認がメインなので省略してしますが、ユーザー管理アカウントの IAM ユーザーには MFA の設定許可やパスワードの変更許可もアタッチすることが多いです。

スイッチロール先アカウントの設定

テスト用に次のバケット名で S3 バケットを 2 つ作成しています。これらの S3 バケットにはタグを付与していません。

  • S3 バケット名 prd-aaa-20240703
  • S3 バケット名 prd-bbb-20240703

IAM ロールは下表の設定で作成します。

項目 設定値
IAM ロール名 test-abac-role
許可 - カスタマー管理ポリシー test-abac-policy
信頼ポリシー 下記参照
タグ (Key : Value) Project : aaa

カスタマー管理ポリシー test-abac-policy のポリシーは次の例で設定します。1 つ目のブロックは S3 のリスト権限を与えています。2 つ目のブロックでは、バケット名が prd- から始まり、プリンシパル(今回の場合は IAM ロール)の Project タグの値続いているバケット名を条件として、S3 の全てのアクションの権限を与えています。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:List*",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::prd-${aws:PrincipalTag/Project}-*",
                "arn:aws:s3:::prd-${aws:PrincipalTag/Project}-*/*"
            ]
        }
    ]
}

信頼ポリシーでは、ユーザー管理アカウントで作成した IAM ユーザーのみからスイッチロールできるように指定します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111122223333:user/test-abac-user"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

信頼ポリシーでは、Condition を追加して MFA が利用されている場合や送信元 IP アドレスが一致した場合のみ許可することもできます。

以上で設定は終わりです。

動作確認

ユーザー管理アカウントで作成した IAM ユーザー test-abac-user でマネジメントコンソールにサインインします。

スイッチロール先のアカウント ID と IAM ロールを指定してスイッチロールします。

amazon-s3-abac-3

S3 のリスト権限を与えているため、スイッチロール先では S3 バケットの一覧を確認できます。

amazon-s3-abac-4

始めに、IAM ロールに付与したタグの値 aaa が含まれる prd-aaa-20240703 から確認します。

オブジェクトのアップロードはできました。

amazon-s3-abac-5

画像はないですが、ダウンロードもできました。この時点で AWS CloudShell の権限も付与して AWS CLI で試せばよかったと思いましたが、このまま進めます。

オブジェクトの削除もできました。

amazon-s3-abac-6

次に、IAM ロールに付与したタグの値 aaa が含まれない prd-bbb-20240703 を確認します。

アップロードは拒否されました。

amazon-s3-abac-7

あらかじめアップロードしておいた demo.txt のダウンロードも拒否されました。

amazon-s3-abac-8

demo.txt の削除も拒否されました。

amazon-s3-abac-9

想定通り、IAM ロールに付与した Project タグの値とバケット名が部分一致する S3 バケットだけ操作できました。

以上で終わりです。

さいごに

IAM ロールの特定のタグの値と S3 バケット名の部分一致で操作できる S3 バケットを制限するポリシーを試してみました。

S3 バケット以外にも任意のリソース名を付与できるサービスなら同様の制御ができるかもしれません。EC2 インスタンスのようにリソース名(インスタンス ID)が AWS 側で付与されるサービスでは、本ブログのポリシーのようなアプローチはできませんが、EC2 の場合はインスタンスにタグを付けて、IAM ロールのタグと一致するインスタンスのみ操作できるようにする方法はあります。

https://dev.classmethod.jp/articles/abac-in-jump-account/

以上、このブログがどなたかのご参考になれば幸いです。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.