本記事は2017年3月1日時点での情報です。正確かつ最新の情報は公式ドキュメントをご参照ください。
はじめに
秘密鍵,APIトークン,パスワードなどはたとえ社内公開・プライベートであってもGitリポジトリに含めたくない情報です。では,どのように管理すればよいでしょうか? 少し前の本ブログの記事 でもAWSのKey管理に 1.環境変数に設定する, 2. .aws/credentials にもたせておく, 3. コードに直接もたせる という3つの方法が提示されていました。しかし環境変数に設定する場合やGit管理していない外部ファイルで管理する場合,以下のような可能性があります。
- バージョン管理されていないので変更に気づけない
- 誤って鍵を保存している環境変数やファイルを削除してしまう
- 開発者個人の環境に鍵が残ってしまう
こうした問題に対応するためAudienceOne開発チームではAWS Key Management Service (KMS)を利用しています。AWS KMSを利用することで,暗号化した鍵をGitリポジトリに保存し,バージョン管理が可能になります。またAWS KMSなら誤ってマスターキーを削除してしまうこともありません。またKMS APIの利用範囲はAWS IAMでポリシーを設定でき,APIの利用履歴も残ります。
本記事ではAWS KMSの概要と,その利用手順を記述します。
AWS KMSを使った暗号化/復号のおおまかな流れ
概念については公式ドキュメントを参考にしてください。 AWS Key Management Service の概念 (日本語): https://docs.aws.amazon.com/ja_jp/kms/latest/developerguide/concepts.html
上記の概念を踏まえ,AWS KMSを利用して,あるデータを暗号化し,後に復号する際の流れを説明します。
- データを暗号化したいとき
- AWS KMSでCMK(Master key)を作成します
- Data key作成APIを叩きます
- 平文Data key(Data key)と暗号化されたData key(Encrypted data key)が返ってきます
- 平文Data keyを使って暗号化したいデータ(Plaintext data)を暗号化します
- セキュリティのため平文Data keyを削除します
- 暗号化されたData keyと暗号化されたデータ(Encrypted data)を同一箇所で保存します
- データを復号したいとき
- 復号APIを使って,暗号化されたData keyを平文Data keyに戻します
- 平文Data keyで暗号化されたデータを復号します
- セキュリティのため平文Data keyを削除します
AWS CLIを使ったKMS利用手順例
AWS CLIを使ってデータの暗号化と復号の手順です。
CMKを作成する
出典 : http://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html
- aws consoleで IAM > 暗号化キー > キーの作成 を選択します。
- 手順に従い,何の鍵なのかをわかるようエイリアスと説明をつけ,鍵を管理できる&鍵で暗号化/復号できるIAMユーザー(orロール)を決め,CMKを作成します。
IAMユーザー(orロール)のポリシーを設定する
AWSKeyManagementServicePowerUser
などKMSの諸権限のポリシーをIAMユーザー(orロール)に設定します。aws kms list-keys
で作成したCMK一覧を取得できます。
$ aws kms list-keys
{
"Keys": [
{
"KeyArn": "arn:aws:kms:ap-northeast-1:1234567890xx:key/6381b92f-8ed4-49c1-bd11-abcdef123456",
"KeyId": "6381b92f-8ed4-49c1-bd11-abcdef123456"
}
]
}
データを暗号化する
- 暗号化したいデータを準備します。 今回は
data.txt
というファイルを暗号化したいと思います。
$ cat data.txt
デジタルは、人の想いでできている。
DAC 20th Anniversary
- 先程作成したCMKを使って,DataKeyを作成します。
$ aws kms generate-data-key --key-id arn:aws:kms:ap-northeast-1:1234567890xx:key/6381b92f-8ed4-49c1-bd11-abcdef123456 --key-spec AES_256
{
"Plaintext": "iwkcuXR2jtPT6VrdUZAscH00eDIBpqMKj4vmNbKAjB4=",
"KeyId": "arn:aws:kms:ap-northeast-1:1234567890xx:key/6381b92f-8ed4-49c1-bd11-abcdef123456",
"CiphertextBlob": "AQEDAHgvZ9Hbx0qkls0OseOHSkwGc2Luwrz/v/pJR8y7rvj0LAAAAH4wfAYJKoZIhvcNAQcGoG8wbQIBADBoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDDsRgW7Ft6qdN0wFHAIBEIA7xDn8t7b72tszYyI//PddKE+XUULLk8o1blJ3wqHK+f3BJK1B1S5Er1U3dnAUFRSSdCfFCPzQPaCXOsg="
}
Plaintext
は平文DataKeyです。データを暗号化するのに使用します。CiphertextBlob
は暗号化されたDataKeyです。Plaintext
をファイルに保存します。
$ echo iwkcuXR2jtPT6VrdUZAscH00eDIBpqMKj4vmNbKAjB4= > plaintext-data-key
encrypted-data-key
はCMKがなければ復号できないので,Gitリポジトリで管理しても問題ありません。CiphertextBlob
はbase64でデコードしてからファイルに保存しておきます。
$ echo AQEDAHgvZ9Hbx0qkls0OseOHSkwGc2Luwrz/v/pJR8y7rvj0LAAAAH4wfAYJKoZIhvcNAQcGoG8wbQIBADBoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDDsRgW7Ft6qdN0wFHAIBEIA7xDn8t7b72tszYyI//PddKE+XUULLk8o1blJ3wqHK+f3BJK1B1S5Er1U3dnAUFRSSdCfFCPzQPaCXOsg= | base64 -d > encrypted-data-key
plaintext-data-key
を使ってデータを暗号化します。- 暗号化したデータは,ファイルやDBなど用途に応じて好きな場所に保存してください。ここでは
encrypted-data.txt
に保存することとします。
$ openssl aes-256-cbc -e -in data.txt -out encrypted-data.txt -pass file:plaintext-data-key
$ cat encrypted-data.txt
Salted__:ק?H?*ݡ??????f??Ln???yP?飱??PZ?s?6I?u?ƨ3缄?
a|k??-
?x?rS/??5?????WӵlI?N)
- 【重要】 データの暗号化ができたら,
plaintext-data-key
は必要ないので必ず削除しておきましょう。 data.txt
も不要になったら削除しておきます。
$ rm plaintext-data-key data.txt
データを復号する
- CMKと暗号化されたDataKeyを使って,平文DataKeyを取得します。
plaintext-data-key
と一致することがわかります。
$ aws kms decrypt --ciphertext-blob fileb://encrypted-data-key --query Plaintext --output text > decrypted-data-key
$ cat decrypted-data-key
iwkcuXR2jtPT6VrdUZAscH00eDIBpqMKj4vmNbKAjB4=
- この平文DataKeyを使ってデータの復号を行いましょう。
data.txt
と一致することがわかります。
$ openssl aes-256-cbc -d -in encrypted-data.txt -pass file:decrypted-data-key
デジタルは、人の想いでできている。
DAC 20th Anniversary
- 【重要】 データの復号ができたら,必ず
decrypted-data-key
を削除しておきましょう。
$ rm decrypted-data-key
Node.js AWS SDKを使って復号する
- 復号のサンプルコード(JavaScript)です。
- 復号した平文Data Keyをファイルに書き出す,ということはしていません。
npm install aws-sdk crypto-js
const AWS = require('aws-sdk');
const fs = require('fs');
const CryptoJS = require('crypto-js');
// API versionとregionを指定してKMSのインスタンスを作成する
const kms = new AWS.KMS({apiVersion: '2014-11-01', region: 'ap-northeast-1'});
// 暗号化されたデータを読み込む
const encryptedData = fs.readFileSync('encrypted-data.txt', 'base64');
// ファイルから暗号化されたData keyを取得する
const encryptedDataKey = fs.readFileSync('encrypted-data-key', 'base64');
const ciphertextBlob = new Buffer(encryptedDataKey, 'base64');
const params = {
CiphertextBlob: ciphertextBlob
};
// 暗号化されたData keyを復号する
kms.decrypt(params, (err, data) => {
if (err) {
console.log(err, err.stack);
} else {
// 復号されたData Key
const decryptedDataKey = data.Plaintext.toString('base64');
// 平文Data keyでデータを復号
const decryptedData = CryptoJS.AES.decrypt(encryptedData.toString(), decryptedDataKey).toString(CryptoJS.enc.Utf8);
// 復号されたデータを出力
console.log(decryptedData);
}
});
$ node decrypt-data.js
デジタルは、人の想いでできている。
DAC 20th Anniversary
もとのデータに復号できたことを確認しました。
まとめ
以上,AWS KMSを使った鍵の管理でした。