はじめに
フューチャーの棚井龍之介です。
認証情報を Lambda の環境変数に渡す要件が発生し、
- Lambda は環境変数を含めて Terraform 管理配下にある
- コードは全て GitHub で履歴管理している
- 生の認証情報はリポジトリに Push すべきでない
となったため、認証情報を KMS で暗号化して、リポジトリには暗号化した値を登録し、Lambda 内で復号化する構成を取りました。
認証情報のコード管理について、Terraform 作業とローカル作業を組み合わせて対応できたため、備忘録も兼ねて手順をブログ化しました。
KMS とは
公式: AWS Key Management Service (KMS)
AWS の提供する、データの暗号化・復号化サービスです。共通鍵暗号の仕組みを使い、データベースの接続キーや認証情報の暗号化・復号化機能を提供します。他サービスと組み合わせることにより、KMS でアクセスキーで暗号化して、EC2 から RDS への接続時にのみ復号化する、といった柔軟な対応も可能です。
KMS の仕組み自体は、Classmethod さんの書かれた「10分でわかる!Key Management Serviceの仕組み」が詳しいのです。
Terraform とは
公式: Terraform
HashiCorp 社により開発されている、OSS のクラウド管理ツールです。AWS や GCP などのクラウドサービスに対して、リソースの作成・削除や、各種パラメータの調整機能をコードベースで提供します。オペレーターになどよる GUI 操作や AWS CLI コマンド操作を排除し、インフラリソース管理を Terraform に一本集中することで、煩雑なリソース管理作業を簡略化できます。
Future の技術ブログでは、Terraform 関連の投稿がありますので、こちらも合わせてご覧ください。
Terraform やってみたいという方は、以下の記事がオススメです。
本記事の流れ
KMS の暗号化・復号化操作を、以下の流れで説明します。
- Terraform で KMS マスタキーの生成
- AWS CLI で暗号化・復号化
- Lambda で KMS 操作
また、本記事では一部 Terraform による操作を前提としていますが、基本的な Terraform 操作の説明は省略しています。
Terraform で KMS マスタキーの生成
Terraform で KMS リソースを作成します。
KMS マスタキーの定義だけでなく、エイリアスも同時に定義します。
マスタキーの値は 1234abcd-12ab-34cd-56ef-1234567890ab
のような値であり非常に判別しづらいため、別名(エイリアス)として alias/demo-alias
のように任意の識別名を付与します。
マスタキーの値と Alias の関係は マスタキー : Alias = 1 : n なので、1つのマスタキーには複数の Alias が設定可能です。逆に、1つの Alias を複数のマスタキーに紐づけることはできません。
公式: エイリアスの使用
resource "aws_kms_key" "demo" { |
Terraform 定義パラメータ
リソース定義を追加後、$ terraform plan/apply
により KMS マスタキーと Alias を作成します。
AWS CLI で暗号化・復号化
作成した Alias を用いて、テキスト情報の暗号化・復号化作業を実施してみます。
暗号化作業で AliasArn
の値を使うため、環境変数 $KEYID に登録します。
# KEYID に登録 |
暗号化
ローカルに PlaintextFile
の名前でファイルを生成して、認証情報の平文を保存します。
$ vim PlaintextFile |
続いて、AWS CLI コマンドにより PlaintextFileの中身(=平文)
を暗号化します。
コマンド実行後、KMS により暗号化された認証情報が CiphertextBlob
として取得できます。CiphertextBlob の実態は、認証情報を暗号化して Base64 エンコードした値です。
$ aws kms encrypt \ |
以上で「平文を暗号化して、暗号文を取得するまで」が完了です。
復号化
暗号文 CiphertextBlob
の値を復号化してみましょう。
先ほどの操作で生成した暗号文 CiphertextBlob
を、CiphertextFile
に保存します。
$ aws kms encrypt \ |
復号化コマンドを実行すると、最初に暗号化した平文が取得できます。
暗号文自体に KEYID の情報が格納されているので、復号化のコマンドには --key-id $KEYID
の指定が不要です。
$ aws kms decrypt \ |
以上で「暗号文の復号化」が完了しました。
Lambda で KMS 操作
KMS で生成した暗号文を、Lambda の中で復号化します。
先ほどの暗号化作業で作成した CiphertextBlob
の値を、Lambda 内で復号化します。
KMS の復号化には kms:Decrypt
のポリシーが必須なので、demo 用の Lambda に以下のインラインポリシーを追加します。
{ |
Terraformでのlambdaのリソース構築設定にkms_key_arn
を追記することで、lambdaはデフォルトのAWS KMSキーではなく作成したKMSのキーを利用するようになります。
resource "aws_lambda_function" "kms_lambda" { |
手動で設定を行う場合は環境変数の設定から暗号化設定を有効化します。
Lambda で復号化
以下のコードを Lambda にデプロイして、復号化結果を取得してみます。encryptedKey
には、CiphertextBlob
の値を直接代入しています。
package main |
コマンドで動作確認
invoke を実行して、関数のレスポンスを取得
$ aws lambda invoke \ |
暗号化されていた CiphertextBlob
の値が、正しく復号化されたことを確認できました。
まとめ
本記事では、KMS のマスタキー生成を Terraform で行い、暗号化は AWS CLI で手動実施するというハイブリッド方式をご紹介しました。
CiphertextBlob
の値は KMS で暗号化済みのため、Terraform やアプリケーションコードに直接追記しても問題ありません(Lambdaで利用するならば、ハードコードではなく環境変数に追記すべきですが)。GitHub 管理するコード上には暗号文のまま登録して、呼び出し先で復号化する機能配置ならば、生の認証情報がリポジトリに残らないようにできます。
以上、長文にお付き合いいただき、ありがとうございました。