[PR] あなたが Kindle で読みたいその本、Kindle に対応したら Twitter でお知らせします。

AWS CLI と KMS を使って機密ファイルを暗号化する

Posted on

AWS Key Management Service (KMS) は暗号化キーを簡単に作成・管理できるマネージド型サービスですが、これまでは EBS や RDS のように AWS サービスに統合された用途でしか使ったことがありませんでした。

今回は機密ファイルの耐タンパー性を確保するために KMS を使ってファイルを暗号化してみます。

検証なので次のようなプレーンテキストを暗号化してみます。

$ echo 'Hello, world!' > plaintext-file.txt
$ cat plaintext-file.txt
Hello, world!

AWS CLI で暗号化する

まず KMS のマスターキーのエイリアス名を確認します。 alias/aws/* は AWS サービスに統合されたキーで、alias/test_key が検証用に作ったマスターキーです。

$ aws kms list-aliases --query 'Aliases[].AliasName'
[
    "alias/aws/acm",
    "alias/aws/ebs",
    "alias/aws/rds",
    "alias/aws/redshift",
    "alias/aws/s3",
    "alias/test_key"
]

次にマスターキーからデータキーを生成します。マスターキーで直接暗号化できるのは 4 KiB 以下です。それ以上のファイルを暗号化するときは、マスターキーから生成したデータキーを使う必要があります。

plaintext-file.txt はマスターキーで暗号化できますが、実践では 4 KiB 以上のファイルを扱うこともあるのでデータキーを生成してみます。

$ aws kms generate-data-key --key-id alias/test_key --key-spec AES_256 --query 'KeyId' --output text
arn:aws:kms:ap-northeast-1:xxxxxxxxxxxx:key/6544487d-xxxx-xxxx-xxxx-dd3a29d6dc19

KMS のキーは ARN 形式になっています。

生成したデータキーを使って plaintext-file.txt を暗号化します。 AWS CLI のドキュメントにも書いていますが、ファイルは fileb:// スキーマでバイナリデータとして渡して、ファイルに書き出す前に base64 でデコードする必要があります。

$ aws kms encrypt \
--key-id arn:aws:kms:ap-northeast-1:xxxxxxxxxxxx:key/6544487d-xxxx-xxxx-xxxx-dd3a29d6dc19 \
--plaintext fileb://plaintext-file.txt \
--query CiphertextBlob --output text | \
base64 --decode > encrypted-file.txt

encrypted-file.txt が暗号化されたファイルで、中身はバイナリになっています。

AWS CLI で復号する

ファイルを暗号化できたので、今度はちゃんと復号できるか確認してみます。

$ aws kms decrypt --ciphertext-blob fileb://encrypted-file.txt --query Plaintext --output text | base64 --decode
Hello, world!

プレーンテキストの Hello, world! が取り出せました!

ちなみに、復号するときは --key-id オプションは不要です。 --query オプションを省略すればわかりますが、ファイルの中にどのキーを使って暗号化されたか記録されています。

$ aws kms decrypt --ciphertext-blob fileb://encrypted-file.txt
{
    "Plaintext": "SGVsbG8sIHdvcmxkIQo=",
    "KeyId": "arn:aws:kms:ap-northeast-1:xxxxxxxxxxxx:key/6544487d-xxxx-xxxx-xxxx-dd3a29d6dc19"
}

当然ですが、KMS の権限が割り当てられていない IAM ユーザー / ロールでは次のようなエラーになり復号できません。

An error occurred (AccessDeniedException) when calling the Decrypt operation: The ciphertext refers to a customer master key that does not exist, does not exist in this region, or you are not allowed to access.

追記: AWS SDK for Ruby で復号する

ついでに AWS SDK for Ruby で復号するコードも検証しました。非常に短いコードで復号できます。

require 'aws-sdk'

kms = Aws::KMS::Client.new(region: 'ap-northeast-1')

file = IO.read(ARGV[0])
res = kms.decrypt({
  ciphertext_blob: file
})

p res.plaintext
$ ruby decrypt.rb encrypted-file.txt
"Hello, world!\n"

AWS CLI と同じように Hello, world! が取り出せました。あらかじめ AWS CLI で暗号化して、それをアプリケーション側で復号することも簡単にできますね。

まとめ

KMS を使うと機密ファイルも簡単に暗号化できることがわかりました。思っていたよりも簡単に扱えるので、高いセキュリティが求められる場面では積極的に使っていこうと思います。