Ephemeral variables なら terraform apply 時に plan file と一緒に渡せる
Terraform v1.10 で Ephemeral values がサポートされました。
本記事では Ephemeral values を使って terraform apply 実行時に provider の認証情報を変える方法を紹介します。
なお、本記事の内容は自分が Terraform の Community Forum で Terraform のメンテナの方とやり取りした内容そのままになっています。
やりたいこと
まず以下のことを全部実現したいとします。
- terraform apply 実行時に plan file を渡す
- terraform apply による予期せぬ変更 (リソースの削除とか) を防ぎます
- 公式の AWS Provider を使って複数の AWS アカウントのリソースを同じ Terraform Root Module で管理したい
- 基本は 1 Root Module = 1 AWS アカウントだが、他のアカウントのリソースを参照・管理したい場合がある
- terraform plan と apply で IAM Role を分けたい
- 最小権限の原則。 plan では read only な IAM Role を使いたい
なお、今回は AWS に限定して話をしますが、 Google Cloud (Google Provider) などでも話は同じかと思います。
従来の課題
自分の理解が正しければ、従来は上記の 3 つのことを全部実現するのは困難でした (出来たよという場合は教えてほしいです) 。
複数の AWS アカウントを管理するには、異なるアカウントの IAM Role を assume する必要があります。
そのため、複数の provider block を定義して、 assume_role
や assume_role_with_web_identity
属性を使って異なるアカウントの IAM Role を assume する必要があります。
provider "aws" {}
provider "aws" {
alias = "account_a"
assume_role {
role_arn = "arn:aws:iam::123456789012:role/terraform_${var.action}"
}
}
role_arn
をハードコードしてしまうと plan と apply で IAM Role を変えられないので、 Input variables で分けています。
しかし、 plan file と input variable を同時に指定して terraform apply を実行しようとすると失敗します。
$ terraform apply -var action=apply plan.out
╷
│ Error: Can't set variables when applying a saved plan
│
│ The -var and -var-file options cannot be used when applying a saved plan file, because a saved plan includes the variable
│ values that were set when it was created.
╵
エラーメッセージを読めば分かる通り、これは Terraform の制約です。
実際 plan file を JSON に変換して中身を見てみると、 input variable や provider の設定がハードコードされており、 apply 時に変更できないようになっています。
よって上記の 3 つを全てクリアするのは従来難しく、どれかを諦める必要がありました。
解決策
これの解決策がないかと思って Forum で問い合わせたところ、メンテナの方から Ephemeral values で解決できると教えてもらいました。
1.10 リリースのブログでは主に ephemeral resource に目を奪われて見逃していたのですが、 input variable にも ephemeral という属性が追加されています。
variable "action" {
type = string
ephemeral = true
}
ephemeral = true だとその変数の値は Terraform State や plan file に保存されません。
そのため、 plan file を使って terraform apply を実行する場合でも ephemeral variables なら渡せます。
IAM Role を切り替えるのに使う input variable に ephemeral = true
を設定するだけで問題は解決します。
以上、簡単ですが Ephemeral values に関する知見でした。
Discussion