terraform_remote_state — 別のTerraformステートからoutputを参照する

複数のTerraformモジュールやワークスペースで構成を分割している場合、あるモジュールが管理するリソースの情報(VPCのID、サブネットIDなど)を別のモジュールから参照したいことがあります。terraform_remote_stateデータソースは、別のTerraform構成が持つステートファイルのroot module outputsを読み取るための組み込みデータソースです。

⚠️ セキュリティ上の重要な注意 terraform_remote_stateのoutputsを読み取れるユーザーは、直接のネットワークリクエストによりステートスナップショット全体にもアクセスできます。センシティブなデータを扱うリソースが含まれる場合は使用しないでください(詳細は後述)。

terraform_remote_stateとは

terraform_remote_stateはTerraformの組み込みデータソースで、terraform.io/builtin/terraformプロバイダーによって提供されています。このプロバイダーはプロバイダーの設定なしで使用でき、別途インストールも不要です。

できること:

  • リモートバックエンド(S3、GCS、Terraform Cloudなど)に保存されたステートのoutputsを読み取る
  • ローカルバックエンドのステートファイルのoutputsを読み取る
  • デフォルト値を設定して、outputsが存在しない場合に備える

できないこと:

  • root module outputsより深い階層(ネストされたモジュールのoutputsやリソースの詳細)へのアクセス
  • outputsとして公開されていないリソースのattributesへの直接アクセス

引数リファレンス

data "terraform_remote_state" "<名前>" {
  backend   = "<バックエンドタイプ>"  # 必須
  workspace = "<ワークスペース名>"    # オプション
  config    = { ... }               # オプション(ほとんどの場合必要)
  defaults  = { ... }               # オプション
}
引数必須説明
backendstring使用するバックエンドのタイプ("s3""gcs""remote""local"など)
workspacestring対象ワークスペース名(バックエンドがワークスペースをサポートする場合)
configobjectバックエンドの設定(ほとんどのバックエンドで実質必須)
defaultsobjectステートが空またはoutputsが存在しない場合のデフォルト値

注意: config内でネストブロックが必要な場合(例:remoteバックエンドのworkspaces)は、通常のHCLブロック構文ではなくオブジェクト値として指定します。workspaces { ... }ではなくworkspaces = { ... }と書きます。

属性リファレンス

属性説明
outputsリモートステートのroot module outputsをすべて含むオブジェクト(Terraform v0.12以降)

アクセス方法:data.terraform_remote_state.<名前>.outputs.<output名>

基本的な使用例

S3バックエンドのステートを参照する

ネットワーク構成(別のTerraformモジュール)のoutputs:

# network/outputs.tf
output "vpc_id" {
  value       = aws_vpc.main.id
  description = "VPC ID"
}

output "private_subnet_ids" {
  value       = aws_subnet.private[*].id
  description = "プライベートサブネットのIDリスト"
}

アプリケーション構成からネットワーク情報を参照:

terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

variable "environment" {
  description = "デプロイ環境"
  type        = string
  default     = "dev"
}

# ネットワーク構成のステートを参照
data "terraform_remote_state" "network" {
  backend = "s3"

  config = {
    bucket = "my-terraform-state"
    key    = "${var.environment}/network/terraform.tfstate"
    region = "ap-northeast-1"
  }
}

# AMI をdata sourceで取得
data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }
}

# ネットワーク構成のoutputsを利用してEC2インスタンスを作成
resource "aws_instance" "app" {
  ami           = data.aws_ami.amazon_linux.id
  instance_type = "t3.micro"
  subnet_id     = data.terraform_remote_state.network.outputs.private_subnet_ids[0]

  root_block_device {
    encrypted = true
  }

  tags = {
    Name        = "${var.environment}-app-server"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

Terraform Cloud(remoteバックエンド)のステートを参照する

data "terraform_remote_state" "vpc" {
  backend = "remote"

  config = {
    organization = "my-org"
    workspaces = {
      name = "vpc-prod"
    }
  }
}

resource "aws_instance" "foo" {
  ami           = data.aws_ami.amazon_linux.id
  instance_type = "t3.micro"
  subnet_id     = data.terraform_remote_state.vpc.outputs.subnet_id

  root_block_device {
    encrypted = true
  }

  tags = {
    Name        = "app-server"
    Environment = "prod"
    ManagedBy   = "terraform"
  }
}

ローカルバックエンドのステートを参照する(開発・テスト用)

data "terraform_remote_state" "local_network" {
  backend = "local"

  config = {
    path = "../network/terraform.tfstate"
  }
}

defaultsでデフォルト値を設定する

ステートファイルが空の場合やoutputsが存在しない場合の安全策としてdefaultsを使用できます:

variable "environment" {
  description = "デプロイ環境"
  type        = string
  default     = "dev"
}

data "terraform_remote_state" "shared" {
  backend = "s3"

  config = {
    bucket = "my-terraform-state"
    key    = "${var.environment}/shared/terraform.tfstate"
    region = "ap-northeast-1"
  }

  defaults = {
    vpc_id             = "vpc-00000000"
    private_subnet_ids = ["subnet-00000000"]
  }
}

root module outputsのみアクセス可能

terraform_remote_stateでアクセスできるのは、参照先Terraform構成のroot module outputsのみです。ネストされたモジュールのoutputsには直接アクセスできません。

ネストされたモジュールのoutputsを外部から参照可能にするには、root moduleで明示的に公開する必要があります:

# root module の outputs.tf
module "app" {
  source = "..."
}

# ネストモジュールのoutputをroot levelで公開することで terraform_remote_state から参照可能になる
output "app_value" {
  value = module.app.example
}

セキュリティに関する重要な注意事項

公式ドキュメントではterraform_remote_stateの使用について重要な警告があります:

公式警告(原文): “Although terraform_remote_state doesn’t expose any other state snapshot information for use in configuration, the state snapshot data is a single object and so any user or server which has enough access to read the root module output values will also always have access to the full state snapshot data by direct network requests. Don’t use terraform_remote_state if any of the resources in your configuration work with data that you consider sensitive.”

要するに、outputsを読める権限 = ステート全体にアクセスできる権限です。センシティブなデータ(データベースパスワード、APIキー等)がステートに含まれる場合は使用を避けてください。

HCP Terraform / Terraform Enterpriseでの推奨代替手段

HCP TerraformまたはTerraform Enterpriseを使用している場合、公式ではterraform_remote_stateよりもtfe_outputsデータソースの使用を推奨しています。tfe_outputsはoutputsのフェッチにワークスペースステートへのフルアクセスを必要としないためよりセキュアです。

# HCP Terraform での推奨方法
data "tfe_outputs" "network" {
  organization = "my-org"
  workspace    = "network-prod"
}

resource "aws_instance" "app" {
  subnet_id = data.tfe_outputs.network.values.subnet_id
  # ...
}

terraform_remote_stateの代替パターン

公式ドキュメントでは、可能な場合はステートを直接共有するよりも、専用のデータストアを使用することを推奨しています。この方法では共有情報とステートスナップショットに異なるアクセス制御を適用でき、Terraform以外のシステムからもアクセス可能になります:

データ共有の仕組み書き込み読み取り
Amazon SSM Parameter Storeaws_ssm_parameter リソースaws_ssm_parameter データソース
Amazon S3aws_s3_object リソースaws_s3_object データソース
Amazon Route53aws_route53_record リソースDNS参照
HashiCorp Consulconsul_key_prefix リソースconsul_key_prefix データソース
HCP Terraformoutputsブロックtfe_outputs データソース
Kubernetes ConfigMapkubernetes_config_map リソースkubernetes_config_map データソース

まとめ

terraform_remote_stateは複数のTerraform構成間でoutputsを共有するための組み込みデータソースです。

  • 参照できるのはroot module outputsのみ(ネストモジュールは不可)
  • セキュリティリスクあり:outputsにアクセスできるユーザーはステート全体にアクセスできる
  • HCP Terraform利用時はより安全なtfe_outputsを推奨
  • 可能な場合はSSM Parameter Store等の専用データストアへの切り替えを検討

シンプルなマルチモジュール構成の出力共有には有効ですが、センシティブなデータを扱う環境では代替手段を検討することが重要です。

関連リソース