はじめに
最近、巷でマルチアカウント構成が流行ってるということで、マルチアカウント環境を前提とした KMS のクロスアカウントアクセスによる復号を試します。
前提条件
マルチアカウント環境を前提とします。本記事では便宜上、各アカウントを以下呼称とします。
- MasterAccount
- MemberAccount
KMS クロスアカウント復号の仕組み
KMS に対する操作権限は以下 2 つのポリシーで制御します。
- IAM ポリシー
- KMS key ポリシー
両方でアクセス許可されている時に、KMS のクロスアカウントアクセスが可能となります。
クロスアカウントアクセスには、KMS key の key ポリシーと、外部ユーザーアカウントの IAM ポリシーのアクセス許可が必要です。 https://docs.aws.amazon.com/ja_jp/kms/latest/developerguide/key-policy-modifying-external-accounts.html
図で表すと以下のイメージです。
検証の構成
上記の仕組みを検証するために、以下構成でクロスアカウントアクセスによる復号を試します。
①MasterAccount にて、Cfn テンプレートを使用して、KMS key を作成します。
②MasterAccount にて、Cloudshell から ① で作成した KMS key により適当な文字列を暗号化します。
③MemberAccount にて、Cloudshell から ② で暗号化した適当な文字列を復号します。
セットアップ
①KMS key 作成
①-1. 本記事の "付録" > "KMS Key 用 Cfn テンプレート" の Cfn テンプレートを使用して、MasterAccount に KMS key を作成します。
Cfn コンソールでは、下記テンプレートパラメータを更新してください。
- CrossAccountAccessID: KMS key のアクセス許可する 外部 AWS アカウント内に存在する IAM オブジェクト ARN のカンマ区切りのリスト
e.g. arn:aws:iam::12345678xxxx:root, arn:aws:iam::23456789xxxx:root
なお、今回作成される KMS Key Policy は、
- 自アカウント(=MasterAccount)内の全ての IAM オブジェクトに対して、本 Cfn テンプレートで作成する KMS key への全 API コールの許可
- "CrossAccountAccessID" でインプットした外部アカウント(=MemberAccount)内の全ての IAM オブジェクトに対して、本 Cfn テンプレートで作成する KMS key への kms:Decrypt API コールの許可
が付与されます。
② 適当な文字列の暗号化
CloudShell から CLI を使って、Encrypt API コールをおこない、適当な文字列を暗号化します。
②-1. KMS:Encrypt API コールをできる IAM ユーザを使って、CloudShell にログインします。
②-2. 以下 CLI コマンドを実行します。
{{KMS_KEY_ID}} は、対象の Cfn スタックにて、 "出力タブ" > "OutputKmsCrossAccountDecryptVerificationID" から取得した KMS Key の ID に置き換えて実行します。
$ KMS_KEY_ID={{KMS_KEY_ID}} //KMS_KEY_ID 環境変数に KMS Key ID を格納 $ echo ${KMS_KEY_ID} //環境変数の確認用 $ echo "こんにちは、世界!" | base64 | xargs -IPLAIN_TEXT aws kms encrypt --key-id ${KMS_KEY_ID} --plaintext PLAIN_TEXT //文字列の暗号化
②-3 実行出力の JSON の CiphertextBlob 値を、どこかに控えます。
この値は動作確認で復号する際に使用します。
③(オプション)CloudShell 用 IAM ユーザ作成
必要に応じて、以下条件の IAM ユーザを MemberAccount に作成します。
- KMS:Decrypt 権限がある
- CloudShell の操作権限がある
- コンソールログイン可能
細かい手順は割愛します。
動作確認
MemberAccount の CloudShell を使って、クロスアカウント復号のテストを行います。
① KMS:Decrypt API コールをできる IAM ユーザにより、MemberAccount の CloudSell へログインします。
② ログイン後、以下コマンドを実行します。
{{CIPHER_TEXT}} は、本記事の "セットアップ" > "②-3" から取得した CiphertextBlob 値に置き換えます。
$ CIPHER_TEXT={{CIPHER_TEXT}} //KMS_KEY_ID 環境変数に KMS Key ID を格納 $ echo ${CIPHER_TEXT} //環境変数の確認用 $ aws kms decrypt --ciphertext-blob ${CIPHER_TEXT} --query 'Plaintext'| tr -d \" | base64 -d //クロスアカウント復号
なお、decrypt コマンドには KMS Key 指定は必須ではありません。これは、 CiphertextBlob に KMS Key ID が含まれているからです。
③ "②" の出力結果が暗号化した文字列であれば、動作確認完了です。
付録
KMS Key 用 Cfn テンプレート
作成されるリソース:
- KMS Key
- KMS Key Alias
※ KMS 削除する場合、テンプレート内の "PendingWindowInDays" セクションの期間中は完全に削除されませんので、ご注意ください。
PendingWindowInDays 引用元: https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-kms-key.html
Parameters: CrossAccountAccessIamARN: Description: Input AWS IAM ARN you want to allow access to. e.g. arn:aws:iam::12345678xxxx:root, arn:aws:iam::23456789xxxx:root Type: CommaDelimitedList Resources: KmsCrossAccountDecryptVerification: Type: AWS::KMS::Key Properties: Description: for kms-crossaccount-access verification Enabled: True EnableKeyRotation: True KeyPolicy: { "Version": "2012-10-17", "Statement": [ { "Sid": "All API Call From MyAccount IAM Resource", "Effect": "Allow", "Principal": { "AWS": { "Fn::Sub": "arn:aws:iam::${AWS::AccountId}:root" } }, "Action": "kms:*", "Resource": "*" }, { "Sid": "Decrypt API Call From OtherAccount IAM Resource", "Effect": "Allow", "Principal": { "AWS": { "Ref": "CrossAccountAccessIamARN" } }, "Action": [ "kms:Decrypt" ], "Resource": "*" } ] } KeySpec: SYMMETRIC_DEFAULT MultiRegion: False PendingWindowInDays: 7 Tags: - Key: Name Value: !Sub kms-crossaccount-decrypt-verification-${AWS::AccountId} - Key: Use Value: Verification - Key: CfnStackName Value: !Ref AWS::StackName KmsCrossAccountDecryptVerificationAlias: Type: AWS::KMS::Alias Properties: AliasName: !Sub alias/kms-crossaccount-decrypt-verification-${AWS::AccountId} TargetKeyId: !Ref KmsCrossAccountDecryptVerification Outputs: OutputKmsCrossAccountDecryptVerificationID: Value: !Ref KmsCrossAccountDecryptVerification OutputKmsCrossAccountDecryptVerificationArn: Value: !GetAtt KmsCrossAccountDecryptVerification.Arn OutputKmsCrossAccountDecryptVerificationAlias: Value: !Ref KmsCrossAccountDecryptVerificationAlias
参考:
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-kms-key.html
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-kms-alias.html
菅谷 歩 (記事一覧)