目次
はじめに
こんにちは、ディーネットの牛山です。
Terraform1.11より古いバージョンでは、パスワードなどのシークレット情報がstateファイルと呼ばれる状態を管理するところに平文で書き込まれる状況にありましたが、1.11から一部のリソースにおいて書き込み専用引数がサポートされました。
これにより、状態を管理するところに書き込まれずシークレット情報の管理がより柔軟となりましたので、この機能について紹介したいと思います。
従来パターンと書き込み専用引数を使用したパターンで比較していきます。
設定データや機密データを管理するストレージを提供する「AWS Systems Manager Parameter Store」で書き込み専用引数がサポートされていますので、今回はこちらを例にします。
1. 従来のパターン(stateファイルに値が保存される)
パラメータストアに「my-secret-value」という値を設定するTerraformコードです。
resource "aws_ssm_parameter" "example" {
name = "example"
type = "SecureString"
value = "my-secret-value" # この値がstateファイルに平文で記録されてしまう
}
terraform planの内容を見ると次の差分が出ています。
+ value_wo = (write-only attribute)
読み取り専用引数が差分に出ていますが、Terraformバージョンが読み取り専用引数属性に対応しているためです。対応バージョンより古いものでは、出ないことを確認しています。
terraform plan
Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_ssm_parameter.example will be created
+ resource "aws_ssm_parameter" "example" {
・・・
+ type = "SecureString"
+ value = (sensitive value)
+ value_wo = (write-only attribute)
・・・
}
・・・
terraform applyを行いAWS環境に適用後、状態管理ファイル(tfstate)を確認すると想定通り「"value": "my-secret-value",」と機密データが書き込まれている状態になっています。
cat terraform.tfstate | jq
{
・・・
"terraform_version": "1.11.0",
・・・
"arn": "arn:aws:ssm:ap-northeast-1:{AWSアカウントID12桁}:parameter/example",
・・・
"type": "SecureString",
"value": "my-secret-value",
2. Terraform 1.11以降のパターン(書き込み専用引数)
従来パターンでは、 value で値を指定していましたが、value_wo(書き込み専用属性)とvalue_wo_version(値更新トリガー属性)を使用して管理する形になります。
書き込み専用引数 value_wo は、状態管理ファイル(tfstate)に値が保存されないため、terraform applyやplanで差分検知が行えません。
この状態を防ぐため、value_wo_version(値更新トリガー属性)を使用します。この属性はAWS Parameter Storeの実際のバージョンとは異なり、単にTerraformの差分検知のためのものです。バージョンが変われば更新と判断し、applyやplanで差分検知、適用が可能となります。
resource "aws_ssm_parameter" "example" {
name = "example"
type = "SecureString"
value_wo = "my-secret" # この値はstateファイルに記録されない
value_wo_version = 0 # 書き込み専用引数は永続化されないため、インクリメントしバージョン管理する
}
terraform planの内容を確認してみます。
「value_wo_version = 0」が増えています。
他は、従来パターンと代わり映えしない感じになっています。
terraform plan
・・・
# aws_ssm_parameter.example will be created
+ resource "aws_ssm_parameter" "example" {
・・・
+ type = "SecureString"
+ value = (sensitive value)
+ value_wo = (write-only attribute)
+ value_wo_version = 0
・・・
}
Plan: 1 to add, 0 to change, 0 to destroy.
・・・
terraform applyを行いAWS環境に適用後、状態管理ファイル(tfstate)を確認すると次の内容が増えています。
"value_wo": null,
"value_wo_version": 0,
value_wo(書き込み専用属性)が null となっており、状態管理ファイル(tfstate)に値が保存されていないことを確認できます。
cat terraform.tfstate | jq
{
・・・
"terraform_version": "1.11.0",
・・・
"arn": "arn:aws:ssm:ap-northeast-1:{AWSアカウントID12桁}:parameter/example",
・・・
"type": "SecureString",
"value": "",
"value_wo": null,
"value_wo_version": 0,
パラメータ値の更新例
パラメータの値を更新する場合は、value_wo に新しい値を設定し、value_wo_version の値をインクリメントします。これにより、Terraformが値の変更を検知して更新を実行します。
resource "aws_ssm_parameter" "example" {
name = "example"
type = "SecureString"
value_wo = "updated-secret" # 新しい値
value_wo_version = 1 # 前回から+1してインクリメント
}
まとめ
書き込み専用引数は、状態管理ファイル(tfstate)に保存されないため、S3等に置いた場合でも安全に保管できるようになり、より柔軟性が高くなりました。
実運用では、以下のような方法でセキュリティを向上させることができます:
terraform.tfvarsの活用: 機密データを変数に入れておき、書き込み専用引数に代入する。terraform.tfvarsはgit管理対象外としておけば、ソースも含めセキュアな状態が保てます。

プロフィール
AWSの設計・構築をメインにおこなっています。
運用・保守をおこなう部署におりましたが、最近、アーキテクト課に異動しました。
日々精進しております。
LINK
クラウドベリージャム:プロフィールページ