remote state sharing
分割されたtfstateを参照する場合、terraform_remote_stateを利用する。これを利用することで別のtfstateのoutputで定義した情報を参照することができる。
tfstateへのアクセスを制限する場合は実行ユーザのアクセス権限を設定することで制御するが、Terraform Cloudではそれに加えてtfstate側(Terraform Cloud Workspace側)のアクセス制御の機能として remote state sharingがある。
Workspace Settings → General Settingsから変更でき、Share with all workspaces in this organization
を選択すると別のworkspaceからtfstateを参照可能になる。Share with specific workspaces
を選択して対象のworkspaceを指定すると、指定したworkspaceからはtfstateの参照が可能となり、指定していないworkspaceからはtfstateの参照が不可能となる。
動作検証
実際にremote state sharingを試してみる
検証環境
network-workspaceとapp-workspaceという2つのworkspaceを準備する。
network-workspaceではネットワーク関連のリソースを定義し、app-workspaceではアプリ固有のリソースを定義することを想定する。また、app-workspaceはnetwork-workspaceのoutputを参照する。
network-workspaceのremote state sharingで、app-workspaceからのアクセスを許可すればapp-workspaceのリソース構築は成功するし、app-workspaceからのアクセスを許可しなければapp-workspaceのリソース構築は失敗することが期待できる。
ローカルplan実行
network-workspaceのremote state sharingで、アクセスを許可した状態で app-workspaceでplanを実行する。
このとき、無事terraform_remote_stateを用いてnetwork-workspaceのoutputを参照できている。
(事前にapply済のためここのplanでは差分なしになっている)
$ terraform plan
data.terraform_remote_state.network: Reading...
data.terraform_remote_state.network: Read complete after 2s
data.aws_subnet.sample: Reading...
data.aws_subnet.sample: Read complete after 0s [id=subnet-xxxx]
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
続いて、network-workspaceのremote state sharingで、アクセスを許可せずに app-workspaceでplanを実行する。
するとなぜか今度もplanに成功してしまう。本当は data.terraform_remote_state.network
の参照でエラーになって欲しかった。
$ terraform plan
data.terraform_remote_state.network: Reading...
data.terraform_remote_state.network: Read complete after 2s
data.aws_subnet.sample: Reading...
data.aws_subnet.sample: Read complete after 0s [id=subnet-xxxx]
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
なぜ実行できるのか
app-workspaceのExecution ModeをLocalにしてplanを実行したから。
Terraform Cloudには、Terraform Cloud上でterraform planを実行する Remote Execution Modeと、ローカルでterraform planを実行する Local Execution Modeがある。Remote Execution Modeの場合はローカルでterraform planを実行しても、Terraform Cloud上で実行したplan結果が表示されるだけになる。
Local Execution Modeの場合、Terraform Cloudは単なるtfstate置き場になる。このときローカルでterraform planを実行しても直接network workspaceのリソースを参照するので、remote state sharingも機能しなくなると推測する。
リモートplan実行
app-workspaceのExecution ModeをRemoteに変更してplanを実行する。
$ terraform plan
...
Terraform v1.3.6
on linux_amd64
Initializing plugins and modules...
data.terraform_remote_state.network: Reading...
╷
│ Error: Error retrieving state: forbidden
│
│ This Terraform run is not authorized to read the state of the workspace 'sample-network-workspace'.
│ Most commonly, this is required when using the terraform_remote_state data source.
│ To allow this access, 'sample-network-workspace' must configure this workspace ('sample-app-workspace')
│ as an authorized remote state consumer. For more information, see:
│ https://www.terraform.io/docs/cloud/workspaces/state.html#accessing-state-from-other-workspaces.
│
│
│
╵
Operation failed: failed running terraform plan (exit 1)
となり、無事 remote state sharingによるアクセス制御に成功した。
また、network-workspaceの remote state sharingでapp-workspaceにアクセスを許可して再度planを実行してみる。
すると、今度はplanの実行に成功する。もちろん、全workspaceにアクセスを許可しても結果は同じ。
$ terraform plan
...
Terraform v1.3.6
on linux_amd64
Initializing plugins and modules...
data.terraform_remote_state.network: Reading...
data.terraform_remote_state.network: Read complete after 0s
data.aws_subnet.sample: Reading...
data.aws_subnet.sample: Read complete after 1s [id=subnet-xxxx]
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration
and found no differences, so no changes are needed.
tfe_outputsを利用する
Terraform Cloudを利用する場合、outputの参照に terraform_remote_stateを使わずにtfe_outputsを使う方法がある。
こちらのドキュメントでは、terraform_remote_stateのoutputsを使わずにtfe_outputsを利用することを推奨している。
tfe_outputsを利用する場合も同じ。
network-workspaceの remote state sharingでapp-workspaceにアクセスを許可してplanを実行すると成功し、アクセスを許可しないとplanに失敗する。
ただし、失敗時のエラーがforbiddenではなくUnsupported attributeになる。
$ terraform plan
...
Terraform v1.3.6
on linux_amd64
Initializing plugins and modules...
data.tfe_outputs.network: Reading...
data.tfe_outputs.network: Read complete after 0s [id=xxxx]
╷
│ Error: Unsupported attribute
│
│ on network.tf line 3, in data "aws_subnet" "sample":
│ 3: id = data.tfe_outputs.network.values.subnet_id
│
│ This object does not have an attribute named "subnet_id".
╵
Operation failed: failed running terraform plan (exit 1)
アクセスエラー時に401ではなく404を返すのはセキュリティ的には正しい挙動か。
まとめ
- Terraform Cloudにおけるwrokspace間のリソース参照の制御にremote state sharing機能がある
- remote state sharingはTerraform Cloud上でterraform planを実行するRemote Execution Modeのときのみ有効
- ローカルでterraform planを実行するLocal Execution Modeのときはremote state sharingではアクセス制御できない
- terraform_remote_stateでもtfe_outputsでもアスセス制御は可能だがエラー時のレスポンスが異なる