LoginSignup
4
1

More than 1 year has passed since last update.

Azure での異なる Tenant, Subscription 間での Terraform での VNET Peering 設定

Posted at

はじめに

Azure にて異なる Tenant (Azure AD), Subscription 間で VNET Peering を
Terraform (サービスプリンシパル利用) で実施した内容を記載する

スクリーンショット 2022-04-18 0.40.43.png

実施内容

マルチテナントでの Subscription 間 VNET Peering を Terraform で実施するために、下記を実施した

  1. User Access Administrator 権限設定
  2. Terraform で使用するサービスプリンシパルのマルチテナント化
  3. spoke での Terraform サービスプリンシパルのアクセス許可
  4. spoke でのサービスプリンシパルへの IAM での権限追加
  5. Terraform でのマルチテナント操作での VNet Peering

Azure_VNet-Peering_20220417.png.png

1. User Access Administrator 権限設定

ロールの割り当ての追加をするには、Microsoft.Authorization/roleAssignments/writeが必要で、
組み込みロールで言うと Owner もしくは User Access Administrator (ユーザー アクセス管理者) のロールを持っている必要がある
(Azure ドキュメントの Terraform サービス プリンシパルの作成で例に記載されているContributor/共同作成者では無理なので注意)

User Access Administrator (ユーザー アクセス管理者) のロールを割り当てる

サブスクリプションやリソースグループのアクセス制御(IAM)で設定する

スクリーンショット 2022-04-17 20.49.39.png

ユーザー アクセス管理者をクリックして次へ

スクリーンショット 2022-04-17 20.53.03.png

+メンバーを選択するで選択するユーザをクリックして、選択してクリック
(ここではユーザにしているが、サービスプリンシパルで実施している場合は、サービスプリンシパルを選択)

スクリーンショット 2022-04-17 20.55.19.png

レビューと割り当てを実施して割り当てる

スクリーンショット 2022-04-17 20.56.46.png

2. Terraform サービスプリンシパルのマルチテナント化

サポートされているアカウントの種類:所属する組織のみになっている場合は、マルチテナント対応をする必要がある
所属する組織のみをクリックする

スクリーンショット 2022-04-17 19.37.57.png

下記を選択して、変更する
任意の組織ディレクトリ内のアカウント (任意の Azure AD ディレクトリ - マルチテナント)
スクリーンショット 2022-04-17 19.44.57.png

サポートされているアカウントの種類:複数の組織となっていることを確認

スクリーンショット 2022-04-17 19.49.08.png

API のアクセス許可Microsoft GraphUser.Read 権限を追加 (最初からマルチテナントでサービスプリンシパル作成しているとデフォルトで設定済)

スクリーンショット 2022-04-17 20.02.54.png

スクリーンショット 2022-04-17 20.05.02.png

スクリーンショット 2022-04-17 20.14.51.png

3. spoke への Hub Terraform サービスプリンシパルのアクセス許可

マルチテナント化した Hub 側のサービスプリンシパルのアプリケーション ID (Application(client) ID) を参照する

スクリーンショット 2022-04-17 19.54.39.png

spoke のディレクトリ(テナント)ID(Service Tenant ID) を取得する

スクリーンショット 2022-04-17 19.57.52.png

https://login.microsoftonline.com/<Service Tenant ID>/oauth2/authorize?client_id=<Application (client) ID>&response_type=code&redirect_uri=https%3A%2F%2Fwww.microsoft.com%2F

ブラウザでアクセスして承認する

スクリーンショット 2022-04-17 20.16.08.png

サインインエラーとなるが気にせずこのタブは閉じて良い

スクリーンショット 2022-04-17 20.18.44.png

spoke 側の エンタープライズ アプリケーションに追加したアプリケーション ID でサービスプリンシパルが追加されていることが確認できる

スクリーンショット 2022-04-17 20.20.08.png

4. spoke でのサービスプリンシパルへの IAM での権限追加

ひとつ前で追加した、Hubのアプリケーションのサービスプリンシパルへ spoke の VNET のネットワーク共同作成者権限を付与する

GUI (Azure Portal) で実施する場合

spoke の VNET からアクセス制御 (IAM)へ移動してロールの割り当ての追加を実施する

スクリーンショット 2022-04-16 13.07.27.png

ネットワーク共同作成者を選択する

スクリーンショット 2022-04-17 21.45.57.png

+メンバーを選択するをクリックして、追加したサービスプリンシパルをクリックして、選択をクリックして、
最後に次へをクリック

スクリーンショット 2022-04-17 21.47.43.png

レビューと割り当てをクリックして割り当てる

スクリーンショット 2022-04-17 21.48.48.png

CLI (az-cli) で実施する場合

Spoke VNET のプロパティリソース ID を取得する

スクリーンショット 2022-04-17 21.33.18.png

下記コマンドをユーザー アクセス管理者ロールを持つユーザでログインした状態で実施

az role assignment create --role "Network Contributor" --assignee-object-id <サービスプリンシパルのオブジェクトID> --scope <Spoke VNET リソース ID> --assignee-principal-type ServicePrincipal

下記実行出力例

スクリーンショット 2022-04-17 21.59.13.png

5. Terraform での VNet Peering 作成

Terraform で VNet Peering を作成する

サービスプリンシパルの ID/Password は環境変数に設定してから実施する
(パスワードは作成時を参照)

export ARM_CLIENT_ID=81XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX9
export ARM_CLIENT_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

下記、Terraform コード例
マルチテナント操作のため、provider を alias で複数定義して、auxiliary_tenant_ids を使用する

env/test/japaneast/hub/vnet/spoke-peering-different-subscription/vnet-peering.tf
# Spoke との Peering
module "spoke-peering-infratest2" {
  source = "../../../../../../modules/hub/vnet/spoke-peering-different-subscription"

  hub_resource_group_name  = var.resource_group_name
  hub_virtual_network_name = var.virtual_network_name
  hub_tenant_id            = "ceXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX1"
  hub_subscription_id      = "38XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX7"

  spoke_resource_group_name  = "rg-testinfra2-japaneast-001"
  spoke_virtual_network_name = "vnet-testinfra2-japaneast-001"
  spoke_tenant_id            = "edXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX4"
  spoke_subscription_id      = "a4XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX9"
}
modules/hub/vnet/spoke-peering-different-subscription/main.tf
# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs
provider "azurerm" {
  alias                      = "hub"
  tenant_id                  = var.hub_tenant_id
  subscription_id            = var.hub_subscription_id
  skip_provider_registration = true
  auxiliary_tenant_ids       = [var.spoke_tenant_id, ]
  features {}
  # client_id                  = var.client_id     # ARM_CLIENT_ID
  # client_secret              = var.client_secret # ARM_CLIENT_SECRET
}

provider "azurerm" {
  alias                      = "spoke"
  tenant_id                  = var.spoke_tenant_id
  subscription_id            = var.spoke_subscription_id
  skip_provider_registration = true
  auxiliary_tenant_ids       = [var.hub_tenant_id, ]
  features {}
  # client_id                  = var.client_id     # ARM_CLIENT_ID
  # client_secret              = var.client_secret # ARM_CLIENT_SECRET
}

# https://registry.terraform.io/providers/hashicorp/azurerm/3.1.0/docs/data-sources/virtual_network
data "azurerm_virtual_network" "hub" {
  name                = var.hub_virtual_network_name
  resource_group_name = var.hub_resource_group_name
  provider            = azurerm.hub
}

data "azurerm_virtual_network" "spoke" {
  name                = var.spoke_virtual_network_name
  resource_group_name = var.spoke_resource_group_name
  provider            = azurerm.spoke
}


# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_network_peering
resource "azurerm_virtual_network_peering" "hub-to-spoke" {
  name                         = "peer-${data.azurerm_virtual_network.hub.name}-to-${data.azurerm_virtual_network.spoke.name}"
  resource_group_name          = data.azurerm_virtual_network.hub.resource_group_name
  virtual_network_name         = data.azurerm_virtual_network.hub.name
  remote_virtual_network_id    = data.azurerm_virtual_network.spoke.id
  allow_virtual_network_access = true
  allow_forwarded_traffic      = true
  allow_gateway_transit        = true
  use_remote_gateways          = false
  provider                     = azurerm.hub
}

resource "azurerm_virtual_network_peering" "spoke-to-hub" {
  name                         = "peer-${data.azurerm_virtual_network.spoke.name}-to-${data.azurerm_virtual_network.hub.name}"
  resource_group_name          = data.azurerm_virtual_network.spoke.resource_group_name
  virtual_network_name         = data.azurerm_virtual_network.spoke.name
  remote_virtual_network_id    = data.azurerm_virtual_network.hub.id
  allow_virtual_network_access = true
  allow_forwarded_traffic      = true
  allow_gateway_transit        = false
  use_remote_gateways          = true
  provider                     = azurerm.spoke
}

modules/hub/vnet/spoke-peering-different-subscription/variables.tf
# Local Param
variable "hub_resource_group_name" {}

variable "hub_virtual_network_name" {}

# spoke Param
variable "spoke_virtual_network_name" {}

variable "spoke_resource_group_name" {}


# hub SP Param
variable "hub_tenant_id" {}

variable "hub_subscription_id" {}

# spoke SP Param
variable "spoke_tenant_id" {}

variable "spoke_subscription_id" {}

terraform apply を実行すると、Peering が完了する
下記は spoke 側で vnet の ピアリングから今回作成のピアリング状態が接続済みとなっていることを確認した

スクリーンショット 2022-04-17 23.05.49.png

おわりに

マルチテナントでの VNET Peeirng を実施した
サービスプリンシパルが複雑で、実施するのに非常に苦労した
記載内容も正規手順ではないかもしれないので、ご参考程度でお願いします

参考

4
1
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
4
1