Terraformのエフェメラルリソースを使ってみた

Terraformのエフェメラルリソースを使ってみた

Terraformのエフェメラルリソースを使ってみました。この記事では注意点などをお伝えします。
Clock Icon2025.01.28

お疲れさまです。とーちです。

みなさんはTerraformのエフェメラルリソースをご存知でしょうか?Terraformをよりセキュアに使える素晴らしいアップデートなのですが、使ってみるとなかなか使い所が難しいと感じたので実際のコードも交えて使い方を紹介したいと思います。

エフェメラルリソースとは

そもそもエフェメラルリソースとはという話ですが、Terraform公式ドキュメントによると、以下のような特徴があります

  • エフェメラルリソースはTerraform v1.10以降で利用可能
  • 通常のリソースと異なり、tfstateファイルに保存されない
  • AWS Secrets Manager(以後Secrets Manager)などのサービスに保存されたDBパスワードなどの機密情報を、Terraformコード内で参照するために使用
  • エフェメラルリソースにより取得した値を使える場所は限られている

特徴としてはtfstateファイルに保存されないということでしょう。従来はtfstateファイルに値がプレーンテキストで保存されていたので、例えばS3バケットへのアクセス権限を絞るなどして、tfstateの参照をある程度厳密に考える必要がありました。エフェメラルリソースを使うとDBパスワード等の機微な情報を安全にTerraformで扱えるようになります。

またエフェメラルリソースにより取得した値を使える場所が限られている点についても注意が必要です。これについては後ほど詳しく見ていきます。

AWSプロバイダーの対応状況

AWSプロバイダーでの対応状況は以下のページに記載があります

https://support.hashicorp.com/hc/en-us/articles/36370466952979-List-of-Ephemeral-Resources-released-by-Top-Terraform-Providers

上記によると、2025/1/28時点で以下の値を取得できます

エフェメラルリソースの使用場所の制限について

エフェメラルリソースの使用制限について、実際に試してみましょう。

あらかじめSecretsManagerを作成しておき、 dummy-value という値をセットしておきます。そして以下のようなSecretsManagerから値を取得してパラメータストアに取得した値を入れるだけの簡単なTerraformコードを実行します。

data "aws_secretsmanager_secret_version" "example" {
  secret_id = var.datastore_sysdig_secret_params_secret_id
}

resource "aws_ssm_parameter" "test" {
  name  = "testParam"
  type  = "SecureString"
  value = jsondecode(data.aws_secretsmanager_secret_version.example.secret_string)["sysdig_agent_access_key"]
  
}

なおこの状態では以下のようにtfstateファイルに本来は隠したい値である dummy-value が記録されてしまっています。

      "type": "aws_ssm_parameter",
      "name": "test",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            <中略>
            "type": "SecureString",
            "value": "dummy-value", # 生の値が記録
            "version": 1
          },

続いてこのコードを以下のようにエフェメラルリソースを使うように修正してみます。

# data "aws_secretsmanager_secret_version" "example" {
ephemeral "aws_secretsmanager_secret_version" "example" {
  secret_id = var.datastore_sysdig_secret_params_secret_id
}

resource "aws_ssm_parameter" "test" {
  name  = "testParam"
  type  = "SecureString"
  value = jsondecode(ephemeral.aws_secretsmanager_secret_version.example.secret_string)["sysdig_agent_access_key"]
  
}

terraform applyを実行すると以下のエラーメッセージが表示されました

Ephemeral values are not valid in resource arguments, because resource instances must persist between Terraform phases.
(日本語訳:リソース引数では一時的な値は有効ではありません。リソースインスタンスはTerraformのフェーズ間で持続する必要があるためです。)

resourceブロックでエフェメラルリソースを使用しようとしたのでエラーとなったようです。
続いて、エフェメラルリソースを参照可能なlocal valuesに値を入れてみます。

# data "aws_secretsmanager_secret_version" "example" {
ephemeral "aws_secretsmanager_secret_version" "example" {
  secret_id = var.datastore_sysdig_secret_params_secret_id
}

locals {
  token = jsondecode(ephemeral.aws_secretsmanager_secret_version.example.secret_string)["sysdig_agent_access_key"]
}

# resource "aws_ssm_parameter" "test" {
#   name  = "testParam"
#   type  = "SecureString"
#   value = jsondecode(ephemeral.aws_secretsmanager_secret_version.example.secret_string)["sysdig_agent_access_key"]
  
# }

当たり前ですが、これは正常に実行ができました。

続いてlocal valuesを経由して、ParameterStoreを作成しようとしてみます。

# data "aws_secretsmanager_secret_version" "example" {
ephemeral "aws_secretsmanager_secret_version" "example" {
  secret_id = var.datastore_sysdig_secret_params_secret_id
}

locals {
  token = jsondecode(ephemeral.aws_secretsmanager_secret_version.example.secret_string)["sysdig_agent_access_key"]
}

resource "aws_ssm_parameter" "test" {
  name  = "testParam"
  type  = "SecureString"
  # value = jsondecode(ephemeral.aws_secretsmanager_secret_version.example.secret_string)["sysdig_agent_access_key"]
  value = local.token
  
}

このコードを実行すると先程と同様に以下のエラーとなりました。

Ephemeral values are not valid in resource arguments, because resource instances must persist between Terraform phases.

このように、エフェメラルリソースで得た値は何かを経由したとしても指定の場所でしか使えないということが分かります。

実践:Sysdigプロバイダーでの活用例

それでは実際のユースケースを想定した使い方をしてみましょう。今回はエフェメラルリソースを使ってコンテナやクラウド環境のセキュリティ監視・可視化を行うためのプラットフォームであるSysdigのAPIトークンを取得し、Sysdigのプロバイダーにトークンを入れることでSysdigリソースを作成してみます。
なお、このリソースはSysdigに監視対象のAWSアカウントを登録するためのもので、正常に実行されるとSysdigの管理画面に登録したAWSアカウントが表示されます。

ephemeral "aws_secretsmanager_secret_version" "sysdig_secret_params_secret_id" {
  secret_id = var.datastore_sysdig_secret_params_secret_id
}

provider "sysdig" {
  sysdig_secure_url       = "https://us2.app.sysdig.com"
  sysdig_secure_api_token = jsondecode(ephemeral.aws_secretsmanager_secret_version.sysdig_secret_params_secret_id.secret_string)["sysdig_api_token"]
}

module "onboarding" {
  source  = "sysdiglabs/secure/aws//modules/onboarding"
  version = "~>1.1"
}

module "config-posture" {
  source                   = "sysdiglabs/secure/aws//modules/config-posture"
  version                  = "~>1.1"
  sysdig_secure_account_id = module.onboarding.sysdig_secure_account_id
}

resource "sysdig_secure_cloud_auth_account_feature" "config_posture" {
  account_id = module.onboarding.sysdig_secure_account_id
  type       = "FEATURE_SECURE_CONFIG_POSTURE"
  enabled    = true
  components = [module.config-posture.config_posture_component_id]
  depends_on = [module.config-posture]
}

上記のコードを実行すると正常にSysdigにAWSアカウントが登録されました。

Dataソースで作成した場合とのtfstateファイルの差分を比較してみます。以下のように機微な情報が含まれるSecretsManagerを参照した箇所がエフェメラルリソースでは丸ごとなくなっているのがわかります。

image.png

まとめ

以上、エフェメラルリソースの紹介でした。
エフェメラルリソースは機密情報を安全に扱うための素晴らしい機能ですが、使用できる場所が限定されているため、注意してください。特にプロバイダーの設定やプロビジョナーでの使用など、限定的なユースケースで活用するのが良さそうです。

以上、とーちでした。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.