📑

Terraform 1.10のEphemeralでシークレット管理しましょう

2024/12/11に公開

はじめに

インフラストラクチャーコード(IaC)の普及に伴い、運用効率が大幅に向上しましたが、シークレット(パスワードやAPIキー)の安全な管理は依然として大きな課題です。Terraform 1.09まで、シークレットがステートファイルに保存されるリスクがありましたが、「エフェメラル値」機能の登場により、この課題が根本的に解決されました。今回Terraform 1.10のEphemeral値シークレット管理をしてみました。


比較:ランダム文字列 vs Ephemeral値

①ランダム文字列(random_string)の使用

Terraformのrandom_stringを使うことで、手軽に資格情報を生成できますが、この方法では生成されたシークレットがステートファイルに保存されるため、漏洩リスクが高まります。

例: random_stringリソースを使ったTerraformファイル

resource "random_string" "resource_password" {
  length  = 16
  special = true
  upper   = true
  lower   = true
  numeric = true
}

問題点:

  • 生成されたパスワード(random_string.resource_password.result)がステートファイルに保存される。
  • ステートファイルが誤管理された場合、シークレットが漏洩する可能性がある。

結果のterraform.tfstate例:

{
  "version": 4,
  "terraform_version": "1.10.0",
  "serial": 4,
  "lineage": "b1dfe50f-aa0c-aed2-c925-cd56062b4dad",
  "outputs": {},
  "resources": [
    {
      "mode": "managed",
      "type": "random_string",
      "name": "resource_password",
      "provider": "provider[\"registry.terraform.io/hashicorp/random\"]",
      "instances": [
        {
          "schema_version": 2,
          "attributes": {
            "id": "1dJdLfmM$evgk\u003cue",
            "keepers": null,
            "length": 16,
            "lower": true,
            "min_lower": 0,
            "min_numeric": 0,
            "min_special": 0,
            "min_upper": 0,
            "number": true,
            "numeric": true,
            "override_special": null,
            "result": "1dJdLfmM$evgk\u003cue",
            "special": true,
            "upper": true
          },
          "sensitive_attributes": []
        }
      ]
    }
  ],
  "check_results": null
}

②エフェメラル値とAWS Secrets Managerの使用

Terraform 1.10では、エフェメラル値により、シークレットがステートファイルやプランファイルに保存されることを防ぎます。この方法では、シークレットはTerraformの実行フェーズ中のみ一時的に利用されます。

例: エフェメラル値を使ったTerraformファイル

terraform {
  required_version = ">= 1.10.0"
}

provider "aws" {
  region = "ap-northeast-1"
}

ephemeral "aws_secretsmanager_secret_version" "test_secret" {
  # AWS SecretのARN
  secret_id = "arn:aws:secretsmanager:ap-northeast-1:1234567890:secret:secret-arn"
}

利点:

  • シークレットがステートファイルに保存されない。
  • シークレットはTerraformの実行中のみ存在し、永続化されない。

結果のterraform.tfstate例:

{
  "resources": []
}

エフェメラル値を使用することで、例えばRDSデータベースの認証情報を安全に管理できます。以下はその一例です。

エフェメラル値を使ったRDS MySQLデータベースのプロビジョニング

locals {
  mysql_credentials = jsondecode(ephemeral.aws_secretsmanager_secret_version.test_secret.secret_string)
}

resource "aws_db_instance" "default" {
  allocated_storage    = 10
  db_name              = "mydb"
  engine               = "mysql"
  engine_version       = "8.0"
  instance_class       = "db.t3.micro"
  username             = local.mysql_credentials["username"]
  password             = local.mysql_credentials["password"]
  vpc_security_group_ids = [aws_security_group.mysql_sg.id]
  skip_final_snapshot  = true
  parameter_group_name = "default.mysql8.0"
}

結論

エフェメラル値により、シークレットがTerraformのアーティファクトに保存されるリスクがなく、インフラ運用もより安全でシンプルになります。これからのシークレット管理は、エフェメラル値の活用が標準となり、セキュリティの強化と運用効率も向上するでしょう。

参考資料:

Komlock lab

Discussion