AWS CLIからKey Management Service(KMS)の暗号処理を使ってみる

aws_logo
Amazon AWS が最近発表した Key Management Service(KMS) は暗号の鍵管理を AWS が面倒を見てくれる。
この機能を使って

  • KMS の鍵だけを利用した暗号/復号
  • KMS と連携した S3 オブジェクトの暗号/復号

を AWS CLI から操作してみる。

鍵の作成

まずはマニュアルに従い、鍵を作成する。

http://docs.aws.amazon.com/kms/latest/developerguide/getting-started.html

作成した鍵は $ aws kms list-keys で確認できる。

KMS Envelope Encryption

次に KMS から鍵だけを借りてデータを暗号・復号する

処理の流れは次のページが詳しい

AWS KMS Workflow with Supported AWS Services
http://docs.aws.amazon.com/kms/latest/developerguide/workflow.html

暗号化の際には master key から

  • data key
  • 暗号化された data key

を生成

Workflow_EnvelopeEncryption

data key を使ってデータを暗号化。data key はすぐに破棄。

Workflow_EncryptingContent

復号化の際には暗号化された data key を master key で復号。

Workflow_DecryptingContentPt1

暗号化されたデータを data key で復号

Workflow_DecryptingContentPt2

この暗号の流れを AWS は Envelope Encryption と呼んでいるけれども、 digital envelop などとも呼んだりするみたい。

data encryption

まずは暗号化するデータを作成。

$ echo ママに最高の「ありがとう」を。娘に最高の「愛してる」を。 | base64 | tee plaintext
44Oe44Oe44Gr5pyA6auY44Gu44CM44GC44KK44GM44Go44GG44CN44KS44CC5aiY44Gr5pyA6auY
44Gu44CM5oSb44GX44Gm44KL44CN44KS44CCCg==

サーバに渡す plaintext は base64 されていることを期待しているらしく(ドキュメントで記述を見つけられなかったけど、、、)$ echo hello world > plaintext として実際に暗号・復号すると、復号後 hello/world/ などと暗号前とことなる文字列になってしまう。

次にデータを暗号化する。

API

$ aws kms encrypt --key-id master-key-id --plaintext file://path/to/plaintext

とする。

$ aws kms encrypt --key-id "arn:aws:kms:ap-northeast-1:1234567890:key/asdfasdf" --plaintext file://plaintext
{
  "KeyId": "arn:aws:kms:ap-northeast-1:1234567890:key/asdfasdf",
  "CiphertextBlob": "CiB0uyGNphikevAQ7DzGGBQW9WRls1O9hmNcqoLSOO8i5xLgAQEBAgB4dLshjaYYpHrwEOw8xhgUFvVkZbNTvYZjXKqC0jjvIucAAAC3MIG0BgkqhkiG9w0BBwaggaYwgaMCAQAwgZ0GCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMQsK5+T1bqmW9xgmvAgEQgHAktxBw10f+nez7J8BYcztE3+25S8r8G82BC4DVrMECkhlUeONqvMC3BowvlBwg1Ig2fBYrmFJStp+3/y7sJw155M6+dynIrHKEjyKx674byj3DBAiRayva7GflCAn6+LCh8kjRfnsajDpvinrA99nM"
}

レスポンスには

  • master key
  • ciphertext

が返ってくる。

ciphertext だけを ciphertext というファイルに保存する。

$ aws kms encrypt --key-id "arn:aws:kms:ap-northeast-1:1234567890:key/asdfasdf" --plaintext file://plaintext | jq .CiphertextBlob | tr -d '"' | tee ciphertext
CiB0uyGNphikevAQ7DzGGBQW9WRls1O9hmNcqoLSOO8i5xLgAQEBAgB4dLshjaYYpHrwEOw8xhgUFvVkZbNTvYZjXKqC0jjvIucAAAC3MIG0BgkqhkiG9w0BBwaggaYwgaMCAQAwgZ0GCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM/0r+vUUN1xXPxcoKAgEQgHA92jE/tQFdQI9hYGRnPJg/tvj4EMuh9JgasUGvSVfJhzrUxWXxpxSmvm+QIXz5LEPBCPH6jNetF9MXPe55pLDTsTfKmK2SG34urtVxtovftQhWkbaOk3XqtNvnmDGsPeoJkQjx4XmEw5Gm5OzF0o8a

data decryption

次にデータを復号化する。

API

$ aws kms decrypt --ciphertext-blob file://path/to/ciphertext

とする。

$ aws kms decrypt --ciphertext-blob file://ciphertext
{
  "Plaintext": "44Oe44Oe44Gr5pyA6auY44Gu44CM44GC44KK44GM44Go44GG44CN44KS44CC5aiY44Gr5pyA6auY44Gu44CM5oSb44GX44Gm44KL44CN44KS44CCCg==",
  "KeyId": "arn:aws:kms:ap-northeast-1:1234567890:key/asdfasdf"
}

レスポンスには

  • master key
  • plaintext

が返ってくる。

plaintext だけを抽出して base64 デコードするとものとデータを復元できる。

$ aws kms decrypt --ciphertext-blob file://ciphertext | jq .Plaintext | tr -d '"' | base64 -d
ママに最高の「ありがとう」を。娘に最高の「愛してる」を。

MEMO

API には

などがあるので、暗号化処理の過程でこれら API も内部的に呼び出しているものと思われる。

また、plaintext は base64 エンコードした状態で 4096 バイト以下でなければいけない。

$ aws kms encrypt --key-id "arn:aws:kms:ap-northeast-1:1234567890:key/asdfasdf" --plaintext fileb://large-plaintext-data

A client error (ValidationException) occurred when calling the Encrypt operation: 1 validation error detected: Value at 'plaintext' failed to satisfy constraint: Member must have length less than or equal to 4096

KMS S3 Encryption

次に KMS と AWS のマネージドサービスを連携させる。
確認しやすいということで S3 と連携してみる。
2011年から存在する server side encryption(SSE-S3) では、鍵の管理を AWS が完全に握っていた。

Protecting Data Using Server-Side Encryption with Amazon S3-Managed Encryption Keys (SSE-S3)
http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingServerSideEncryption.html

KMS 版(SSE-KMS)では AWS にアカウントに紐付いた鍵で暗号処理が行われる。

詳細は次のドキュメントを参照

AWS Documentation ≫ AWS KMS ≫ Developer Guide ≫ How AWS Services use AWS KMS ≫ Amazon Simple Storage Service
http://docs.aws.amazon.com/kms/latest/developerguide/services-s3.html

テスト用バケットの作成

$ aws s3 mb s3://z51460a9
make_bucket: s3://z51460a9/

テストデータの作成

$ echo ホルモン > test.txt

S3 オブジェクトの put

--server-side-encryption で暗号方式(今回は aws:kms)を指定する

$ aws s3api put-object --bucket z51460a9 --key test.txt --server-side-encryption aws:kms --body test.txt

A client error (InvalidArgument) occurred when calling the PutObject operation: Requests specifying Server Side Encryption with AWS KMS managed keys require AWS Signature Version 4.

aws cli の kms のトップページに書かれているように “All KMS operations require Signature Version 4 .” らしいので S3 サービスで Signature Version 4 を有効にする。

$ aws configure set default.s3.signature_version s3v4
$ aws configure get  default.s3.signature_version
s3v4
$ cat ~/.aws/config
[default]
region = ap-northeast-1
aws_access_key_id = 00000000000000000000
aws_secret_access_key = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/xxxxxxxxx
s3 =
    signature_version = s3v4

この状態で再チャレンジ

$ aws s3api put-object --bucket z51460a9 --key test.txt --server-side-encryption aws:kms --body test.txt
{
    "SSEKMSKeyId": "arn:aws:kms:ap-northeast-1:1234567890:key/84d37fcc-c023-4377-99dc-57d44798ooii",
    "ETag": "\"e1fb53aad86906937fa0821d240b6183\"",
    "ServerSideEncryption": "aws:kms"
}
$ aws s3api head-object --bucket z51460a9 --key test.txt
{
    "AcceptRanges": "bytes",
    "ContentType": "binary/octet-stream",
    "LastModified": "Sun, 23 Nov 2014 16:17:43 GMT",
    "ContentLength": 13,
    "ETag": "\"e1fb53aad86906937fa0821d240b6183\"",
    "ServerSideEncryption": "aws:kms",
    "SSEKMSKeyId": "arn:aws:kms:ap-northeast-1:1234567890:key/84d37fcc-c023-4377-99dc-57d44798ooii",
    "Metadata": {}
}

S3 への PUT に成功
HEAD から “ServerSideEncryption”“SSEKMSKeyId” といった SSE-kms 固有の情報を確認できる。

S3 PUT 時に鍵を指定せずに暗号化されている。
レスポンスで帰ってきた key-id をマネージメントコンソールから確認するとわかるように、鍵作成時にデフォルトで追加される S3 用の鍵が使われている。

$ aws kms describe-key --key-id 84d37fcc-c023-4377-99dc-57d44798ooii
{
    "KeyMetadata": {
        "KeyId": "84d37fcc-c023-4377-99dc-57d44798ooii",
        "Description": "Default master key that protects my S3 objects when no other key is defined",
        "Enabled": true,
        "KeyUsage": "ENCRYPT_DECRYPT",
        "CreationDate": 1416499734.879,
        "Arn": "arn:aws:kms:ap-northeast-1:1234567890:key/84d37fcc-c023-4377-99dc-57d44798ooii",
        "AWSAccountId": "1234567890"
    }
}

S3 オブジェクトの get

GET の時は特に考えなくて良い。

$ aws s3api get-object --bucket z51460a9 --key test.txt test.out.txt
{
    "AcceptRanges": "bytes",
    "ContentType": "binary/octet-stream",
    "LastModified": "Sun, 23 Nov 2014 16:17:43 GMT",
    "ContentLength": 13,
    "ETag": "\"e1fb53aad86906937fa0821d240b6183\"",
    "ServerSideEncryption": "aws:kms",
    "SSEKMSKeyId": "arn:aws:kms:ap-northeast-1:1234567890:key/84d37fcc-c023-4377-99dc-57d44798ooii",
    "Metadata": {}
}
$ md5sum test.*txt
61d11243f45d81d5bbf07e783a4d9cb0  test.out.txt
61d11243f45d81d5bbf07e783a4d9cb0  test.txt

S3 デフォルトと異なる鍵を指定

--ssekms-key-id 引数で S3 デフォルトと異なる鍵を指定することも可能。

$ aws s3api put-object --bucket z51460a9 --key foo.txt --server-side-encryption aws:kms --ssekms-key-id "10ff108a-zxcv-4ce1-a2a1-5a2751213d8b" --body foo.txt
{
    "SSEKMSKeyId": "arn:aws:kms:ap-northeast-1:1234567890:key/10ff108a-zxcv-4ce1-a2a1-5a2751213d8b",
    "ETag": "\"e5477a951e94ab295ca380c6b5ffe31d\"",
    "ServerSideEncryption": "aws:kms"
}

MEMO

aws s3api のハイレベル API である aws s3 に関していうと

  • PUT 操作に関してはサーバサイド暗号は sse-s3 しか指定できず sse-kms を指定するオプションがまだ用意されておらず
  • GET 操作に関しても、ETAG の計算で自爆してダウンロードに失敗する(こっちは 1,2週間程度で直してくれそう)
Advertisements
Tagged with: , , ,
Posted in aws

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Archives
  • RT @__apf__: How to write a research paper: a guide for software engineers & practitioners. docs.google.com/presentation/d… /cc @inwyrd 4 months ago
  • RT @HayatoChiba: 昔、自然と対話しながら数学に打ち込んだら何かを悟れるのではと思いたち、専門書1つだけ持ってパワースポットで名高い奈良の山奥に1週間籠ったことがある。しかし泊まった民宿にドカベンが全巻揃っていたため、水島新司と対話しただけで1週間過ぎた。 それ… 5 months ago
  • RT @googlecloud: Ever wonder what underwater fiber optic internet cables look like? Look no further than this deep dive w/ @NatAndLo: https… 5 months ago
  • @ijin UTC+01:00 な時間帯で生活しています、、、 10 months ago
  • RT @mattcutts: Google's world-class Site Reliability Engineering team wrote a new book: amazon.com/Site-Reliabili… It's about managing produc… 1 year ago
%d bloggers like this: