DACエンジニアブログ:アドテクゑびす界

DACのエンジニアやマーケター、アナリストが執筆するアドテクの技術系ブログです。

AWS KMSを使って秘密鍵を管理する

本記事は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を利用して,あるデータを暗号化し,後に復号する際の流れを説明します。

  • データを暗号化したいとき
  1. AWS KMSでCMK(Master key)を作成します
  2. Data key作成APIを叩きます
  3. 平文Data key(Data key)と暗号化されたData key(Encrypted data key)が返ってきます
  4. 平文Data keyを使って暗号化したいデータ(Plaintext data)を暗号化します
  5. セキュリティのため平文Data keyを削除します
  6. 暗号化されたData keyと暗号化されたデータ(Encrypted data)を同一箇所で保存します
  • データを復号したいとき
  1. 復号APIを使って,暗号化されたData keyを平文Data keyに戻します
  2. 平文Data keyで暗号化されたデータを復号します
  3. セキュリティのため平文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を使った鍵の管理でした。