タダです.
プログラムで使うトークンや DB 接続情報,鍵情報といった秘匿情報を Secrets Manager に入れています.Secrets Manager に保管してる情報を Terraform で管理しようとした時コードで直書きし,GitHub などで管理するのはリスキーなので別の方法を探していた時に以下のブログを見つけ,参照しつつ試したことをこの記事にまとめていきます.
ブログで紹介されていた秘匿情報の取り扱い方法
冒頭のブログで紹介されていた方法として以下の3つがあります.
- 変数にして外出しする
- ファイルを暗号化してバージョン管理する
- Secrets Manager や Hashicorp Vault などに格納する
一つ目は毎回任意のコマンドを打てる環境ならいいのですが,自動デプロイ を仕組んでいる場合にその運用コストが高そうだなと思ったのと,三つ目は現状やっていることでやりたいことに当たらなかったので,二つ目の手法を使ってアプローチを試みることにしました.
大まかな作業の流れ
二つ目の手法の大まかな流れとして,まず Secrets Manager で扱う情報群を YAML ファイルに書き出します.その後,YAML ファイルを KMS を使って暗号化し,そのファイルを Terraform のコードで復号化 -> パラメーターごとにマッピングするといった作業を行います.
秘匿情報を格納する YAML ファイルの作成
secrets.yaml
というファイルを作成し,その中に Secrets Manager に格納したい キー:バリュー
の順番で転記します.そして,secrets.yaml
はリポジトリで管理しないように .gitignore
で除外しておきます.
hoge_token: hogehoge dbhost: hoge.cluster-xxxx.ap-northeast-1.rds.amazonaws.com dbhost_replica: hogecluster-ro-xxxx.ap-northeast-1.rds.amazonaws.com dbname: hogedb password: hogehoge username: hoge
KMS での暗号化処理
次に,KMS で secrets.yaml
を暗号化します.AWS CLI で次のようなコマンドを実行して secrets.yaml.encrypted
が生成されることを確認します.また,このファイルはリポジトリで管理するようにします.
aws kms encrypt \ --key-id xxxx-xxxx-xxxx-xxxx-xxxx(個別に発行した CMK) \ --region ap-northeast-1 \ --plaintext fileb://secrets.yaml \ --output text \ --query CiphertextBlob \ > secrets.yaml.encrypted
なお,生成された secrets.yaml.encrypted
の中身は見てもらうとわかりますが,全然何が書いているか当然わからないようになっています.
Terraform での復号化と秘匿情報のマッピング
secrets.yaml.encrypted
の生成が終わったら Terraform のコードを書いていきます.復号化の処理は data.aws_kms_secrets
とyamldecode(data.aws_kms_secrets.secrets.plaintext["secrets"])
で行います. hoge_secrets
の中に復号化した秘匿情報が入っているのですが,そのデータを aws_secretsmanager_secret_version
の secret_string
でマッピングしていきます.local.hoge_secrets.[YAML ファイルで定義したキー]
といった具合です.
コード例
data "aws_kms_secrets" "secrets" { secret { name = "secrets" payload = file("./secrets.yaml.encrypted") } } resource "aws_secretsmanager_secret" "hoge_secrets" { name = "hoge-secrets" recovery_window_in_days = 30 } locals { hoge_secrets = yamldecode(data.aws_kms_secrets.secrets.plaintext["secrets"]) } resource "aws_secretsmanager_secret_version" "hoge_secrets_detail" { secret_id = aws_secretsmanager_secret.hoge_secrets.id version_stages = ["AWSCURRENT"] secret_string = jsonencode({ username = local.hoge_secrets.username password = local.hoge_secrets.password dbhost = local.hoge_secrets.dbhost dbname = local.hoge_secrets.dbname dbhost_replica = local.hoge_secrets.dbhost_replica hoge_token = local.hoge_secrets.hoge_token }) }
関連情報
Terraform の適用と結果確認
Terraform の適用と結果確認していきます.secret_string
の中身は(sensitive value)
という形で見えないようになっているので,どの秘匿情報を Secrets Manager に保存しようとしているかはわからないです.
Terraform will perform the following actions: # aws_secretsmanager_secret.hoge_secrets will be created + resource "aws_secretsmanager_secret" "hoge_secrets" { + arn = (known after apply) + id = (known after apply) + name = "hoge-secrets" + name_prefix = (known after apply) + policy = (known after apply) + recovery_window_in_days = 30 + rotation_enabled = (known after apply) + rotation_lambda_arn = (known after apply) + tags_all = (known after apply) + rotation_rules { + automatically_after_days = (known after apply) } } # aws_secretsmanager_secret_version.hoge_secrets_detail will be created + resource "aws_secretsmanager_secret_version" "hoge_secrets_detail" { + arn = (known after apply) + id = (known after apply) + secret_id = (known after apply) + secret_string = (sensitive value) + version_id = (known after apply) + version_stages = [ + "AWSCURRENT", ] }
適用の結果を見ると,意図通りの設定値が入っていました.
まとめ
Secrets Manager にいれる秘匿情報を Terraform で管理する時どうするかを悩んでいたので,冒頭のブログを参考に KMS を使いつつ試してみました.Terraform のコードに秘匿情報は載らないし,暗号化して管理できかつTerraform の適用時にも秘匿情報がターミナル上にも出てこないため運用上も良さそうに思います.何か参考になれば嬉しいです!