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?

HCP Terraformにおける1 Workspace <-> 複数SubscriptionのOIDC認証設定方法

0
Last updated at Posted at 2026-03-17

はじめに

Terraform Cloud(TFC)のOpenID Connect (OIDC) 認証を使えば、シークレットを保持せずにAzureへデプロイが可能です。

しかし、複数サブスクリプションをまたぐHub & Spoke構成(VNetピアリングなど)の構築には、複数のプロバイダーおよびOIDC設定が必要になります。

本記事では、Azureプラットフォームに対するTFCのマルチOIDC構成を利用し、Hub/Spoke間のVNetピアリングを構築する手順を解説します。

参考ドキュメント:
Multiple Configurations - Azure Dynamic Provider Credentials | Terraform | HashiCorp Developer


前提条件:対向VNetへの権限について

1. Hub/SpokeのVNetをデプロイするサービスプリンシパル準備

Hub/Spokeそれぞれをデプロイするためのサービスプリンシパルを事前に作成する必要があります。

OIDCを利用するため、作成後資格情報の登録も必要です。

サービスプリンシパル関連の設定は以下を参考にできます。
HCP Terraform WorkspaceでAzure Provider認証にOIDCを利用する

2. 必要なRole付与

複数サブスクリプション間でVNetピアリングを構築する場合、それぞれの認証情報(Service Principal等)に対して、Azure側で事前に以下のRBAC(ロールベースアクセス制御)を設定しておく必要があります。

  • Hub用の認証情報: 対向となる「Spoke側VNet」に対するRead(読み取り)以上の権限(Network Contributorなど)
  • Spoke用の認証情報: 対向となる「Hub側VNet」に対するRead(読み取り)以上の権限(Network Contributorなど)

※互いのVNetを参照・紐づけするために、クロスでの権限付与が必須となります。
※もちろん自サブスクリプションに対する権限も必要になります。


1. TFCの環境変数設定

デフォルトのプロバイダー(Hub用)と、エイリアスプロバイダー(Spoke用)のそれぞれに対して設定を行います。エイリアスを使用する場合、環境変数名の末尾に _<TAG> (今回は _SPOKE)を付与します。

設定する環境変数(Environment Variables)

Key Value 備考
TFC_AZURE_PROVIDER_AUTH true Hub用(デフォルト)
TFC_AZURE_RUN_CLIENT_ID (Hub用のClient ID) Hub用(デフォルト)
TFC_AZURE_PROVIDER_AUTH_SPOKE true Spoke用(SPOKEエイリアス)
TFC_AZURE_RUN_CLIENT_ID_SPOKE (Spoke用のClient ID) Spoke用(SPOKEエイリアス)

2. Terraformコードの実装

実際にTerraformで実装します。
複数OIDCに関連する設定を実施にしているのは、2.1 ~ 2.2です。

2.1 変数の定義

無くてもよさそうですが必須です。

TFCが動的に生成する認証情報を受け取るため、特定の名前 (tfc_azure_dynamic_credentials) のvariable を必ず定義する必要があります。この名前は予約されており、変更できません。

# variables.tf

### -----------------------------------
# HCP Terraform仕様によるvariable
# 名前変更不可
variable "tfc_azure_dynamic_credentials" {
  description = "Object containing Azure dynamic credentials configuration"
  type = object({
    default = object({
      client_id_file_path  = string
      oidc_token_file_path = string
    })
    aliases = map(object({
      client_id_file_path  = string
      oidc_token_file_path = string
    }))
  })
}

### -----------------------------------
# 通常のvariable設定
variable "tenant_id" {
  type = string
}

variable "hub_subscription_id" {
  type = string
}

variable "spoke_subscription_id" {
  type = string
}

2.2 プロバイダーの設定

use_cli = falseuse_oidc = true を明示的に設定し、先ほど定義した tfc_azure_dynamic_credentials からトークンを読み込みます。

ここでの tfc_azure_dynamic_credentials.default...tfc_azure_dynamic_credentials.aliases["<TAG>"]... といった記述は、TFCのDynamic Provider Credentialsを利用する際の「決まり文句(固定の仕様)」です。 独自の名前に変更することはできず、必ずこの記述方法に沿ってファイルパスをプロバイダーに渡す必要があります。

# providers.tf

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 4.0"
    }
  }
}

# デフォルトプロバイダー (Hub用)
provider "azurerm" {
  tenant_id       = var.tenant_id
  subscription_id = var.hub_subscription_id
  use_cli         = false

  # 複数構成を使用するため明示的にtrueに設定
  use_oidc        = true

  # ※ここが決まり文句
  client_id_file_path  = var.tfc_azure_dynamic_credentials.default.client_id_file_path
  oidc_token_file_path = var.tfc_azure_dynamic_credentials.default.oidc_token_file_path

  features {}
}

# エイリアスプロバイダー (Spoke用)
provider "azurerm" {
  alias = "spoke"

  tenant_id       = var.tenant_id
  subscription_id = var.spoke_subscription_id
  
  use_cli         = false
  use_oidc        = true

  # 環境変数の末尾を _SPOKE としたため、キーは "SPOKE" となる。これも決まり文句。
  client_id_file_path  = var.tfc_azure_dynamic_credentials.aliases["SPOKE"].client_id_file_path
  oidc_token_file_path = var.tfc_azure_dynamic_credentials.aliases["SPOKE"].oidc_token_file_path

  features {
    resource_group {
      prevent_deletion_if_contains_resources = false
    }
  }
}

ここまででOIDCの設定が完了です。

2.3 VNetとVNetピアリングの作成例

実際に呼び出し側の設定をします。

ここでは例として、異なるサブスクリプションにVNetを作成し、VNetピアリングします。

ポイントはSpoke側のリソースには明示的に provider = azurerm.spoke を指定することです。

# main.tf

# ---------------------------------------------------------
# Hub側リソース (デフォルトプロバイダー)
# ---------------------------------------------------------
resource "azurerm_resource_group" "hub" {
  name     = "rg-hub-vnet"
  location = "Japaneast"
}

resource "azurerm_virtual_network" "hub" {
  name                = "vnet-hub"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.hub.location
  resource_group_name = azurerm_resource_group.hub.name
}

# ---------------------------------------------------------
# Spoke側リソース (エイリアスプロバイダー)
# ---------------------------------------------------------
resource "azurerm_resource_group" "spoke" {
  provider = azurerm.spoke
  name     = "rg-spoke-vnet"
  location = "Japaneast"
}

resource "azurerm_virtual_network" "spoke" {
  provider            = azurerm.spoke
  name                = "vnet-spoke"
  address_space       = ["10.1.0.0/16"]
  location            = azurerm_resource_group.spoke.location
  resource_group_name = azurerm_resource_group.spoke.name
}

# ---------------------------------------------------------
# VNetピアリングの設定
# ---------------------------------------------------------
# Hub -> Spoke のピアリング
resource "azurerm_virtual_network_peering" "hub_to_spoke" {
  name                      = "peer-hub-to-spoke"
  resource_group_name       = azurerm_resource_group.hub.name
  virtual_network_name      = azurerm_virtual_network.hub.name
  remote_virtual_network_id = azurerm_virtual_network.spoke.id
}

# Spoke -> Hub のピアリング
resource "azurerm_virtual_network_peering" "spoke_to_hub" {
  provider                  = azurerm.spoke
  name                      = "peer-spoke-to-hub"
  resource_group_name       = azurerm_resource_group.spoke.name
  virtual_network_name      = azurerm_virtual_network.spoke.name
  remote_virtual_network_id = azurerm_virtual_network.hub.id
}

これで1つのWorkspace内で複数のOIDCを利用できるようになります。

注意点としては、TFC_AZURE_PROVIDER_AUTHのような環境変数を使う必要があることです。

azurerm providerのargumentを確認すると環境変数ではなく、provider block内にterraformの変数として直接渡してもできそうですが、環境変数の利用が必須でした。
(provider内の引数をうまく認識せずエラーになった)

さいごに

HCP Terraformの仕様によって、一部理解が難しい部分があるものの、一度設定してしまえば簡単に使いまわせそうです。

この記事が参考になれば幸いです。

最後までお読みいただきありがとうございました。

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?