Upgrade to Pro — share decks privately, control downloads, hide ads and more …

2026-08-15 JAWS-UG 茨城 #16 Secrets ManagerにおけるSe...

2026-08-15 JAWS-UG 茨城 #16 Secrets ManagerにおけるSecret値の管理(Terraformの場合) / Secrets Manager Secrets

2026/08/15(土) JAWS-UG 茨城 #16 LT&BBQ大会
https://jawsug-ibaraki.connpass.com/event/401327/

で話した内容。
TerraformでSecret値を扱う際の課題とその対応の話。

Avatar for SUZUKI Masashi

SUZUKI Masashi

August 15, 2026

More Decks by SUZUKI Masashi

Other Decks in Technology

Transcript

  1. おまえだれよ • • • • • すずきまさし/masasuzu/@masasuz 株式会社スリーシェイク クラウドインフラなんでも屋さんをしてます 2026年はGoogle

    Cloudばかりしてます 茨城は小中高の頃毎年キャンプに来ていました • 得意領域 ◦ AWS ▪ AWS Community Builder Cloud Operation Since 2024~2026 ▪ 2026 Japan All AWS Certifications Engineers ◦ Google Cloud ▪ Google Cloud Partner Top Engineer 2026 ◦ Terraform Copyright © 3-shake, Inc. All Rights Reserved. 2
  2. ちなみにIaCなに使ってますか? • • • • • Terraform? CloudFormation? CDK? Pulumi?

    CDK Terrain? (旧CDKTF) Copyright © 3-shake, Inc. All Rights Reserved. 4
  3. 素直に書いてみる resource "aws_secretsmanager_secret" "db" { name = "prd-app-db" } resource

    "aws_secretsmanager_secret_version" "db" { secret_id = aws_secretsmanager_secret.db.id secret_string = jsonencode({ username = "app" password = var.db_password }) } • Secrets ManagerとSecrets ManagerのSecret値を設定しています Copyright © 3-shake, Inc. All Rights Reserved. 7
  4. tfstateにはこう書かれる { } • • "type": "aws_secretsmanager_secret_version", "instances": [{ "attributes":

    { "secret_string": "{\"username\":\"app\",\"password\":\"P@ssw0rd\"}" } }] パスワードが平文で載っている !!! これはよくない Copyright © 3-shake, Inc. All Rights Reserved. 8
  5. そもそも tfstateって?(状態の同期とマッピング) ① あるべき姿 (コード ) ② 前回の状態 (tfstate) #

    main.tf resource "aws_instance" "web" { ami = "ami-123456" instance_type = "t3.micro" tags = { Name = "web-server" } } # terraform.tfstate マッピング { } 作成したいインフラ構成の定義定義書。 Copyright © 3-shake, Inc. All Rights Reserved. ③ 実際のインフラ (AWS等) "resources": [{ "type": "aws_instance", "name": "web", "instances": [{ "attributes": { "id": "i-0abcd1234ef", "public_ip": "1.2.3.4" } }] }] 前回applyしたときの記録。 コードと実際のAWSリソースを紐付けるマッ ピングデータ。 状態検知 EC2 Instance ID: i-0abcd1234ef Status: running クラウド上に実際にプロビジョニングされ た実世界のリソース。
  6. つまり、避けようがない • • • terraform plan/apply時にはあるべき姿、前回の記録、実物の状態を突き合わせます 差分を出すには前回の値を覚えている必要があります tfstate はリソースの値そのものを持ちます terraform

    state showなどではsensitive扱いされるのでマスクがされます。 しかしながらtfstateを直接見ることができる人には Secret値が見えてしまいます。 tfsateは通常S3に保存することが多いので、 tfsate用のS3バケットにアクセス権がある人には見えうります。 Copyright © 3-shake, Inc. All Rights Reserved. 10
  7. では、どうするか tfstateに値が載ってしまうのは通常に使う分には仕組み避けられない。 ここで取れるアプローチとしては 3つあります。 • • • a. Secret値が平文で入り込むのは諦めて tfstateを守る

    Secret値をTerraformを管理しない ◦ b. Secretなリソースを管理しない ◦ c. Secretな値を管理しない (ignore_change) Secret値をtfstateに載せないようにする ◦ d. ephemeral + write-only ◦ e. sops 次ページからこれらの方法を見ていきます Copyright © 3-shake, Inc. All Rights Reserved. 12
  8. 諦めてtfstateを守る Secret値がtfstateに入り込むこと自体は仕方ないと諦めて、 Secret値が見られないようにする • • • tfstate用のバケットを最小権限にする ◦ 可能な限り人間が Terraformを扱わず、機械

    (CI/CD)からしか参照できないようにする CIのログにSecret値を出さないようにする ◦ terraform show -json など生値が出力されるコマンドを実行しない planfileをアーティファクトに残さない いくら気を付けても、なんらかの方法で tfstateにアクセスできてしまったら Secret値は漏れることを留意すること Copyright © 3-shake, Inc. All Rights Reserved. 15
  9. Secrets Managerを手動管理 そもそもTerraform管理せず、コンソールや CLIから作成すれば、 tfstateにそもそも残りません。 ただし、デメリットとして、 • 特定のリソースだけ管理されていないので管理が煩雑に • Secrets

    ManagerリソースがTerraform管理されないので、他のリソースに渡す際に arnの取り出しに一手 間必要 • RDSのパスワードのようにリソースのパラメータが Secretなものは対応できない ◦ RDSに関して言うなら自動ローテーションすれば良いという観点もある • インフラの管理者と Secret値の管理者が別のときは良い気はしますが、同じ時は煩雑に感じます Copyright © 3-shake, Inc. All Rights Reserved. 17
  10. ignore_changes resource "aws_secretsmanager_secret_version" "db" { secret_id = aws_secretsmanager_secret.db.id secret_string =

    jsonencode({ username = "app" password = "PLACEHOLDER_REPLACE_ME" }) } • • lifecycle { ignore_changes = [secret_string] } ignore_changesに指定したパラメータは差分があっても無視されます 作成時にダミー値を入れることで tfstateは以降ダミー値しか保存されません ◦ 逆に言うと最初に本当のSecret値を入れた永遠に残り続けます Copyright © 3-shake, Inc. All Rights Reserved. 19
  11. ephemeral とは Terraform 1.10 で入ったtfstate に残さないための仕組み # tfstateに記録される data "aws_secretsmanager_random_password"

    "db" { password_length = 32 exclude_punctuation = true } # tfstateに記録されない ephemeral "aws_secretsmanager_random_password" "db" { password_length = 32 exclude_punctuation = true } dataとして使っていたものを ephemeralにするだけで対応できます (対応data sourceのみ) Copyright © 3-shake, Inc. All Rights Reserved. 21
  12. write-only 引数 Terraform 1.11 以降 • これを使用して書かれたパラメータは tfstateに記録されません • 従来のパラメータ名の

    suffixに _wo がつきます • tfstate に無い値の差分は、原理的に計算できません • そのためversionを利用する ◦ versionがtfstateに保存されるので、この値が変わったことで変更されたと認識します ◦ 逆に言うと、versionが変えなければ、 Secret値も変更されません resource "aws_secretsmanager_secret_version" "db" { secret_id = aws_secretsmanager_secret.db.id } secret_string_wo = jsonencode({ username = "app" password = ephemeral.aws_secretsmanager_random_password.db.random_password }) secret_string_wo_version = 1 Copyright © 3-shake, Inc. All Rights Reserved. 22
  13. パスワード生成から保存まで tfstate を通さない ephemeral "aws_secretsmanager_random_password" "db" { password_length = 32

    exclude_punctuation = true } resource "aws_secretsmanager_secret_version" "db" { secret_id = aws_secretsmanager_secret.db.id } secret_string_wo = jsonencode({ username = "app" password = ephemeral.aws_secretsmanager_random_password.db.random_password }) secret_string_wo_version = 1 random passwordもephemeral、secret_string_woはwrite onlyなのでtfstateには残らない Copyright © 3-shake, Inc. All Rights Reserved. 24
  14. 外部からデータを取ってきてそれを設定する場合にも使える ephemeral "aws_ssm_parameter" "db" { arn = var.db_ssm_arn } resource

    "aws_secretsmanager_secret_version" "db" { secret_id = aws_secretsmanager_secret.db.id } secret_string_wo = jsonencode({ username = "app" password = ephemeral.aws_ssm_parameter.db.value }) secret_string_wo_version = 1 今回はParameter Storeからデータを取得して今すぐが、 ephemeralなのでこの値は tfstateには残らない Copyright © 3-shake, Inc. All Rights Reserved. 25
  15. 生成できない値はどうする 値がterraformで側で生成や呼び出せるものよいなら ephemeralで完結します。 でも、API キーのように値が外部で決まっているもので Terraformで呼び出せなかったり、呼び出し権限を与え たくない場合は ? terraformに -var-file

    オプションを付けることで gitレポジトリの外にあるパラメータファイルを読み取らせてそこか らSecret値を参照させることができます。 terraform plan -var-file="./secrets.tfvars" # git管理外のtfvarsファイルを参照 Copyright © 3-shake, Inc. All Rights Reserved. 27
  16. sops とは • • • { } 暗号化エディタ ◦ https://github.com/getsops/sops

    YAML / JSON / ENV / INI / バイナリをサポート 暗号鍵は AWS KMSを使用 "db": { "username": "app", "password": "ENC[AES256_GCM,data:...,iv:...,tag:...,type:str]" } キーは読めるが、値は暗号化されて読めないようにできる。 これによりSecret値を”安全”にgitにコミットできます。 sops providerとしてTerraformから利用できます。 Copyright © 3-shake, Inc. All Rights Reserved. 29
  17. Terraformでの利用 • API キーをtfstateに残さないために、 ephemeralを使用する ephemeral "sops_file" "secrets" { source_file

    = "secrets/prod/app.enc.json" } resource "aws_secretsmanager_secret_version" "api_key" { secret_id = aws_secretsmanager_secret.api_key.id } secret_string_wo = jsondecode(ephemeral.sops_file.secrets.raw)["api_key"] secret_string_wo_version = 1 Copyright © 3-shake, Inc. All Rights Reserved. 30
  18. まとめ • • • • TerraformにおけるSecret値の課題を説明しました ◦ tfstateファイルにはSecret値が平文で入りうります Secret値を管理するかについて説明しました ◦

    リソース自体管理しない ◦ Secretなパラメータだけ管理しない (ignore_change) ◦ tfstateに残さない方法を使う ◦ Secrets値はsopsで暗号化して gitで管理できるようにする チーム状況やアプリの特性に合わせて使い分けていただけたらと思います。 Terraformについては説明しましたが、 CDKやCloudFormation、Pulumi、CDK Terrainなどではどうなの か知見が薄いので懇親会等で教えてください。 Copyright © 3-shake, Inc. All Rights Reserved. 33