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

Azure DevOps流水线中az ad app update的JSON转义问题

Azure DevOps流水线中Azure CLI authV2扩展更新Entra ID应用作用域时JSON解析异常问题

问题描述

尝试通过Azure CLI authV2扩展更新Entra ID应用注册的OAuth2权限作用域,本地运行代码时请求负载格式正常,但在Azure DevOps流水线(使用windows-latest代理,PowerShell 7.6.2、Azure CLI 2.67.0、authV2扩展v0.1.3,与本地环境版本一致)中运行时,JSON负载出现异常拆分:

  • 本地正常请求负载:
    {"api": {"oauth2PermissionScopes": [{"adminConsentDisplayName": "user_impersonation", "userConsentDisplayName": "user_impersonation", "value": "user_impersonation", "id": "xxxxxx", "type": "User", "isEnabled": "true", "userConsentDescription": "user impersonation", "adminConsentDescription": "user impersonation"}]}}
    
  • 流水线异常请求负载:
    {"api": "{\"oauth2PermissionScopes\":[{\"adminConsentDescription\":\"user", "impersonation\",\"adminConsentDisplayName\":\"user_impersonation\",\"id\":\"xxxxxx\",\"isEnabled\":\"true\",\"type\":\"User\",\"userConsentDescription\":\"user": "", "impersonation\",\"userConsentDisplayName\":\"user_impersonation\",\"value\":\"user_impersonation\"}]}": ""}
    

经调试确认,本地与流水线中$updateJson和$escapedJson的内容完全一致,问题出在命令行参数传递阶段。

核心代码如下:

$appId = 'xxxxxx'

# 获取API应用注册详情
$appRegApi = (az ad app show --id $appId --query 'api' | ConvertFrom-Json)

# 获取现有作用域
$scopes = $appRegApi.oauth2PermissionScopes

# 构建新的user_impersonation作用域
$scopeId = [guid]::NewGuid().Guid
$userImpersonationScope = [ordered]@{
    adminConsentDescription = "user impersonation"
    adminConsentDisplayName = "user_impersonation"
    id                      = "$scopeId"
    isEnabled               = "true"
    type                    = "User"
    userConsentDescription  = "user impersonation"
    userConsentDisplayName  = "user_impersonation"
    value                   = "user_impersonation"
}

# 构建更新内容
$update = @{
    oauth2PermissionScopes = @($scopes; @($userImpersonationScope))
}
$updateJson = ConvertTo-Json $update -Depth 4 -Compress 
$escapedJson = ConvertTo-Json $updateJson

# 执行更新
az ad app update --id $appId --set api=$escapedJson --debug

问题原因

流水线环境中,PowerShell向Azure CLI传递包含空格的JSON字符串时,命令行解析器会将空格视为参数分隔符,导致adminConsentDescription和userConsentDescription字段中的"user impersonation"被拆分为多个参数,破坏了JSON结构。虽然本地环境也存在空格,但由于终端解析逻辑或PowerShell执行上下文的差异,未触发该问题。

解决方案

方案1:用引号包裹参数避免拆分

修改az ad app update命令,将api=$escapedJson用单引号完整包裹,确保CLI接收完整的JSON字符串:

az ad app update --id $appId --set 'api=$escapedJson' --debug

也可以使用双引号结合转义符:

az ad app update --id $appId --set "api=`"$escapedJson`"" --debug

方案2:通过临时文件传递JSON(推荐)

完全避开命令行参数解析问题,将JSON内容写入临时文件,再通过CLI的@语法读取文件内容:

$appId = 'xxxxxx'

$appRegApi = (az ad app show --id $appId --query 'api' | ConvertFrom-Json)
$scopes = $appRegApi.oauth2PermissionScopes

$scopeId = [guid]::NewGuid().Guid
$userImpersonationScope = [ordered]@{
    adminConsentDescription = "user impersonation"
    adminConsentDisplayName = "user_impersonation"
    id                      = "$scopeId"
    isEnabled               = $true  # 改为布尔值,符合API预期类型
    type                    = "User"
    userConsentDescription  = "user impersonation"
    userConsentDisplayName  = "user_impersonation"
    value                   = "user_impersonation"
}

# 构建完整的api更新对象
$apiUpdate = [ordered]@{
    oauth2PermissionScopes = @($scopes; $userImpersonationScope)
}

# 将JSON写入临时文件
$tempFile = New-TemporaryFile
ConvertTo-Json @{ api = $apiUpdate } -Depth 4 | Out-File $tempFile.FullName -Encoding utf8

# 通过文件参数执行更新
az ad app update --id $appId --set api=@$($tempFile.FullName) --debug

# 清理临时文件
Remove-Item $tempFile.FullName -Force

方案3:优化JSON构建逻辑

直接构建包含api键的完整更新对象,减少转义步骤,同时修正isEnabled的类型为布尔值(API实际期望布尔类型而非字符串):

$appId = 'xxxxxx'

$appRegApi = (az ad app show --id $appId --query 'api' | ConvertFrom-Json)
$scopes = $appRegApi.oauth2PermissionScopes

$scopeId = [guid]::NewGuid().Guid
$userImpersonationScope = [ordered]@{
    adminConsentDescription = "user impersonation"
    adminConsentDisplayName = "user_impersonation"
    id                      = "$scopeId"
    isEnabled               = $true
    type                    = "User"
    userConsentDescription  = "user impersonation"
    userConsentDisplayName  = "user_impersonation"
    value                   = "user_impersonation"
}

# 直接构建完整的更新JSON
$fullUpdate = [ordered]@{
    api = [ordered]@{
        oauth2PermissionScopes = @($scopes; $userImpersonationScope)
    }
}
$fullUpdateJson = ConvertTo-Json $fullUpdate -Depth 4 -Compress

# 用引号包裹传递
az ad app update --id $appId --set "$fullUpdateJson" --debug

验证

执行修改后的代码后,通过--debug参数查看请求负载,确认其结构与本地环境一致,无字符串拆分问题,Entra ID应用注册的作用域可成功更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 19:52:01