AWS KMSでの手動キーローテーション

TL;DR

あるAWS Security関連の教科書に、KMSの手動ローテーションは、鍵を新規作成して 古い鍵を削除する旨の記述があり、「古い鍵を削除したら復号できなくなるじゃないのか?」 と思ったので検証してみた。

KMSのAPIに、ReEncryptというキーローテーションのためのAPIが用意されており、これを使うと、新しい鍵でData Keyを再暗号化できる。 よって管理しているData Keyをすべて再暗号化すれば、ローテーションされた古い鍵を削除することができる。

また手動キーローテーションは、以下の手順がよさそうだ。

  1. 新しい鍵を生成 (CreateKey)
  2. ローテートする鍵のエイリアスを新しい鍵に継承 (UpdateAlias)
  3. 古い鍵で暗号化したData Keyを新しい鍵で再暗号化 (ReEncrypt)
  4. 古い鍵の削除予約 (ScheduleKeyDeletion)

Introduction

AWS KMS 開発者ガイドの手動でのキーローテーションには、以下の注釈がある。

新しい CMK の使用を開始するときに、元の CMK を有効なままにすれば、AWS KMS は元の CMK により暗号化されたデータを復号できます。データを復号するとき、KMS はデータの暗号化に使用された CMK を識別し、同じ CMK を使用して復号します。元の CMK と新しいものの両方が有効である限り、AWS KMS はどちらの CMK によって暗号化されたデータでも復号できます。

鍵が有効、すなわち削除または無効化しなければ復号できるとある。まぁそれはそうだろう。 しかしこれは、教科書とは異なっているため、検証してみた。

鍵の削除保留期間中に復号可能かどうか確認

まず、前回作成した鍵を削除予約し、削除保留状態にする。

$ aws kms schedule-key-deletion --key-id a99dd0c2-494f-4650-99ba-811078e86390
{
    "KeyId": "arn:aws:kms:ap-northeast-1:xxxxxxxxxxxxx:key/a99dd0c2-494f-4650-99ba-811078e86390",
    "DeletionDate": 1599436800.0
}

鍵の状態を確認すると、PendingDeletionになっており、削除保留状態であることがわかる。

$ aws kms describe-key --key-id a99dd0c2-494f-4650-99ba-811078e86390 \
 	--output text  --query KeyMetadata.KeyState
PendingDeletion

では、この鍵を使って復号するとどうなるか。

$ aws kms decrypt --ciphertext-blob  fileb://encrypted_datakey.bin \
	--key-id a99dd0c2-494f-4650-99ba-811078e86390

An error occurred (KMSInvalidStateException) when calling the Decrypt operation: arn:aws:kms:ap-northeast-1:xxxxxxxxxxxxx:key/a99dd0c2-494f-4650-99ba-811078e86390 is pending deletion.

ですよねー

ちなみに無効のときも、ちゃんとエラーが返る。

$ aws kms decrypt --ciphertext-blob  fileb://encrypted_datakey.bin \
	--key-id a99dd0c2-494f-4650-99ba-811078e86390

An error occurred (DisabledException) when calling the Decrypt operation: arn:aws:kms:ap-northeast-1:xxxxxxxxxxxxx:key/a99dd0c2-494f-4650-99ba-811078e86390 is disabled.

Data Key ReEncryption

なーんだ、教科書まちがってんじゃん。まぁよくあるよねーで済まそうと思っていたのだが、 AWSのAPIドキュメントに、ReEncryptというActionがあるのに気がついた。 KMS APIドキュメントのReEncryptの冒頭に以下の記述がある。

Decrypts ciphertext and then reencrypts it entirely within AWS KMS. You can use this operation to change the customer master key (CMK) under which data is encrypted, such as when you manually rotate a CMK or change the CMK that protects a ciphertext.
(AWS KMSの内部で暗号化されたデータを復号したあと、再暗号化する。 この操作は、手動ローテートまたはデータを保護しているCMKの変更といった、 暗号化されたデータのCMKの変更に使用することができる。)

あーCMKのmanually rotateに使うって書いてあるよ。 ということで、Data Keyを新しい鍵で再暗号化することで、古い鍵を削除することができるようだ。

せっかくなので、検証。

$ aws kms re-encrypt --ciphertext-blob fileb://encrypted_datakey.bin \
    --source-key-id a99dd0c2-494f-4650-99ba-811078e86390 \
    --destination-key-id 0676925f-cf0f-4dd3-b44e-28019abc4b4f
{
    "CiphertextBlob": "AQICAHiU/sFZekLEdu8fd/KEweZKipeRYu7IFuTQhYEqP/GM5wEBgW7RhOZ5GNPgKKOIcPrTAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMMLNzPFHv5pC5TMKeAgEQgDvrQ+/LP8dwZy/joqeZIa8bnbfzKEfTHEXxsrWtRZyhOCcJhMTqhBPf7KhruU2kMqDIeA7ZhyRs8I93fQ==",
    "SourceKeyId": "arn:aws:kms:ap-northeast-1:xxxxxxxxxxxxx:key/a99dd0c2-494f-4650-99ba-811078e86390",
    "KeyId": "arn:aws:kms:ap-northeast-1:xxxxxxxxxxxxx:key/0676925f-cf0f-4dd3-b44e-28019abc4b4f",
    "SourceEncryptionAlgorithm": "SYMMETRIC_DEFAULT",
    "DestinationEncryptionAlgorithm": "SYMMETRIC_DEFAULT"
}

おーできたー

CybertextBlobのBase64エンコードを解いてre-encrypted_datakey.binに格納したあと、再暗号化に使用した鍵で復号する。

$ aws kms decrypt --key-id 0676925f-cf0f-4dd3-b44e-28019abc4b4f --ciphertext-blob fileb://re-encrypted_datakey.bin --output text --query Plaintext|base64 -d >decrypted_datakey.bin

で、オリジナルのハッシュと比較する。

$ sha256sum datakey.bin decrypted_datakey.bin 
0ce2033e1f0aff4508ebf82612e59c449d11bf0e5e50a6ac7fc95337989f9b84  datakey.bin
0ce2033e1f0aff4508ebf82612e59c449d11bf0e5e50a6ac7fc95337989f9b84  decrypted_datakey.bin

一致した。ということで、Data Keyの再暗号化に成功したことがわかる。

Key aliasの継承

鍵のローテーションにより、Key aliasを新しい鍵に継承する必要がある。 そこで、UpdateAliasオペレーションをつかう。

$ aws kms update-alias --alias-name alias/aestest --target-key-id 0676925f-cf0f-4dd3-b44e-28019abc4b4f

このオペレーションには、KeyPolicyのaliasを、kms:UpdateAlias できるIAMロールが必要なので注意。

継承が終わったあと、古い鍵はまだ有効であるが、Aliasは削除されている。 よって、手動の鍵のローテーションは以下の手順が良さそうだ。

  1. 新しい鍵を生成 (CreateKey)
  2. ローテートする鍵のエイリアスを新しい鍵に継承 (UpdateAlias)
  3. 古い鍵で暗号化したData Keyを新しい鍵で再暗号化 (ReEncrypt)
  4. 古い鍵の削除予約 (ScheduleKeyDeletion)

まとめ

KMSの手動によるキーローテーションでは、ReEncryptオペレーションを使うとData KeyのCMKを変更することができる。古い鍵を有効にしておくこともできるが、鍵一つにつき1USD/monthのキーストレージの使用料金がかかってしまう。また、ローテーションするときには、新しい鍵を生成後、Aliasを新しい鍵に継承したあと、Data Keyの再暗号化処理を行うと良い。


awskms

1801 Words

2020-08-07 16:50 +0900