<!-- AI_TASK_START: AI标题翻译 -->
[解决方案] 跨租户 Azure 虚拟中心虚拟网络连接的自动化部署
<!-- AI_TASK_END: AI标题翻译 -->
<!-- AI_TASK_START: AI竞争分析 -->
# 解决方案分析
## 解决方案概述
本文档描述了Azure跨租户Virtual Hubs和Virtual Networks连接的自动化部署方案,旨在解决现代云基础设施中资源互联问题,例如企业合并、收购或多部门协作。该方案针对多租户环境,提供高效的网络连接机制,使用 **Bicep** 和 **Azure Pipelines** 实现自动化。核心目标是简化跨租户资源访问,提升云架构的灵活性和可扩展性。在云计算趋势中,随着企业数字化转型,这种解决方案满足了混合云和多租户场景下的行业需求。
## 实施步骤
1. **创建Service Principal并分配角色**
使用一个Service Principal在主租户中创建 **Virtual WAN** 和 **Virtual Hub**,并授予其在主租户和远程租户的订阅级别 **Contributor** 访问权限。这确保了SPN能够跨租户操作资源,避免了资源组级别权限的局限性。
2. **设置多租户SPN**
在远程租户中运行管理员同意URL(例如,[https://login.microsoftonline.com/{organization}/adminconsent?client_id={client-id}](https://login.microsoftonline.com/{organization}/adminconsent?client_id={client-id})),以创建SPN。然后,为SPN分配远程订阅的Contributor访问权限。该步骤依赖于Azure CLI命令,确保安全登录和权限隔离。
3. **部署资源使用Bicep文件**
- 通过 **Network.bicep** 文件创建 **Virtual WAN**、**Virtual Hub** 和虚拟网络,参数文件(如 _network.main.parameters.json_)控制创建条件,例如仅在指定参数为 _True_ 时建立连接。
- 使用 **RemoteVnetSubnet.bicep** 创建资源组、VNET和子网。
- 通过 **VhubRemoteVnetMapping.bicep** 连接远程VNET到Virtual Hub,涉及Key Vault检索SPN凭证,并运行Azure CLI脚本实现连接。脚本使用双重登录机制(az login),处理多租户认证。
该过程逻辑上依赖于参数化和模块化设计,确保步骤间顺畅衔接,避免手动干预。
## 方案客户价值
- **简化跨租户网络管理**
通过自动化管道减少手动配置,提高部署效率,适用于企业协作场景,帮助业务快速实现资源共享,而无需传统方案的复杂协调。
- **提升资源利用和灵活性**
与传统IaaS架构相比,该方案利用 **Virtual WAN** 实现全局网络拓扑,潜在地降低管理开销;例如,自动化连接可减少人为错误,优化多部门协作的业务流程。
- **潜在成本优化**
虽然文档未量化,但隐含的自动化可减少运维工作量,相比手动部署,可能实现间接成本降低,通过高效资源分配提升整体ROI。
## 涉及的相关产品
- **Azure Virtual WAN**:作为核心网络框架,提供全球规模的连接能力,用于创建和管理Virtual Hubs。
- **Azure Virtual Hub**:在Virtual WAN中充当中心节点,负责跨租户VNET连接,实现流量路由和隔离。
- **Azure Pipelines**:自动化部署工具,结合Bicep模板执行资源创建和连接脚本。
- **Azure Key Vault**:存储SPN凭证,确保敏感信息安全传递到管道参数中。
- **Bicep**:基础设施即代码语言,用于定义和部署Azure资源,提高代码可读性和复用性。
## 技术评估
该方案的技术先进性体现在自动化跨租户连接上,利用 **Bicep** 的声明式语法和Azure CLI脚本提升部署效率和可重复性,适用于动态云环境。然而,可行性依赖于严格的权限管理,如果权限配置不当,可能面临安全风险,如SPN泄露。在大规模组网场景中,优势在于简化复杂网络拓扑,但局限性包括管理复杂度上升,例如多租户登录过程可能增加潜在延迟或故障点,建议结合Azure的监控工具(如Azure Monitor)进行优化。总体上,该方案在多云趋势中具有竞争力,但需注意跨租户合规性挑战。
<!-- AI_TASK_END: AI竞争分析 -->
<!-- AI_TASK_START: AI全文翻译 -->
# 跨租户 Azure 虚拟中心 (Virtual Hub) 虚拟网络连接的自动化部署
**原始链接:** [https://techcommunity.microsoft.com/blog/azurenetworkingblog/automated-deployment-of-cross-tenant-azure-virtual-hubs-virtual-networks-connect/4393709](https://techcommunity.microsoft.com/blog/azurenetworkingblog/automated-deployment-of-cross-tenant-azure-virtual-hubs-virtual-networks-connect/4393709)
**发布时间:** 2025-03-19
**厂商:** AZURE
**类型:** TECH-BLOG
---
Azure 网络博客
# 跨租户 Azure 虚拟中心 (Virtual Hub) 虚拟网络连接的自动化部署
2025 年 3 月 19 日
在现代云基础设施中,跨不同 Azure 租户 (Tenant) 互连资源对于各种业务场景至关重要,例如合并、收购或多部门协作。本文将指导您在虚拟广域网 (Virtual WAN) 中创建虚拟中心 (Virtual Hub),并使用 Bicep 和 Azure 管道连接到另一个租户中的虚拟网络。
管道将使用服务主体 (Service Principal) 来创建和访问两个租户中的资源。客户端 ID 和密钥需要存储在密钥库 (Key Vault) 中,并作为参数传递给管道。

### 多租户服务主体 (Service Principal) 设置和访问
如 [Azure 文档](<https://learn.microsoft.com/en-us/azure/virtual-wan/cross-tenant-vnet-az-cli#connect>) 中所述,我们将在管道中使用以下命令来设置虚拟中心 (Virtual Hub) 与虚拟网络的连接:
az network vhub connection create --resource-group "[resource_group_name]" --name "[connection_name]" --vhub-name "[virtual_hub_name]" --remote-vnet "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/rgName/providers/Microsoft.Network/virtualNetworks/vnetName"
由于使用服务主体运行管道,该服务主体需要在主租户和远程租户的相应订阅上具有贡献者 (Contributor) 访问权限。这可以通过以下方式实现:
##### 1\. 创建服务主体并分配角色
我们将使用单个服务主体来创建虚拟广域网 (Virtual WAN)、虚拟中心 (Virtual Hub) 以及连接到远程虚拟网络。在将包含虚拟广域网和虚拟中心的租户中创建服务主体,并在订阅级别提供贡献者访问权限。
##### 2\. 设置多租户服务主体
- 运行以下 URL 在另一个租户中创建服务主体:[https://login.microsoftonline.com/{organization}/adminconsent?client_id={client-id}](<https://login.microsoftonline.com/{organization}/adminconsent?client_id={client-id}>)。其中 organization 是远程虚拟网络的租户 ID,client ID 是服务主体的应用 ID。
- 为服务主体在虚拟网络所在的订阅上分配贡献者访问权限。
_注意:订阅级别的贡献者访问是多租户设置所需的最低权限。资源组级别的贡献者访问无法正常工作。_
### 代码说明
**代码和参数文件可在[此处](<https://github.com/alishamb/AzureMultiTenantVhubVnetConnection/tree/main>)找到。**
有 3 个主要 Azure Bicep 文件用于管理资源创建:
###### Network.bicep
- 该文件检索所需的模块来创建单个虚拟广域网 (Virtual WAN) 和多个虚拟中心 (Virtual Hub),以及虚拟网络和资源组(s)。命名约定基于环境 (如 TST、PROD 等) 和资源区域 (如 west us、east us 等) 固定。
- 使用的参数文件是 _‘network.main.parameters.json’_。
- 以下代码仅在 createHubVirtualNetworkConnection 设置为 _True_ 时运行。默认情况下,该参数设置为 _False_。
module connectVnetHub '../Modules/VirtualHub/connectVnet.bicep' = if (createHubVirtualNetworkConnection){
name: 'connect-vnet-to-hub'
scope: resourceGroup(vwan.subscriptionID, vwan.resourceGroupName)
params: {
vhubName: 'vwanhub-${env}-${stage}-${vnet.location}-001'
virtualNetworkID: (createVnet) ? virtualnetwork.outputs.resourceId : vnet.id
connectionName: '${purpose}-vnet-${env}'
}
dependsOn: [
vWan
vwanHub
virtualnetwork
]
}
上述模块调用以下 Bicep 文件来创建连接:
param vhubName string
param virtualNetworkID string
param connectionName string
resource vhub 'Microsoft.Network/virtualHubs@2023-04-01' existing = {
name: vhubName
}
resource connectVnet 'Microsoft.Network/virtualHubs/hubVirtualNetworkConnections@2023-04-01' = {
name: connectionName
parent: vhub
properties: {
remoteVirtualNetwork: {
id: virtualNetworkID
}
}
}
###### RemoteVnetSubnet.bicep
- 此 Bicep 文件根据参数文件创建多个资源组、虚拟网络和子网。
- 参数文件名是 _network.remote.parameters.json_。
###### VhubRemoteVnetMapping.bicep
- 此文件调用模块将远程虚拟网络(s) 连接到虚拟中心 (Virtual Hub)。根据区域选择适当的虚拟中心,例如,在 east us 创建的虚拟网络将连接到 east us 中的虚拟中心。
- 需要将多租户服务主体作为参数传递,用于运行模块中的 PowerShell 脚本。
- 服务主体详细信息存储在密钥库中,并使用以下代码检索客户端 ID 和密钥:
param keyVaultName string
param keyVaultResourceGroup string
param keyVaultSubscription string
resource keyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = {
name: keyVaultName
scope: resourceGroup(keyVaultSubscription, keyVaultResourceGroup)
}
targetScope='subscription'
param vnets object [] = []
param vwan object
param env string = 'main'
param stage string = 'prod'
module connectRemoteVnetVhub '../Modules/VirtualHub/connectRemoteVnet.bicep' = [for i in range(0, length(vnets)): {
name: 'connect-${vnets[i].vnetName}-to-vhub'
scope: resourceGroup(vwan.subscriptionID, vwan.resourceGroupName)
params: {
remoteResourceGroup: vnets[i].resourceGroupName
remoteSubscriptionID: vnets[i].subscriptionID
remoteTenant: vnets[i].tenantID
remoteVnetName: vnets[i].vnetName
vhubName: 'vwanhub-${env}-${stage}-${vnets[i].location}-001'
subscriptionID: vwan.SubscriptionID
tenantID: vwan.tenantID
clientID: keyVault.getSecret('clientid-Main')
clientSecret: keyVault.getSecret('clientsecret-Main')
connectionName: '${vnets[i].vnetName}-dns-connection'
location: vnets[i].location
}
}]
该模块包含一个部署脚本资源,用于运行 Bash 脚本以连接虚拟网络和虚拟中心。
resource deploymentScript 'Microsoft.Resources/deploymentScripts@2023-08-01' = {
name: 'connectRemote${remoteVnetName}toVhub'
location: location
kind: 'AzureCLI'
properties: {
arguments: '${tenantID} ${remoteTenant} ${remoteSubscriptionID} ${subscriptionID} ${remoteResourceGroup} ${remoteVnetName} ${connectionName} ${vhubName}'
environmentVariables: [
{
name: 'parentResourceGroupName'
value: resourceGroup().name
}
{
name: 'clientID'
value: clientID
}
{
name: 'clientSecret'
value: clientSecret
}
]
azCliVersion: '2.54.0'
scriptContent: '''
az login --service-principal -u $clientID -p $clientSecret --tenant $2
az account set --subscription $3
az login --service-principal -u $clientID -p $clientSecret --tenant $1
az account set --subscription $4
az extension add --name virtual-wan -y --version 0.3
'''
}
}
<!-- AI_TASK_END: AI全文翻译 -->