Terraformのシークレット管理

アプリケーションがある程度成長したときに、あなたの管理するソフトウェアにはシークレットキーが発生します。 ex) DBのパスワード、APIキー、SSHキー

これらの情報は機密データであり、クラッカーから守らなければならない情報です。 この章ではこれらの情報をどのように管理するべきかを記載します。

シークレットキーをプレーンテキストで保存しない。

ex) Terraformコードにデータベースの認証情報をハードコーディングしてしまう -> NG

resource "aws_db_instance" "example" {
  identifier_prefix   = "terraform-up-and-running"
  engine              = "mysql"
  allocated_storage   = 10
  instance_class      = "db.t2.micro"
  skip_final_snapshot = true
  db_name             = var.db_name

  # Pass the secrets to the resource
  username = "admin"
  password = "password"
}

プレーンテキストなシークレットをバージョン管理システムに入れるのは避けましょう。 この場合、バージョン管理システムにアクセス権がある人は誰でもそのシークレット情報にアクセスできてしまいます。 また、 シークレットのアクセスを監査したり、権限を剥奪する方法がありません 加えて、ハードコーディングしたTerraformの場合は別の環境を作成するときに同じパスワードを使用することになってしまいます。

おすすめ: シークレットストア

シークレットを集中シークレットストアに保存することで、セキュリティと可用性の双方を担保できます。

シークレットストアには以下のようなメリットがあります。

  • コードやバージョン管理システムでプレーンテキストとして保存することはありません。
  • 通常はWeb UIを使用するので、シークレットの保存は誰でもできます。
  • CloudformationやTerraformはシークレットストアにアクセスする方法を提供してくれます。
    • Terraformの場合、 aws_secretsmanager_secret_version というデータストアを使用。
    • Cloudformationの場合、
  • シークレットが漏洩(ろうえい)した際に、シークレットのローテーションや無効化をサポートしてくれます。
  • シークレットストアは誰がどのデータにアクセスしたのかを確認できる監査ログをサポートしています。
  • 暗号化や保存、アクセスパターンが強制されます。

ただし、シークレットストアからのデータの取り出しは少しだけ難しくなり、コストもかかります。

プロバイダーがAWSの場合は、 AWS Secrets Managerを利用できます。

シークレットストアの設定

https://docs.aws.amazon.com/ja_jp/secretsmanager/latest/userguide/intro.html

シークレットストアのコンソール画面から、「その他のシークレットのタイプ」を選択して、プレーンテキストを選択することでjson形式で キーバーリュー形式で保存することができます。

その際、シークレットに一意になるように名前をつけておきましょう。

参考 https://qiita.com/tsubaki_019475/items/4a4bb43fde333b218ca7

上記のコンソール画面で db-creds という名前を作成した場合、Terraformからは以下のようにaws_secretsmanager_secret_versionを使用してアクセス可能です。

data "aws_secretsmanager_secret_version" "creds" {
  secret_id = "db-creds"
}

locals {
  db_creds = jsondecode(
    data.aws_secretsmanager_secret_version.creds.secret_string
  )
}

resource "aws_db_instance" "example" {
  identifier_prefix   = "terraform-up-and-running"
  engine              = "mysql"
  allocated_storage   = 10
  instance_class      = "db.t2.micro"
  skip_final_snapshot = true
  db_name             = var.db_name

  # Pass the secrets to the resource
  username = local.db_creds.username
  password = local.db_creds.password
}

page:https://minegishirei.hatenablog.com/entry/2025/01/13/120556

Dear My Frends.: 個人開発宣伝ラボ - 個人開発者が間違った施策で時間を溶かさないための、心理学と実務知見のナレッジ共有コミュニティ