« ^ »

AWS KMSを使う

所要時間: 約 2分

鍵の管理するためのAWSのサービスにKMSがある。これを使用すると、鍵自体を自分で保持する事なく、必要な情報を暗号化/復号化できる。AWS KMSを使用した際に調べた事を記録しておく。

boto3で暗号化する

boto3でKMSの暗号化を使うためには以下のようにする。

import boto3
import base64

plain_text: str = "yay"

boto3_session = boto3.Session()
kms_client = boto3_session.client('kms')
resp = kms_client.encrypt(
    KeyId="11111111-2222-3333-4444-555555555555",
    Plaintext=plain_text,
)
cipher_blob: bytes = resp["CiphertextBlob"]
cipher_b64: bytes = base64.b64encode(cipher_blob)
cipher_text: str = cipher_b64.decode()

return cipher_text

気を付ける点としては、返されるデータはバイト列になっているため、文字列として取り扱うためにはbase64でエンコードしたり、decode()して文字列化したりする必要がある。

local開発用のAWS KMS local-kmsを使う

local-kmsはAmazon KMSのダミーサーバーで、local-kmsへ問い合わせるようにすることでAmazon KMSに問い合わせることなく開発が進められる。KMS自体の料金は高くないからあまり使う事はないかもしれないが、CIでのテストなどでは使用してもよいかもしれない。以下では、local-kmsの使い方をまとめる。

local-kmsのDocker Imageをダウンロードする。

docker pull nsmithuk/local-kms

dockerを用いてlocal-kmsを起動する。

docker run -p 8080:8080 -e REGION=ap-northeast-1 nsmithuk/local-kms

KeyIdを発行する。

POST http://localhost:8080/
X-Amz-Target: TrentService.CreateKey
Content-Type: application/json; charset=utf-8

{}
{
  "KeyMetadata": {
    "AWSAccountId": "111122223333",
    "Arn": "arn:aws:kms:ap-northeast-1:111122223333:key/834140e8-e12f-4047-a723-8261bd21c171",
    "CreationDate": 1557292212,
    "Enabled": true,
    "KeyId": "834140e8-e12f-4047-a723-8261bd21c171",
    "KeyManager": "CUSTOMER",
    "KeyState": "Enabled",
    "KeyUsage": "ENCRYPT_DECRYPT",
    "Origin": "AWS_KMS"
  }
}
// POST http://localhost:8080/
// HTTP/1.1 200 OK
// Content-Type: application/x-amz-json-1.1
// Date: Wed, 08 May 2019 05:10:12 GMT
// Content-Length: 317
// Request duration: 0.021481s

利用するkeyを登録する。Plaintextにはbase64でエンコードした値を設定する。

POST http://localhost:8080/
Content-Type: application/json
X-Amz-Target: TrentService.Encrypt

{
  "KeyId": "834140e8-e12f-4047-a723-8261bd21c171",
  "Plaintext": "dGVzdA=="
}
{
  "KeyId": "arn:aws:kms:ap-northeast-1:111122223333:key/834140e8-e12f-4047-a723-8261bd21c171",
  "CiphertextBlob": "UGFybjphd3M6a21zOmFwLW5vcnRoZWFzdC0xOjExMTEyMjIyMzMzMzprZXkvODM0MTQwZTgtZTEyZi00MDQ3LWE3MjMtODI2MWJkMjFjMTcxAAAAAEb30YwGZIgUXvTlNpB3LLXl544WZucO+LzvlE3jgDCT"
}
// POST http://localhost:8080/
// HTTP/1.1 200 OK
// Content-Type: application/x-amz-json-1.1
// Date: Wed, 08 May 2019 05:31:03 GMT
// Content-Length: 268
// Request duration: 0.015830s

ここで取得したCiphertextBlobを使って実際にboto3.clientから鍵を取り出してみる。

環境変数にリージョンを設定する。この環境変数はboto3が参照する。

(setenv "AWS_DEFAULT_REGION" "ap-northeast-1")

boto3.clientを使って鍵を取り出す。endpoint_urlにはlocal-kmsのURLを指定する。CiphertextBlobは先程鍵を保存したときのレスポンスのCiphertextBlobの値です。この値はbase64でエンコードされているので、その値をデコードしてclient.decryptメソッドに渡す。

import base64
import boto3
client = boto3.client('kms', endpoint_url='http://127.0.0.1:8080')
res = client.decrypt(CiphertextBlob=base64.b64decode(
    b"UGFybjphd3M6a21zOmFwLW5vcnRoZWFzdC0xOjExMTEyMjIyMzMzMzprZXkvODM0MTQwZTgtZTEyZi00MDQ3LWE3MjMtODI2MWJkMjFjMTcxAAAAAEb30YwGZIgUXvTlNpB3LLXl544WZucO+LzvlE3jgDCT"
    ))

return res  # for org-babel results
{'KeyId': 'arn:aws:kms:ap-northeast-1:111122223333:key/834140e8-e12f-4047-a723-8261bd21c171', 'Plaintext': b'test', 'ResponseMetadata': {'HTTPStatusCode': 200, 'HTTPHeaders': {'content-type': 'application/x-amz-json-1.1', 'date': 'Wed, 08 May 2019 05:31:32 GMT', 'content-length': '115'}, 'RetryAttempts': 0}}

Plaintextに test というバイト列が返される事が確認できた。