[アップデート] AWS KMS でタグもしくはエイリアスを利用した ABAC(Attribute-Based Access Control) がサポートされました!

AWS KMS で IAM 条件キーが追加されました。タグベースとエイリアスベース、あなたはどちらを選ぶ?

コンバンハ、千葉(幸)です。

AWS KMS が、タグもしくはエイリアスを使用した ABAC (Attribute-Based Access Control)に対応しました!

より細やかに権限制御できるようになりましたね。

ABAC(Attribute-Based Access Control)とは

ABAC とは、属性に基づいてアクセス許可を定義する認証戦略です。属性は、多くの AWS リソースにおいてはタグが該当します。

以下のイメージをご覧ください。

tutorial-abac-concept
AWS の ABAC とは - AWS Identity and Access Managementより)

左側の IAM ロール、および右側の AWS リソース( S3 オブジェクト、 EC2 インスタンス)にはそれぞれの属性に応じてタグが付与されています。環境や部門、プロジェクトなど切り口は様々ありますが、タグに応じた分類が行われています。

ここで、各 IAM ロールには「自身と同じタグが割り振られている AWS リソースに対してはアクション可能」という共通したポリシーが適用されています。

リソースが増えてもロールが増えても、タグ付けがきちんとされている環境であれば、共通したポリシーで統一的に管理を行えます。

こういった制御を行うためには、「リソースにこのタグ(属性)がついているとき〇〇可能」という IAM 条件キーが、実行したい アクションに対応している必要があります。

一方で、従来からの考え方である RBAC(Role-based access control)においては、役割ごとにポリシーを定義する必要があります。

tutorial-abac-rbac-concept
(画像引用元同上)

ここでは、「この AWS リソースに対してアクション可能」というものを個別に定義していくことになります。リソースが増えればそれを追加で許可する必要がありますし、ロールが増えれば新たにポリシーを作成する必要があります。

AWS KMS ではこれまで ABAC には対応していませんでしたが、今回のアップデートでタグもしくはエイリアスを使用した ABAC がサポートされました。タグ以外の属性で ABAC に対応したのは珍しいですね。

KMS のエイリアスとは

KMS のエイリアスは、カスタマー管理キー(CMK)に関連づけることで「判別しやすさ」を提供してくれるものです。

CMK を作成した際に割り振られる一意のキー ID は以下のような形式で、非常に判別しづらいです。

xxx743a8-exx6-4xxe-9xx0-xxx3b2fb1d15

このキー ID の別名としてエイリアスを設定できます。マネジメントコンソールから操作したり AWS CLI から操作したりする際に、長ったらしいキー ID ではなくこのエイリアスを指定できるようになります。

また、エイリアスは CMK とは独立したリソースです。以下のような考え方となります。

  • ひとつの CMK に複数のエイリアスを関連づけできる
  • ひとつのエイリアスを同時に複数の CMK に関連づけできない
  • CMK にエイリアスを関連づけしないこともできる

kms-cmk-alias

タグは「キーと値」の組み合わせからなりますが、エイリアスは「キーのみ」です。似ているようで、少し異なる概念ですね。

IAM ポリシーとキーポリシー

今回のアップデートについて理解する上で、「ポリシー」が二種類あることを押さえておきましょう。

IAM ユーザーやロールなどの IAM エンティティが CMK に対してアクションを実行する際、その成否は両者に設定されたポリシーによって決定されます。( VPC エンドポイント経由の実行であったりOrganizations 配下での実行であったりなど、他のポリシーによる影響を受ける場合もあります。)

ここでは IAM 側に設定されたポリシーを IAM ポリシー、 CMK 側に設定されたポリシーをキーポリシーと呼びます。

iampolicy_keypolicy

IAM ポリシーによるアクセスを可能にするためには、キーポリシー側で許可が与えられている必要があります。

例えば以下のようなポリシーを 特定のCMK のキーポリシーに設定するとします。

IAM ポリシーを有効にするキーポリシー

{
  "Sid": "Enable IAM User Permissions",
  "Effect": "Allow",
  "Principal": {"AWS": "arn:aws:iam::111122223333:root"},
  "Action": "kms:*",
  "Resource": "*"
}

上記の状態では、以下のエンティティが当該 CMK に対してアクセス可能になります。

  • アカウント111122223333の root アカウント
    • 任意のアクションを実行可能
  • アカウント111122223333の IAM のうち、IAM ポリシーで許可を与えられたもの
    • ポリシーで許可を与えられたアクションのみ実行可能

アップデートで追加された IAM 条件キー

今回のアップデートにより追加された IAM 条件キーを確認します。

条件キーによって、それを使用できるポリシーが変わります。以下パターンに分かれます。

  • IAM ポリシーのみで使用できる
  • IAM ポリシーとキーポリシーで使用できる

前述の通り、 IAM ポリシーでアクセスを可能にするためにはキーポリシー側で許可されている必要がある、ということにご注意ください。

タグによるコントロールを行うものとエイリアスによるコントロールを行うものを分けて記載します。

タグによるコントロール

ABAC条件キー 説明 使用できるポリシータイプ 条件を使用できるアクション
aws:ResourceTag CMKに付与されているタグ(キーと値)によるコントロール IAMポリシーのみ 特定のCMKリソースオペレーション(後述)
aws:RequestTag タグ操作リクエストにおけるタグ(キーと値)によるコントロール キーポリシーとIAMポリシー TagResourceUntagResource
aws:TagKeys タグ操作リクエストにおけるタグキーによるコントロール キーポリシーとIAMポリシー TagResourceUntagResource

1番目は「特定のタグが付与されている CMK に対してのみアクション可能(あるいは禁止)」というコントロールを実現するためのものです。(この条件キーを使用できるアクションは後述します。)

例えば以下のようなポリシーであれば、キーがPurpose、値がTestというタグがついた CMK に対していくつかのアクションを実行できる、ということになります。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "kms:Decrypt",
        "kms:Encrypt",
        "kms:GenerateDataKey*"
        "kms:DescribeKey",
      ],
      "Resource": "arn:aws:kms:*:111122223333:key/*",
      "Condition": {
      "StringEquals": {
        "aws:ResourceTag/Purpose": "Test"
      }
    }
  ]
}

2番目と3番目は、「特定のタグのみ タグづけ/タグ除去 が可能(あるいは禁止)」というコントロールを行うものです。

エイリアスによるコントロール

ABAC条件キー 説明 使用できるポリシータイプ 条件を使用できるアクション
kms:ResourceAliases CMKに関連付けられたエイリアスによるコントロール IAMポリシーのみ 特定のCMKリソースオペレーション(後述)
kms:RequestAlias リクエストの中のエイリアス( CMK を表すもの)によるコントロール キーポリシーとIAMポリシー 暗号化操作(※)DescribeKeyGetPublicKey

タグによるコントロールとは少し趣が異なりますね。

2番目のkms:RequestAliasは、リクエストにおけるエイリアスを評価対象とします。

例えば AWS CLI で DescribeKey の API を実行する際には、対象を以下のようにエイリアスで指定できます。(キー ID で指定することもできます。)

$ aws kms describe-key\
  --key-id alias/Test-Key

こういったケースで特定のエイリアスを持つ CMK に対するアクションを許可/禁止できる、という条件キーがkms:RequestAliasです。

また、表中における暗号化操作(※)とは、以下を指します。(ややこしいので余裕があったら見てください。)

Operation CMK key type CMK key usage
Decrypt Any ENCRYPT_DECRYPT
Encrypt Any ENCRYPT_DECRYPT
GenerateDataKey Symmetric ENCRYPT_DECRYPT
GenerateDataKeyPair Symmetric ENCRYPT_DECRYPT
GenerateDataKeyPairWithoutPlaintext Symmetric ENCRYPT_DECRYPT
GenerateDataKeyWithoutPlaintext Symmetric ENCRYPT_DECRYPT
GenerateRandom N/A. This operation doesn't use a CMK. N/A
ReEncrypt Any ENCRYPT_DECRYPT
Sign Asymmetric SIGN_VERIFY
Verify Asymmetric SIGN_VERIFY

特定の CMK リソースオペレーション

ここまでの表で「特定の CMK リソースオペレーション」としていた部分に関しては、以下のドキュメントから確認できます。

ここでは KMS に関するアクション(およびパーミッション)と、それを使用できるポリシーや条件キーが表でまとめられています。

この表で、リソース列が CMKとなっているもので、上述の条件キーが使用できます。

AWS_KMS_permissions_-_AWS_Key_Management_Service-8386669

初見でポリシータイプ列が「キーポリシー」となっていることに混乱した( IAM ポリシーじゃないの??)のですが、以下の脚注がありました。

Key policy means that you can specify the permission in the key policy. When the key policy contains the policy statement that enables IAM policies, you can specify the permission in an IAM policy.

機械翻訳の結果はこちら。

キーポリシーとは、キーポリシーにパーミッションを指定できることを意味します。キーポリシーにIAMポリシーを有効にするポリシーステートメントが含まれている場合、IAMポリシーでパーミッションを指定することができます。

ポリシータイプ列において「 IAM ポリシー」となっているものは、キーポリシーでは使用できないことを表します。

タグによるコントロールかエイリアスによるコントロールか

どちらのパターンでも柔軟でスケーラブルなアクセス制御が可能ですが、両者の考え方はわずかに異なります。どちらを選択すべきかは、既存の AWS の使用パターンによって変わります。

例えば、すでにほとんどの管理者にタグづけ権限が広く与えられている場合には、(それを絞っていくよりは)エイリアスに基づいたコントロールを行う方が簡単に済む場合が多いでしょう。

エイリアスに関するクォータが上限に近い場合には、タグを使用する方が好ましいこともあります。

それぞれのパターンによるメリットは以下の通りです。適したものを選択してください。

タグによるコントロールのメリット

他の AWS リソースと共通したタグを使用できる

すでに他の AWS リソースでタグベースのアクセス制御を行っている場合には、それを CMK にも踏襲できます。「他のリソースはタグベースだけど CMK ではエイリアスベース」とするよりは、一本化した方がメリットが出る場合もあるでしょう。

複数の CMK をグルーピングして使用できる

エイリアスは複数の CMK に対して同一のものを関連づけできない、というのは先述の通りです。複数の CMK に対してコントロールを行いたい場合には、それらに共通したタグを付与することによって簡単にグルーピングができます。

エイリアスによるコントロールのメリット

エイリアスに基づいた暗号化操作へのコントロールが可能

先ほど確認したkms:RequestAlias条件キーは、リクエストに含まれるエイリアスに応じてコントロールができます。これはタグによるコントロールの条件キーでは無い考え方です。

単一の CMK に限定したコントロールができる

タグベースの場合と逆の考え方となりますが、複数の CMK をグルーピングしたコントロールができない、ということがメリットになる場合もあります。エイリアスは AWS アカウントおよびリージョンにおいて一意である必要があり、また、同時に関連づけられる CMK も一つです。厳密なコントロールが要求される場合にはグルーピングせず単一で扱う方が適しているでしょう。

(エイリアスベースであっても、alias/test*など、ワイルドカードを使用することで複数の CMK を対象とすることはできます。)

やってみた

今回は以下のようなケースで試してみました。

kmscondition

IAM ユーザーにはAdministratorAccessを与えつつも、特定の条件で Deny するポリシーを作成してアタッチしています。

条件とは、「特定の値以外のエイリアスに対するリクエストである場合」です。そして「特定の値」とは、「自身に付与されたProjectタグの値」です。ポリシーの内訳は以下です。

特定の条件で Deny するポリシー

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Action": [
                "kms:DescribeKey"
            ],
            "Resource": "arn:aws:kms:*:000000000000:key/*",
            "Condition": {
                "StringNotEquals": {
                    "kms:RequestAlias": "alias/${aws:PrincipalTag/Project}"
                }
            }
        }
    ]
}

今回は IAM ユーザーにはProject:HOGEHOGEタグを付与しているので、「何でもできるけど、 HOGEHOGE 以外のエイリアスが関連づけられた CMK を Describe することができない」という状態です。

CMK は以下が存在しており、どちらもキーポリシーで IAM ポリシーによるアクセスを許可しています。

KMS_Console-8391997

キーポリシー

{
    "Id": "key-consolepolicy-3",
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::000000000000:root"
            },
            "Action": "kms:*",
            "Resource": "*"
        }
    ]
}

この状態でエイリアス HOGEHOGE を指定してaws kms describe-keyを実行すると、問題なく成功します。

% aws kms describe-key\
  --key-id alias/HOGEHOGE
{
    "KeyMetadata": {
        "AWSAccountId": "000000000000",
        "KeyId": "xxxxxxxx-7f6d-4290-b6ff-182b2ae6dd6f",
        "Arn": "arn:aws:kms:ap-northeast-1:000000000000:key/xxxxxxxx-7f6d-4290-b6ff-182b2ae6dd6f",
        "CreationDate": "2020-07-16T01:01:01.811000+09:00",
        "Enabled": true,
        "Description": "",
        "KeyUsage": "ENCRYPT_DECRYPT",
        "KeyState": "Enabled",
        "Origin": "AWS_KMS",
        "KeyManager": "CUSTOMER",
        "CustomerMasterKeySpec": "SYMMETRIC_DEFAULT",
        "EncryptionAlgorithms": [
            "SYMMETRIC_DEFAULT"
        ]
    }
}

エイリアスで Test-Key を指定すると、失敗します。

% aws kms describe-key\
  --key-id alias/Test-Key

An error occurred (AccessDeniedException) when calling the DescribeKey operation: User: arn:aws:iam::000000000000:user/chiba-cli is not authorized to perform: kms:DescribeKey on resource: arn:aws:kms:ap-northeast-1:000000000000:key/xxxxxxxx-e066-4bde-95e0-5ac3b2fb1d15 with an explicit deny

エイリアス Test-key が関連づけられた CMK のキー ID を直接指定しても Deny されます。

% aws kms describe-key\
  --key-id xxxxxxxx-e066-4bde-95e0-5ac3b2fb1d15

An error occurred (AccessDeniedException) when calling the DescribeKey operation: User: arn:aws:iam::000000000000:user/chiba-cli is not authorized to perform: kms:DescribeKey on resource: arn:aws:kms:ap-northeast-1:000000000000:key/xxxxxxxx-e066-4bde-95e0-5ac3b2fb1d15 with an explicit deny

エイリアスベースの ABAC が確認できました。

ちなみに

今回のケースで、実行元の IAM ユーザーにProjectキーを持つタグが設定されていないと Deny が効きません。Projectキーの値がブランクな分には問題ない(エイリアス HOGEHOGE も含めて拒否される)のですが、キー自体が無いとそのような挙動となるようです。

${aws:PrincipalTag/xxx}といったポリシー変数を条件キーに使用する際にはご注意ください。

ちなみに 2

エイリアス HOGEHOGE に加えて、エイリアス FUGAFUGA も関連づけた状態で試してみました。

エイリアス HOGEHOGE を指定した場合は変わらず成功します。

% aws kms describe-key\
  --key-id alias/HOGEHOGE
{
    "KeyMetadata": {
        "AWSAccountId": "000000000000",
        "KeyId": "xxxxxxxx-7f6d-4290-b6ff-182b2ae6dd6f",
        "Arn": "arn:aws:kms:ap-northeast-1:000000000000:key/xxxxxxxx-7f6d-4290-b6ff-182b2ae6dd6f",
        "CreationDate": "2020-07-16T01:01:01.811000+09:00",
        "Enabled": true,
        "Description": "",
        "KeyUsage": "ENCRYPT_DECRYPT",
        "KeyState": "Enabled",
        "Origin": "AWS_KMS",
        "KeyManager": "CUSTOMER",
        "CustomerMasterKeySpec": "SYMMETRIC_DEFAULT",
        "EncryptionAlgorithms": [
            "SYMMETRIC_DEFAULT"
        ]
    }
}

エイリアス FUGAFUGA を指定した場合は失敗します。

% aws kms describe-key\
  --key-id alias/FUGAFUGA

An error occurred (AccessDeniedException) when calling the DescribeKey operation: User: arn:aws:iam::000000000000:user/chiba-cli is not authorized to perform: kms:DescribeKey on resource: arn:aws:kms:ap-northeast-1:000000000000:key/xxxxxxxx-7f6d-4290-b6ff-182b2ae6dd6f with an explicit deny

キー ID を直接指定した場合も失敗します。

% aws kms describe-key\
  --key-id xxxxxxxx-7f6d-4290-b6ff-182b2ae6dd6f

An error occurred (AccessDeniedException) when calling the DescribeKey operation: User: arn:aws:iam::000000000000:user/chiba-cli is not authorized to perform: kms:DescribeKey on resource: arn:aws:kms:ap-northeast-1:000000000000:key/xxxxxxxx-7f6d-4290-b6ff-182b2ae6dd6f with an explicit deny

ややこしいですね。

終わりに

AWS KMS が タグもしくはエイリアスを使用した ABAC に対応したというアップデートでした。

適切に設定を行うことでセキュリティレベルを高めることができますね。一方で、タグやエイリアスの変更によって意図せず動作しなくなる、というリスクも抱えることになりますので、実装される際には検討・検証をしっかり行うようにしてください。

以上、千葉(幸)がお送りしました。

あわせて読んでもいいかもしれない