0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Terraform 1.11 の Write-only Arguments と HCP Vault Secret で Terraform の状態ファイルから機密情報を排除

Last updated at Posted at 2025-02-28

はじめに

terraform でパスワード等の機密情報を扱う場合、state に情報が載ってしまうとセキュリティリスクに繋がるケースがあります。

terraform 1.10 で GA になった Ephemeral values を利用し、HashiCorp Vault 上の機密情報を安全に一元管理した上で環境構築できると嬉しいのですが、現在は vault provider が ephemeral resource に対応しておらず、 state に情報が載らないようにするのは 2025/02/28 時点では不可能な状態です。

一方、terraform 1.11 では Write-only Arguments がリソースブロックで利用可能になりました。

これを使用できるリソースを利用すれば、HCP Vault Secret から同期した Variable を Write-only Arguments をサポートしたリソースに流し込むパターンであれば state に記録されなくなります。

今回は state を記録されないコードの例を示します。

構成例

HCP Vault Secret には、HCP Terraform に Secret を同期する仕組みがあります。

この仕組みで同期し作成された Variable の値を Write-only Arguments に書き込む場合は state に Variable 値が書かれませんので、「Vault で安全に管理された機密情報が state に書き込まれず環境に反映される」という構成をとることができます。
実際に AWS Systems Manager パラメータストアを作成する場合のサンプルコードで確認してみましょう。

サンプルコード

AWS Systems Manager パラメータストアを作成する場合、aws_ssm_parameter リソースを使用します。

従来は value 属性でパラメータ値を設定する必要があり、この値は state に書かれていました。
これを value_wo 属性でパラメータ値を設定する形にすれば、state に書かれなくなります。

main.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.87.0"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

locals {
  token_version = 1
}

resource "aws_ssm_parameter" "wo_token" {
  name             = "test_param"
  type             = "SecureString"
  value_wo         = var.token
  value_wo_version = local.token_version
}
variables.tf
variable "aws_region" {
  type    = string
  default = "ap-northeast-1"
}

variable "token" {
  type      = string
  sensitive = true
}

value_wo_version 属性は value_wo 属性のバージョンを示し、この値が変化したら SSM Parameter の変更が実施されます。
state に記録されなくなることで設定した値が変更されたかどうか terraform 的に判断できなくなるので、別の属性で判断するということですね。

Variable には ephemeral = true を指定したいところですが、HCP Terraform 上で Sensitive な Variable を使って動かすと下記のエラーが出るので sensitive = true の指定のみとしました。
現時点では ephemeral と sensitive をどちらも指定することが想定されていないようです。

Error: failed to encode aws_ssm_parameter.wo_token in state: .value_wo: cannot serialize value marked as cty.NewValueMarks(marks.Ephemeral, marks.Sensitive) for inclusion in a state snapshot (this is a bug in Terraform)
Error: Changes.Encode: new value .value_wo: can't serialize value marked with cty.NewValueMarks(marks.Ephemeral, marks.Sensitive) (this is a bug in Terraform)

どちらも指定可能になるか、HCP Terraform の Workspace Variable で ephemeral の指定ができるようになることで解消する理解なので、今後のアップデートに期待ですね。

Workspace の作成

上記のコードを動かす Workspace を作成します。
使用する terraform のバージョンは 1.11 以降を指定するのを忘れないようにしてください。

image.png

AWS に対する操作が必要なので、aws provider 用に AWS アクセスキー、シークレットアクセスキーの Variable を設定するか、dynamic credentials の設定を実施して plan 実行可能にしておきます。

HCP Vault Secret に Secret を作成

下記画像のように HCP Vault Secret に Secret を作成します。
今回は変数 token の値を Vault から設定したいので、Name には token を指定します。

スクリーンショット 2025-02-23 145220.png

HCP Vault Secret からのシークレット値の同期

あとは token 変数を Vault から指定するようにすれば OK ですね。

下記に記述がある通り設定を進め、HCP Vault Secret に定義した Secret を HCP Terraform の Workspace Variables として同期しておきます。

HCP Terraform で Organization Token または Team Token を作成し、そのトークンを指定することで実現できます。
今回は Free 版の HCP Terraform を使用しており Team が使用できないため、Organization Token を使用して連携してみました。

同期できれば、下記のように Workspace variables の一覧に追加されます。

image.png

動作確認

ここまでの構成を実施することで、

  • トップレベルの Variable 属性は state に記録されない
  • aws_ssm_parameter リソースに指定した機密情報は state に記録されない
    となるので、state に機密情報が載らない想定です。
    動作を確認していきましょう。

state に記録されないことの確認

Workspace で apply してみましょう。

image.png

state には機密情報が見当りません!

{
  ~  ~
  "resources": [
    {
      "mode": "managed",
      "type": "aws_ssm_parameter",
      "name": "wo_token",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "allowed_pattern": "",
            "arn": "arn:aws:ssm:ap-northeast-1:xxxx:parameter/test_param",
            "data_type": "text",
            "description": "",
            "has_value_wo": true,
            "id": "test_param",
            "insecure_value": null,
            "key_id": "alias/aws/ssm",
            "name": "test_param",
            "overwrite": null,
            "tags": null,
            "tags_all": {},
            "tier": "Standard",
            "type": "SecureString",
            "value": "",
            "value_wo": null,
            "value_wo_version": 1,
            "version": 1
          },
          ~  ~
}

しかしパラメータストアを確認すると、HCP Vault Secret に登録したトークン: this_is_sample_token が表示されます。

image.png

値の更新に関する確認

HCP Vault Secret の値を変えて同期しただけだと No changes となります。

image.png

image.png

value_wo_version の値を更新してみましょう。

~  ~

locals {
  token_version = 2
}

~  ~

すると無事 Apply でき、パラメータストアで変更が確認できました。

image.png

image.png

Secret の変更があった際のバージョンの値は自動的に更新できるか ?

実験として Secret の変更を検知して value_wo_version の値を自動的に変更する方法として下記を考えました。
value_wo_version に設定する値を time_static リソース の結果とし、time_statickeepers に機密情報のハッシュ値を指定する方法です。

variable "token" {
  type      = string
  sensitive = true
  # ephemeral = true  ## ephemeral を指定すると random_integer の keepers に指定できない
}

resource "time_static" "token_update" {
  triggers = {
    # トークンのハッシュ値を使用してトリガー
    token_hash = sha256(var.token)
  }
}

resource "aws_ssm_parameter" "wo_token" {
  name             = "test_param"
  type             = "SecureString"
  value_wo         = var.token
  value_wo_version = time_static.token_update.unix
}

time_static リソースの Output: unix は現在日時の UNIX 時間なので、今回のような使用方法であれば重複するリスクもなく更新できる認識です。
state には time_static リソースの keepers 属性に指定した機密情報のハッシュ値しか記録されないため、state の安全性もある程度確保されます。

ただ、variable の値を random_integer の keepers に指定できるようにするため variable に ephemeral を指定できなくなるので、もし variable が意図しない場所で参照されると state に機密情報が記録されてしまうリスク があります。
この実装の採用を検討する場合は十分注意してください。

また、terraform のコード変更ではなく Vault の値の変更がきっかけで修正が実施されるので、 意図しないタイミングで terraform の plan 結果に差分が発生する 可能性があります。
これは CI/CD パイプラインでの自動デプロイ時の予期せぬ変更や、コードレビューの複雑化など、運用上不都合になると思われますので、ローカル変数等でバージョンを持っておく形が良いケースが多いのではないかと思われます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?