クロスアカウントでの KMS キー利用

別の AWS アカウントにある KMS キーを使用するためのアクセス制御の仕組み

基本的な考え方

クロスアカウントで KMS キーを使用するには、2つのポリシーが必要

出典: Allowing users in other accounts to use a KMS key

“Cross-account access requires permission in the key policy of the KMS key and in an IAM policy in the external user’s account.”

必要な2つのポリシー:

ポリシー設定場所役割
キーポリシーKMS キーを所有するアカウント外部アカウントにキーの使用を許可する
IAM ポリシーKMS キーを使用する外部アカウント自アカウントのユーザー/ロールにキーの使用を許可する

キーポリシーだけでも、IAM ポリシーだけでも不十分。両方が揃って初めてアクセスが許可される

出典: Allowing users in other accounts to use a KMS key

“The key policy determines who can have access to the KMS key. The IAM policy determines who does have access to the KMS key. Neither the key policy nor the IAM policy alone is sufficient—you must change both.”

キーポリシーは「誰がアクセスできる可能性があるか」を定義し、IAM ポリシーは「実際に誰がアクセスするか」を定義する。この2段階の仕組みにより、キー所有者と利用者の両方が制御権を持てる

必要な設定

ステップ1: キーポリシーの設定(キー所有アカウント側)

キー所有アカウントで、外部アカウントへの権限をキーポリシーに追加する

出典: Allowing users in other accounts to use a KMS key

“To give an external account permission to use the KMS key, add a statement to the key policy that specifies the external account. In the Principal element of the key policy, enter the Amazon Resource Name (ARN) of the external account.”

外部アカウントの ARN を Principal に指定することで、そのアカウントに権限を委譲できる

{
    "Sid": "Allow an external account to use this KMS key",
    "Effect": "Allow",
    "Principal": {
        "AWS": "arn:aws:iam::444455556666:root"
    },
    "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:DescribeKey"
    ],
    "Resource": "*"
}

ステップ2: IAM ポリシーの設定(利用アカウント側)

外部アカウント側で、ユーザーやロールに IAM ポリシーをアタッチする

出典: Allowing users in other accounts to use a KMS key

“The key policy in the account that owns the KMS key sets the valid range for permissions. But, users and roles in the external account cannot use the KMS key until you attach IAM policies that delegate those permissions, or use grants to manage access to the KMS key.”

キーポリシーで許可された範囲内でのみ、IAM ポリシーで権限を付与できる。キーポリシーで許可されていない操作を IAM ポリシーで許可しても無効

{
    "Sid": "AllowUseOfKeyInAccount111122223333",
    "Effect": "Allow",
    "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:DescribeKey"
    ],
    "Resource": "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"
}

図解

┌─────────────────────────────────────────────────────────────────────────┐
│ アカウント A(キー所有者: 111122223333)                                  │
│                                                                         │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │ KMS キー                                                         │   │
│  │                                                                  │   │
│  │ キーポリシー:                                                    │   │
│  │   Principal: arn:aws:iam::444455556666:root                     │   │
│  │   Action: kms:Encrypt, kms:Decrypt, ...                         │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                    ▲                                    │
└────────────────────────────────────│────────────────────────────────────┘
                                     │ クロスアカウントアクセス
┌────────────────────────────────────│────────────────────────────────────┐
│ アカウント B(利用者: 444455556666)│                                    │
│                                    │                                    │
│  ┌──────────────────┐              │                                    │
│  │ IAM ユーザー/ロール│──────────────┘                                    │
│  │                  │                                                   │
│  │ IAM ポリシー:                                                        │
│  │   Resource: arn:aws:kms:...:111122223333:key/...                    │
│  │   Action: kms:Encrypt, kms:Decrypt, ...                             │
│  └──────────────────┘                                                   │
└─────────────────────────────────────────────────────────────────────────┘

クロスアカウントで許可できる操作

すべての KMS 操作がクロスアカウントで使えるわけではない

出典: Allowing users in other accounts to use a KMS key

“Cross-account permission is effective only for the following operations: Cryptographic operations, CreateGrant, DescribeKey, GetKeyRotationStatus, GetPublicKey, ListGrants, RetireGrant, RevokeGrant.”

クロスアカウントで許可できるのは暗号化操作とグラント関連操作のみ。キーの削除やローテーション設定などの管理操作はクロスアカウントでは許可できない

許可可能許可不可
Encrypt, DecryptScheduleKeyDeletion
GenerateDataKeyEnableKeyRotation
CreateGrantPutKeyPolicy
DescribeKeyListKeys

グラント (Grant)

KMS キーへの一時的なアクセス許可を付与する仕組み

出典: Grants in AWS KMS

“A grant is a policy instrument that allows AWS principals to use KMS keys in cryptographic operations. It also can let them view a KMS key (DescribeKey) and create and manage grants.”

グラントはキーポリシーや IAM ポリシーと並ぶ、KMS のアクセス制御メカニズムの1つ

ポリシーではなくグラントを使う場面

出典: KMS key access and permissions

“We recommend issuing time-bound access if you don’t know the names of the principals at the time that the policies are created, or if the principals that require access frequently change.”

以下のケースでグラントが適している:

ケース理由
権限を与える相手が事前にわからないポリシーには Principal を書く必要があるが、グラントなら動的に作成できる
権限を与える相手が頻繁に変わるポリシーを何度も編集するより、グラントの作成・削除の方が簡単

「権限を与える相手が頻繁に変わる」ケースについて補足すると、ポリシーは静的なドキュメントであり、変更のたびに編集・デプロイが必要。一方グラントは API で動的に作成・削除できるため、頻繁な変更に向いている

AWS サービスがグラントを使う理由

出典: Grants in AWS KMS

“Grants are commonly used by AWS services that integrate with AWS KMS to encrypt your data at rest. The service creates a grant on behalf of a user in the account, uses its permissions, and retires the grant as soon as its task is complete.”

EBS、RDS、S3 などの AWS サービスがデータを暗号化する際、サービスがユーザーに代わってグラントを作成し、処理完了後に自動で削除する

具体例として AWS Verified Access のドキュメントに詳細な説明がある:

出典: Data encryption at rest for AWS Verified Access

“When you create Verified Access resources encrypted with a customer managed key, Verified Access creates a grant on your behalf by sending a CreateGrant request to AWS KMS. Grants in AWS KMS are used to give Verified Access the access to a customer managed key in your account.”

ユーザーがカスタマーマネージドキーで暗号化されたリソースを作成すると、AWS サービス(この例では Verified Access)がユーザーに代わって CreateGrant を実行し、自分自身に KMS キーへのアクセス権を付与する

出典: Data encryption at rest for AWS Verified Access

“Verified Access requires the grant to use your customer managed key for the following internal operations: Send Decrypt requests to AWS KMS to decrypt the encrypted data keys so that they can be used to decrypt your data. Send RetireGrant requests to AWS KMS to delete a grant.”

グラントによって AWS サービスは Decrypt(復号)や RetireGrant(グラント削除)などの操作を実行できるようになる

なぜグラントが必要か

一時的な権限付与

出典: Grants in AWS KMS

“Grants are often used for temporary permissions because you can create one, use its permissions, and delete it without changing your key policies or IAM policies.”

キーポリシーの変更は影響範囲が大きく、変更履歴の管理も煩雑になる。グラントなら作成→使用→削除のサイクルが簡単で、ポリシーを変更せずに済む

グラントの特徴

出典: Grants in AWS KMS

“Each grant allows access to exactly one KMS key. You can create a grant for a KMS key in a different AWS account.”

1つのグラントは1つの KMS キーに対してのみ有効。ただし、異なるアカウントの KMS キーに対してもグラントを作成できる

出典: Grants in AWS KMS

“A grant can allow access to a KMS key, but not deny access.”

グラントは許可のみ可能で、拒否はできない。拒否が必要な場合はキーポリシーや IAM ポリシーを使う

キーポリシー・IAM ポリシーとの比較

出典: KMS key access and permissions

“You can use grants in combination with the key policy and IAM policies to allow access to a KMS key. Controlling access this way enables you to allow access to the KMS key in the key policy, and to allow identities to delegate their access to others.”

グラントはキーポリシーや IAM ポリシーと組み合わせて使う。特に「権限の委譲」が必要な場合に有効

項目キーポリシーIAM ポリシーグラント
対象KMS キー単位IAM プリンシパル単位KMS キー単位
用途恒久的なアクセス制御恒久的なアクセス制御一時的なアクセス許可
変更の影響大きい中程度小さい
削除ポリシー編集が必要ポリシー編集が必要Retire/Revoke で即削除
拒否可能可能不可

グラントで許可できる操作

出典: Grants in AWS KMS

“A grant can only allow grant operations. The grant operations must be supported by the KMS key in the grant.”

グラントで許可できる操作は限定されている。キー管理操作(削除、ローテーション設定など)はグラントでは許可できない

  • 暗号化操作: Encrypt, Decrypt, GenerateDataKey, ReEncrypt, Sign, Verify など
  • その他: DescribeKey, CreateGrant, RetireGrant

グラントの削除

操作実行者説明
Retireグラント受領者または retiring principal自分のグラントを返上する
Revokeキー管理者管理者がグラントを強制的に取り消す

制限

出典: Grants in AWS KMS

“AWS KMS limits the number of grants on each KMS key.”

1つの KMS キーあたり最大 50,000 グラント


クロスアカウントでのグラント利用

クロスアカウントで KMS キーを使う際、AWS サービスがグラントを作成するケースが多い

典型的なユースケース: 暗号化 AMI の共有

暗号化された AMI を別アカウントに共有する場合、AMI の共有だけでは不十分

出典: Share an AMI with specific AWS accounts

“The encrypted snapshots must be encrypted with a KMS key. You can’t share AMIs that are backed by snapshots that are encrypted with the default AWS managed key.” “If you share an AMI that is backed by encrypted snapshots, you must allow the AWS accounts to use the KMS keys that were used to encrypt the snapshots.”

暗号化スナップショットを復号するには KMS キーへのアクセスが必要。AWS マネージドキーで暗号化された AMI は共有できないため、カスタマーマネージドキーを使う必要がある

なぜ CreateGrant 権限が必要か

サービスリンクロールとは

AWS サービスがユーザーに代わって他の AWS サービスを呼び出すために使用する特殊な IAM ロール

出典: Service-linked role for Spot Instance requests

“Amazon EC2 uses service-linked roles for the permissions that it requires to call other AWS services on your behalf. A service-linked role is a unique type of IAM role that is linked directly to an AWS service.”

EC2 サービスは AWSServiceRoleForEC2Spot などのサービスリンクロールを使って、ユーザーに代わってインスタンスの起動・停止などを行う

サービスリンクロールと KMS キー

出典: Required AWS KMS key policy for use with encrypted volumes

“Amazon EC2 Auto Scaling service-linked roles are predefined and include permissions that Amazon EC2 Auto Scaling requires to call other AWS services on your behalf. The predefined permissions also include access to your AWS managed keys. However, they do not include access to your customer managed keys, allowing you to maintain full control over these keys.”

サービスリンクロールは AWS マネージドキーへのアクセス権は持っているが、カスタマーマネージドキーへのアクセス権は持っていない。カスタマーマネージドキーを使う場合は、明示的に権限を付与する必要がある

グラントによる権限付与

出典: Service-linked role for Spot Instance requests

“If you specify an encrypted AMI or an encrypted Amazon EBS snapshot for your Spot Instances and you use a customer managed key for encryption, you must grant the AWSServiceRoleForEC2Spot role permission to use the customer managed key so that Amazon EC2 can launch Spot Instances on your behalf. To do this, you must add a grant to the customer managed key.”

暗号化された AMI やスナップショットを使う場合、サービスリンクロールに KMS キーの使用権限を与えるためにグラントを作成する必要がある

登場人物

名前説明所属
アカウント AKMS キーと AMI を所有-
アカウント B のユーザーAMI からインスタンスを起動したい人アカウント B
サービスリンクロールAWS サービスがユーザーに代わって操作を行うための IAM ロール(例: AWSServiceRoleForEC2Spotアカウント B

各リソースの所在

リソース所属アカウント
KMS キーアカウント A
暗号化 AMIアカウント A(アカウント B に共有済み)
暗号化スナップショットアカウント A
サービスリンクロールアカウント B
起動されるインスタンスアカウント B
作成される EBS ボリュームアカウント B

処理の流れ

┌─────────────────────────────────────────────────────────────────────────┐
│ アカウント B                                                             │
│                                                                         │
│  ユーザー                                                                │
│    │                                                                    │
│    │ ① インスタンス起動リクエスト                                        │
│    │   「アカウントAのAMIを使ってインスタンス作って」                      │
│    │                                                                    │
│    ▼                                                                    │
│  サービスリンクロール(AWSServiceRoleForEC2Spot など)                    │
│    │                                                                    │
│    │ ② CreateGrant を実行                                               │
│    │   「自分自身(サービスリンクロール)にKMSキーの使用権限を付与」       │
│    │                                                                    │
│    │   ※ この操作には以下が必要:                                        │
│    │     - アカウントBのユーザーが kms:CreateGrant 権限を持っている       │
│    │     - アカウントAのキーポリシーがアカウントBに CreateGrant を許可    │
│    │                                                                    │
│    ▼                                                                    │
│  ┌──────────────────────────────────────────────────────────────────┐   │
│  │ グラント作成完了                                                  │   │
│  │ → サービスリンクロールが一時的に Decrypt 権限を取得               │   │
│  └──────────────────────────────────────────────────────────────────┘   │
│    │                                                                    │
│    │ ③ Decrypt を実行                                                   │
│    │   アカウントAのKMSキーでスナップショットを復号                      │
│    │                                                                    │
│    │ ④ EBS ボリューム作成(アカウントBに)                              │
│    │                                                                    │
│    │ ⑤ インスタンス起動(アカウントBに)                                │
│    │                                                                    │
│    │ ⑥ RetireGrant を実行                                               │
│    │   「一時的な権限を返上します」                                      │
│    ▼                                                                    │
│  完了                                                                    │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘
     │
     │ 結果
     ▼
┌─────────────────────────────────────────────────────────────────────────┐
│ アカウント A                           │ アカウント B                    │
│                                        │                                │
│  KMS キー ←── 復号に使用               │  インスタンス(新規作成)       │
│  暗号化 AMI ←── 元データ               │  EBS ボリューム(新規作成)     │
│  暗号化スナップショット ←── 復号対象   │                                │
│                                        │                                │
└────────────────────────────────────────┴────────────────────────────────┘

ポイント

  1. サービスリンクロールは AWS サービスがユーザーに代わって操作を行うための IAM ロール
  2. ユーザーは「インスタンス起動」をリクエストするだけ。実際の処理はサービスリンクロールが行う
  3. サービスリンクロールがカスタマーマネージドキーを使うために、グラントを作成して自分自身に権限を付与する
  4. グラントを作成するには、ユーザーが kms:CreateGrant 権限を持っている必要がある
  5. 処理完了後、サービスリンクロールがグラントを削除(Retire)するので、一時的な権限は残らない

必要なキーポリシー設定

出典: Allow organizations and OUs to use a KMS key

外部アカウントに対して、暗号化操作に加えて kms:CreateGrant を許可する必要がある

{
    "Sid": "Allow access for external account",
    "Effect": "Allow",
    "Principal": {
        "AWS": "arn:aws:iam::444455556666:root"
    },
    "Action": [
        "kms:Decrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:CreateGrant"
    ],
    "Resource": "*"
}

kms:CreateGrant がないと、EC2 サービスがグラントを作成できず、インスタンス起動が失敗する

全体の流れ

手順実行者操作
1キー所有アカウントKMS キーポリシーに外部アカウントへの権限を追加(CreateGrant 含む)
2キー所有アカウントAMI を外部アカウントに共有
3外部アカウントAMI からインスタンス起動をリクエスト
4EC2 サービスグラントを作成して KMS キーを使用
5EC2 サービススナップショット復号 → ボリューム作成
6EC2 サービスグラントを Retire

注意点

出典: Allowing users in other accounts to use a KMS key

“Be cautious about giving principals permissions to use your KMS keys. Whenever possible, follow the least privilege principle. Give users access only to the KMS keys they need for only the operations they require.”

CreateGrant 権限は強力な権限

グラントを作成できる人は、その権限を他者に委譲できてしまうので最小権限の原則に従い、必要なアカウント・操作のみに限定するのが良い