ablog

不器用で落着きのない技術者のメモ

S3 バケットのデフォルト暗号化に使う CMK を KMS で生成したものから BYOK に変えてみる

S3 バケットのデフォルト暗号化に使う CMK(Customer Master Key) を KMS(Key Management Service) で生成したものから BYOK(Bring Your Own Key) に変えてみた。

手順

KMS に CMK を作成する
  • CMK を作成する
$ aws kms create-key
{
    "KeyMetadata": {
        "Origin": "AWS_KMS",
        "KeyId": "c3c1fb86-168d-40ca-9489-90cf2bd49dfa", ★
        "Description": "",
        "KeyManager": "CUSTOMER",
        "Enabled": true,
        "KeyUsage": "ENCRYPT_DECRYPT",
        "KeyState": "Enabled",
        "CreationDate": 1540799362.916,
        "Arn": "arn:aws:kms:ap-northeast-1:123456789012:key/c3c1fb86-168d-40ca-9489-90cf2bd49dfa",
        "AWSAccountId": "123456789012"
    }
}
$ aws kms create-alias --alias-name alias/kms-gen-key --target-key-id c3c1fb86-168d-40ca-9489-90cf2bd49dfa
S3バケットのデフォルト暗号化を設定してファイルを Put する
$ aws s3 mb s3://kms-key-change-test
make_bucket: kms-key-change-test
  • デフォルト暗号化設定を行う
$ aws s3api  put-bucket-encryption --bucket kms-key-change-test --server-side-encryption-configuration '{
  "Rules": [
    {
      "ApplyServerSideEncryptionByDefault": {
        "SSEAlgorithm": "aws:kms",
        "KMSMasterKeyID": "c3c1fb86-168d-40ca-9489-90cf2bd49dfa" ★
      }
    }
  ]
}'
  • デフォルト暗号化設定を確認する
$ aws s3api get-bucket-encryption --bucket kms-key-change-test
{
    "ServerSideEncryptionConfiguration": {
        "Rules": [
            {
                "ApplyServerSideEncryptionByDefault": {
                    "KMSMasterKeyID": "c3c1fb86-168d-40ca-9489-90cf2bd49dfa", ★
                    "SSEAlgorithm": "aws:kms"
                }
            }
        ]
    }
}
  • ファイルを Put する
$ echo 'Test' > test1.txt
$ cp test1.txt test2.txt
$ cp test1.txt test3.txt
$ aws s3 cp test1.txt s3://kms-key-change-test/
upload: ./test1.txt to s3://kms-key-change-test/test1.txt
$ aws s3 cp test2.txt s3://kms-key-change-test/
upload: ./test2.txt to s3://kms-key-change-test/test2.txt
$ aws s3 cp test3.txt s3://kms-key-change-test/
upload: ./test3.txt to s3://kms-key-change-test/test3.txt
  • オブジェクト暗号化に使われているキーを確認する
$ aws s3api head-object --bucket kms-key-change-test --key test1.txt
{
    "AcceptRanges": "bytes",
    "ContentType": "text/plain",
    "LastModified": "Mon, 29 Oct 2018 08:01:00 GMT",
    "ContentLength": 5,
    "ETag": "\"028422466ea4c14965264d1666728a7c\"",
    "ServerSideEncryption": "aws:kms",
    "SSEKMSKeyId": "arn:aws:kms:ap-northeast-1:123456789012:key/c3c1fb86-168d-40ca-9489-90cf2bd49dfa", ★
    "Metadata": {}
}
KMS に BYOK する
  • CMK を作成する
$ aws kms create-key --origin EXTERNAL --description byok_key
{
    "KeyMetadata": {
        "Origin": "EXTERNAL",
        "KeyId": "2afa832b-d531-40fe-ac8c-4e34a578939a", ★
        "Description": "byok_key",
        "KeyManager": "CUSTOMER",
        "Enabled": false,
        "KeyUsage": "ENCRYPT_DECRYPT",
        "KeyState": "PendingImport",
        "CreationDate": 1540801553.271,
        "Arn": "arn:aws:kms:ap-northeast-1:123456789012:key/2afa832b-d531-40fe-ac8c-4e34a578939a",
        "AWSAccountId": "123456789012"
    }
}
$ aws kms create-alias --alias-name alias/kms-byok-key --target-key-id 2afa832b-d531-40fe-ac8c-4e34a578939a
  • PublicKey と ImportToken をダウンロードする。
$ aws kms get-parameters-for-import \
--key-id 2afa832b-d531-40fe-ac8c-4e34a578939a \
--wrapping-algorithm RSAES_PKCS1_V1_5 \
--wrapping-key-spec RSA_2048
  • 上記のPublicKey を PublicKey.b64、ImportToken を ImportToken.b64 というファイル名で保存する。
  • PublicKey と ImportToken をそれぞれbase64デコードして、新しいファイルで保存する。
$ openssl enc -d -a -A -in PublicKey.b64 -out PublicKey.bin
$ openssl enc -d -a -A -in ImportToken.b64 -out ImportToken.bin
  • KMS にインポートする CMK を作成する
$ openssl rand -out PlaintextKeyMaterial.bin 32
  • 生成した CMK を、デコードした PublicKey を使って暗号化する。
$ openssl rsautl -encrypt \
-in PlaintextKeyMaterial.bin \
-pkcs \
-inkey PublicKey.bin \
-keyform DER \
-pubin \
-out EncryptedKeyMaterial.bin
  • CMK を KMS にインポートする。
$ aws kms import-key-material --key-id 2afa832b-d531-40fe-ac8c-4e34a578939a \
--encrypted-key-material fileb://EncryptedKeyMaterial.bin \
--import-token fileb://ImportToken.bin \
--expiration-model KEY_MATERIAL_EXPIRES \
--valid-to 2018-11-01T00:00:00-00:00
S3バケットのデフォルト暗号化キーを BYOK した CMK に変更する
  • デフォルト暗号化キーを BYOK した CMK に変更する
$ aws s3api put-bucket-encryption --bucket kms-key-change-test --server-side-encryption-configuration '{
  "Rules": [
    {
      "ApplyServerSideEncryptionByDefault": {
        "SSEAlgorithm": "aws:kms",
        "KMSMasterKeyID": "2afa832b-d531-40fe-ac8c-4e34a578939a" ★
      }
    }
  ]
}'
  • デフォルト暗号化キーが変更されていることを確認する
$ aws s3api get-bucket-encryption --bucket kms-key-change-test
{
    "ServerSideEncryptionConfiguration": {
        "Rules": [
            {
                "ApplyServerSideEncryptionByDefault": {
                    "KMSMasterKeyID": "2afa832b-d531-40fe-ac8c-4e34a578939a", ★
                    "SSEAlgorithm": "aws:kms"
                }
            }
        ]
    }
}
S3のオブジェクトを Get/Put して BYOK した CMK で暗号化し直す
  • Get/Put して BYOK したキーで暗号化し直す
$ aws s3 cp s3://kms-key-change-test/test.txt ./
$ aws s3 cp test.txt s3://kms-key-change-test/
$ aws s3 cp s3://kms-key-change-test/test2.txt ./
$ aws s3 cp test2.txt s3://kms-key-change-test/
  • オブジェクト暗号化に使われているキーを確認する
$ aws s3api head-object --bucket kms-key-change-test --key test1.txt
{
    "AcceptRanges": "bytes",
    "ContentType": "text/plain",
    "LastModified": "Mon, 29 Oct 2018 08:37:32 GMT",
    "ContentLength": 5,
    "ETag": "\"f5b4a98e6bbdce444ebe6eaabbf5854b\"",
    "ServerSideEncryption": "aws:kms",
    "SSEKMSKeyId": "arn:aws:kms:ap-northeast-1:123456789012:key/2afa832b-d531-40fe-ac8c-4e34a578939a",
    "Metadata": {}
}
$ aws s3api head-object --bucket kms-key-change-test --key test1.txt
{
    "AcceptRanges": "bytes",
    "ContentType": "text/plain",
    "LastModified": "Mon, 29 Oct 2018 08:37:32 GMT",
    "ContentLength": 5,
    "ETag": "\"f5b4a98e6bbdce444ebe6eaabbf5854b\"",
    "ServerSideEncryption": "aws:kms",
    "SSEKMSKeyId": "arn:aws:kms:ap-northeast-1:123456789012:key/2afa832b-d531-40fe-ac8c-4e34a578939a",
    "Metadata": {}
}
古い CMK を無効化する
  • 古いキーを無効化する
$ aws kms  disable-key --key-id c3c1fb86-168d-40ca-9489-90cf2bd49dfa
  • 無効化されていることを確認する。
$ aws kms describe-key --key-id c3c1fb86-168d-40ca-9489-90cf2bd49dfa
{
    "KeyMetadata": {
        "Origin": "AWS_KMS",
        "KeyId": "c3c1fb86-168d-40ca-9489-90cf2bd49dfa",
        "Description": "",
        "KeyManager": "CUSTOMER",
        "Enabled": false, ★
        "KeyUsage": "ENCRYPT_DECRYPT",
        "KeyState": "Disabled",
        "CreationDate": 1540799362.916,
        "Arn": "arn:aws:kms:ap-northeast-1:123456789012:key/c3c1fb86-168d-40ca-9489-90cf2bd49dfa",
        "AWSAccountId": "123456789012"
    }
}
  • 新しいキーで暗号化し直したオブジェクトはダウンロードできる。
$ aws s3 cp s3://kms-key-change-test/test1.txt ./
download: s3://kms-key-change-test/test1.txt to ./test1.txt
  • 古い CMK で Put したオブジェクトはダウンロードできない。
$ aws s3 cp s3://kms-key-change-test/test3.txt ./
download failed: s3://kms-key-change-test/test3.txt to ./test3.txt An error occurred (KMS.DisabledException) when calling the GetObject operation: arn:aws:kms:ap-northeast-1: 123456789012:key/c3c1fb86-168d-40ca-9489-90cf2bd49dfa is disabled.
  • オブジェクトが暗号化されている CMK を確認する。
$ aws s3 ls --recursive s3://kms-key-change-test|perl -lane 'print $F[3]'|xargs -n1 aws s3api head-object --bucket kms-key-change-test --key|jq '.|@text "\(.SSEKMSKeyId)"'
"arn:aws:kms:ap-northeast-1:123456789012:key/2afa832b-d531-40fe-ac8c-4e34a578939a"
"arn:aws:kms:ap-northeast-1:123456789012:key/2afa832b-d531-40fe-ac8c-4e34a578939a"
"arn:aws:kms:ap-northeast-1:123456789012:key/c3c1fb86-168d-40ca-9489-90cf2bd49dfa"