You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Pipeline跨租户部署Terraform遇订阅未找到错误求助

跨Azure租户Terraform部署问题解决

问题场景

拥有两个Azure租户:

  • tenantA:仅用于存储代码仓库和Pipeline,无任何订阅,只能通过az login --allow-no-subscriptions登录
  • tenantB:用于部署基础设施,存储Terraform后端状态文件

手动通过az login --service-principal -u "spn_id" -p "spn_secret" --tenant "tenantB_id"登录tenantB后,执行Terraform命令正常。但通过tenantA的Azure Pipeline自动化执行,或登录tenantA后执行Terraform时,出现错误:

Error: Error building ARM Config: obtain subscription(id) from Azure CLI: parsing json result from the Azure CI: waiting for the Azure CLI: exit status 1: ERROR: Subscription 'id' not found. Check the spelling and try again.

核心原因

Terraform默认优先尝试从Azure CLI的当前上下文获取订阅信息,但tenantA本身无订阅,或Pipeline中CLI上下文未正确切换到tenantB的订阅,导致无法找到指定的tenantB订阅ID。同时,Terraform后端初始化阶段可能也依赖CLI上下文,未使用配置的服务主体信息。

解决方案

1. 修复Pipeline中的CLI上下文切换

在Pipeline的登录步骤后,显式设置tenantB的订阅,确保后续操作都使用该订阅上下文:

# 登录tenantB的服务主体
az login --service-principal -u "$SPN_ID" -p "$SPN_SECRET" --tenant "$TENANTB_ID"
# 切换到tenantB的目标订阅
az account set --subscription "$TENANTB_SUBSCRIPTION_ID"
# 可选:验证当前订阅
az account show

2. 完善Terraform后端配置,强制使用服务主体认证

Terraform的azurerm后端初始化时,默认也会尝试读取CLI上下文信息,需在backend配置中添加服务主体认证参数,避免依赖CLI:

terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
    }
  }
  backend "azurerm" {
    tenant_id            = "tenantB_id"
    subscription_id      = "tenantB_subscription_id"
    resource_group_name  = "resource_group_name"
    storage_account_name = "storage_account_name"
    container_name       = "container_name"
    key                  = "key_name"
    # 添加服务主体认证信息
    client_id            = "tenantA_service_principal_id"
    client_secret        = "tenantA_service_principal_secret"
  }
}

provider "azurerm" {
  features {}
  client_id       = "tenantA_service_principal_id"
  client_secret   = "tenantA_service_principal_secret"
  tenant_id       = "tenantB_id"
  subscription_id = "tenantB_subscription_id"
}

3. 使用环境变量传递敏感信息(推荐)

避免在代码中硬编码敏感信息,通过Pipeline变量或环境变量传递,Terraform会自动读取这些变量:

  • 设置以下环境变量:
    • ARM_CLIENT_ID:tenantA中创建的服务主体ID
    • ARM_CLIENT_SECRET:服务主体密钥
    • ARM_TENANT_ID:tenantB的租户ID
    • ARM_SUBSCRIPTION_ID:tenantB的订阅ID

修改后的Terraform配置可简化为:

terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
    }
  }
  backend "azurerm" {
    tenant_id            = "tenantB_id"
    subscription_id      = "tenantB_subscription_id"
    resource_group_name  = "resource_group_name"
    storage_account_name = "storage_account_name"
    container_name       = "container_name"
    key                  = "key_name"
  }
}

provider "azurerm" {
  features {}
}

4. 确保服务主体权限正确

确认tenantA中创建的服务主体在tenantB中拥有足够权限:

  • 对tenantB的目标订阅有参与者或更高权限
  • 对存储Terraform状态的存储账户有存储账户参与者或Blob数据所有者权限

内容的提问来源于stack exchange,提问作者mauek unak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 07:53:09