AWS KMS でクロスアカウント復号してみる

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

はじめに

最近、巷でマルチアカウント構成が流行ってるということで、マルチアカウント環境を前提とした 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

図で表すと以下のイメージです。

f:id:swx-sugaya:20220201125930p:plain

検証の構成

上記の仕組みを検証するために、以下構成でクロスアカウントアクセスによる復号を試します。

f:id:swx-sugaya:20220201125956p:plain

①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

菅谷 歩 (記事一覧)