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

如何获取AZURE_CLIENT_ID/SECRET并解决Azure VM启停授权问题

获取AZURE_CLIENT_ID和AZURE_CLIENT_SECRET的分步指南

方法1:使用Azure CLI

  • 登录Azure账户:az login,按提示完成认证
  • 创建带VM权限的服务主体:
    az ad sp create-for-rbac --name "VM-Management-SP" --role "Virtual Machine Contributor" --scopes /subscriptions/<你的订阅ID>/resourceGroups/<目标资源组名称>
    
    执行后会返回JSON结果,其中:
    • appId → 对应AZURE_CLIENT_ID
    • password → 对应AZURE_CLIENT_SECRET
    • tenant → 对应AZURE_TENANT_ID
  • 若需查询已有服务主体信息:
    az ad sp list --display-name "VM-Management-SP" --query "[].{appId:appId, tenant:appOwnerTenantId}"
    

方法2:使用Azure Portal(含Azure DevOps服务连接配置)

步骤1:创建服务主体

  1. 进入Azure Portal → Azure Active Directory → 应用注册 → 新注册
    • 名称:输入服务主体名称(如VM-Management-SP)
    • 支持的账户类型:选择「仅此组织目录中的账户」
    • 重定向URI:可留空,点击「注册」
  2. 在应用注册概述页,复制应用程序(客户端) ID(AZURE_CLIENT_ID)和目录(租户) ID
  3. 进入「证书和密码」→「客户端密码」→「新客户端密码」
    • 填写描述、选择过期时间,点击「添加」
    • 复制生成的密码值(AZURE_CLIENT_SECRET,仅显示一次,务必保存)

步骤2:分配VM操作权限

  1. 进入目标VM所在的资源组 → 访问控制(IAM) → 添加 → 添加角色分配
  2. 角色选择「虚拟机参与者」(遵循最小权限原则,避免使用「参与者」)
  3. 成员类型选择「用户、组或服务主体」,搜索并选中刚创建的服务主体,完成分配

步骤3:关联到Azure DevOps(可选)

  1. 进入Azure DevOps项目 → 项目设置 → 服务连接 → 新建服务连接 → 选择「Azure Resource Manager」
  2. 认证方式选「服务主体(手动)」,填入订阅ID、租户ID、客户端ID、客户端密码,命名后保存

租户ID无效、403授权失败的排查方案

租户ID无效问题

  • 验证租户ID正确性:执行az ad sp show --id <AZURE_CLIENT_ID> --query "appOwnerTenantId",确认返回的租户ID与代码中使用的一致
  • 检查跨租户问题:若VM所在订阅与服务主体所属租户不同,需配置来宾用户访问并重新分配权限
  • 排除输入错误:确保租户ID无多余空格、大小写错误(GUID大小写不敏感,但复制时需完整)

403授权失败问题

  • 检查权限范围:确认服务主体的权限作用域覆盖目标VM/资源组,可通过az role assignment list --assignee <AZURE_CLIENT_ID>查看已分配角色
  • 验证权限生效:尝试用服务主体登录Azure CLI,测试VM操作:
    az login --service-principal -u <AZURE_CLIENT_ID> -p <AZURE_CLIENT_SECRET> --tenant <AZURE_TENANT_ID>
    az vm start --resource-group <资源组> --name <VM名称>
    
  • 确认凭据有效性:若客户端密码过期,重新生成并更新代码中的值
  • 检查订阅状态:确保VM所在订阅处于「活动」状态,无欠费或禁用情况

Go代码修正与优化

以下是修复后的VM启停代码,针对常见错误点进行了优化:

package main

import (
	"context"
	"fmt"
	"os"

	"github.com/Azure/azure-sdk-for-go/sdk/azcore"
	"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
	"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5"
)

func main() {
	// 从环境变量读取配置(禁止硬编码敏感信息)
	config := struct {
		ClientID       string
		ClientSecret   string
		TenantID       string
		SubscriptionID string
		ResourceGroup  string
		VMName         string
	}{
		ClientID:       os.Getenv("AZURE_CLIENT_ID"),
		ClientSecret:   os.Getenv("AZURE_CLIENT_SECRET"),
		TenantID:       os.Getenv("AZURE_TENANT_ID"),
		SubscriptionID: os.Getenv("AZURE_SUBSCRIPTION_ID"),
		ResourceGroup:  "your-resource-group",
		VMName:         "your-vm-name",
	}

	// 验证配置完整性
	if config.ClientID == "" || config.ClientSecret == "" || config.TenantID == "" || config.SubscriptionID == "" {
		fmt.Println("Error: Missing required environment variables")
		return
	}

	// 创建客户端凭据(关键:参数顺序为租户ID、客户端ID、客户端密码)
	cred, err := azidentity.NewClientSecretCredential(
		config.TenantID,
		config.ClientID,
		config.ClientSecret,
		&azidentity.ClientSecretCredentialOptions{},
	)
	if err != nil {
		fmt.Printf("Failed to create credential: %v\n", err)
		return
	}

	// 创建VM管理客户端
	vmClient, err := armcompute.NewVirtualMachinesClient(config.SubscriptionID, cred, &azcore.ClientOptions{})
	if err != nil {
		fmt.Printf("Failed to initialize VM client: %v\n", err)
		return
	}

	// 启动VM示例
	fmt.Printf("Starting VM %s...\n", config.VMName)
	startResp, err := vmClient.Start(context.Background(), config.ResourceGroup, config.VMName, nil)
	if err != nil {
		fmt.Printf("Failed to start VM: %v\n", err)
		return
	}
	fmt.Printf("VM start operation status: %s\n", *startResp.Status)

	// 停止VM示例(取消注释使用)
	/*
	fmt.Printf("Stopping VM %s...\n", config.VMName)
	stopResp, err := vmClient.PowerOff(context.Background(), config.ResourceGroup, config.VMName, nil)
	if err != nil {
		fmt.Printf("Failed to stop VM: %v\n", err)
		return
	}
	fmt.Printf("VM stop operation status: %s\n", *stopResp.Status)
	*/
}

关键修正点

  • 配置安全:使用环境变量注入敏感凭据,避免硬编码泄露风险
  • 凭据创建正确性:确保NewClientSecretCredential的参数顺序为tenantID, clientID, clientSecret,这是常见错误点
  • 前置验证:添加配置完整性检查,提前发现缺失的环境变量
  • 错误信息细化:打印具体错误,Azure SDK的错误会包含权限不足、资源不存在等具体原因,便于排查
  • 最小权限原则:代码中使用Virtual Machine Contributor权限而非全局权限,符合安全最佳实践

内容的提问来源于stack exchange,提问作者Micheal J. Roberts

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 11:52:43