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

Azure DevOps中Terraform init与其他命令认证上下文不一致问题

Azure DevOps流水线Terraform init认证异常问题解决

上下文

流水线中执行Terraform init的任务片段:

- task: AzureCLI@2                      
      displayName: 'Terraform init'                                 
      inputs:
        azureSubscription: $(SERVICE_CONNECTION)                        
        scriptType: 'bash'                                               
        scriptLocation: 'inlineScript'                           
        inlineScript: |                        
          terraform init \
             -backend-config="resource_group_name=$(REMOTE_STATE_RG)" \
             -backend-config="storage_account_name=$(REMOTE_STATE_SA)" \
             -backend-config="container_name=$(REMOTE_STATE_CONTAINER)" \
             -backend-config="key=terraform.tfstate"  

使用版本:Terraform 1.5.5,azurerm provider 3.68.0,后端配置:

backend "azurerm" {
}

问题

执行Terraform init时返回认证错误:

Initializing the backend... ╷ │ Error: Error building ARM Config:
Authenticating using the Azure CLI is only supported as a User (not a
Service Principal). │ │ To authenticate to Azure using a Service
Principal, you can use the separate 'Authenticate using a Service Principal' │ auth method...
│ Alternatively you can authenticate using the Azure CLI by using a User Account.

但执行Terraform apply的任务却一切正常:

- task: AzureCLI@2                                 
  displayName: 'Terraform apply'                         
  inputs:
    azureSubscription: $(SERVICE_CONNECTION)                        
    scriptType: 'bash'                                               
    scriptLocation: 'inlineScript'                                   
    inlineScript: 'terraform apply --auto-approve terraform.tfplan'

疑问与解答

1. 为何Terraform init与其他命令的认证行为存在差异?

Terraform的后端初始化(init阶段)和资源操作(apply等阶段)使用的认证逻辑相互独立:

  • init阶段对接azurerm后端存储(用于保存tfstate),此时Terraform优先尝试用本地Azure CLI上下文认证,但Azure DevOps中AzureCLI@2任务用服务主体登录后的CLI上下文,不被azurerm后端的认证逻辑支持。
  • apply阶段调用azurerm provider操作Azure资源,azurerm provider可以识别AzureCLI@2任务自动注入的服务主体环境变量(如AZURE_CLIENT_ID、AZURE_TENANT_ID等),因此能正常完成认证。

2. 如何让Terraform init像其他命令一样使用Azure服务主体认证?

两种方案均无需手动获取服务主体密钥,仅依赖现有SERVICE_CONNECTION:

方案1:在AzureCLI@2任务中手动映射环境变量

AzureCLI@2任务登录后会自动设置AZURE_*开头的服务主体环境变量,将其映射为Terraform azurerm后端识别的ARM_*前缀变量即可:

- task: AzureCLI@2                      
  displayName: 'Terraform init'                                 
  inputs:
    azureSubscription: $(SERVICE_CONNECTION)                        
    scriptType: 'bash'                                               
    scriptLocation: 'inlineScript'                           
    inlineScript: |                        
      # 映射AzureCLI注入的SP变量为Terraform后端识别格式
      export ARM_CLIENT_ID=$AZURE_CLIENT_ID
      export ARM_CLIENT_SECRET=$AZURE_CLIENT_SECRET
      export ARM_TENANT_ID=$AZURE_TENANT_ID
      export ARM_SUBSCRIPTION_ID=$AZURE_SUBSCRIPTION_ID
      # 执行init命令
      terraform init \
         -backend-config="resource_group_name=$(REMOTE_STATE_RG)" \
         -backend-config="storage_account_name=$(REMOTE_STATE_SA)" \
         -backend-config="container_name=$(REMOTE_STATE_CONTAINER)" \
         -backend-config="key=terraform.tfstate"  

方案2:使用Azure DevOps原生Terraform任务

改用官方Terraform任务,自动适配服务连接,无需手动处理环境变量:

# 安装指定版本Terraform
- task: TerraformInstaller@0
  displayName: 'Install Terraform 1.5.5'
  inputs:
    terraformVersion: '1.5.5'

# 执行Terraform init,自动用服务连接认证后端
- task: TerraformTaskV4@4
  displayName: 'Terraform init'
  inputs:
    provider: 'azurerm'
    command: 'init'
    backendServiceArm: $(SERVICE_CONNECTION)
    backendAzureRmResourceGroupName: $(REMOTE_STATE_RG)
    backendAzureRmStorageAccountName: $(REMOTE_STATE_SA)
    backendAzureRmContainerName: $(REMOTE_STATE_CONTAINER)
    backendAzureRmKey: 'terraform.tfstate'

内容的提问来源于stack exchange,提问作者Frédéric De Lène Mirouze

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 00:27:46