Azure DevOps执行PowerShell脚本添加应用注册范围遇Schema错误
问题1:Azure DevOps流水线中更新应用注册Scope时的Schema错误
脚本内容
param ( [Parameter(Mandatory = $true)] [string]$serviceAppRegAppId ) $uuid = [guid]::NewGuid() $api = @{ acceptMappedClaims = $null knownClientApplications = @() oauth2PermissionScopes = @( @{ adminConsentDescription = "admin description" adminConsentDisplayName = "admin name" isEnabled = $true id = "$uuid" type = "User" userConsentDescription = "user description" userConsentDisplayName = "user name" value = "amx.read" } ) preAuthorizedApplications = @() requestedAccessTokenVersion = "2" } | ConvertTo-Json write-host "api=$api" $appRegName = az ad app show --id $serviceAppRegAppId --query displayName $appRegNameWithoutQuotes = $appRegName.Trim('"') write-host "Going to add scope to app reg:$appRegNameWithoutQuotes" # Update app registration with App ID URL and api object az ad app update ` --id $serviceAppRegAppId ` --identifier-uris "api://$appRegNameWithoutQuotes" ` --set api="$api"
错误信息
Going to add scope to app reg:apreg-gis-maps-prod-001
ERROR: Property api in payload has a value that does not match schema
问题解析与修复
核心原因
Azure CLI的--set参数无法直接解析带双引号转义的JSON字符串,而Azure DevOps的PowerShell任务对字符串转义的处理比本地VS Code终端更严格:
ConvertTo-Json生成的JSON包含大量双引号,传入--set api="$api"时,会被截断为不完整的JSON结构- 本地终端可能因PowerShell版本或环境差异意外兼容了错误的传参方式,但流水线环境不会
修复方案
方案1:用临时文件传递JSON(最可靠)
# 将JSON写入临时文件 $apiPath = Join-Path $env:TEMP "api-config.json" $api | Out-File -FilePath $apiPath -Encoding utf8 # 使用@符号引用文件路径 az ad app update ` --id $serviceAppRegAppId ` --identifier-uris "api://$appRegNameWithoutQuotes" ` --set api=@$apiPath # 清理临时文件 Remove-Item $apiPath -Force
方案2:逐个添加属性(避免整段JSON)
如果仅需添加Scope,可直接用--add参数单独设置:
# 先设置标识符URI az ad app update --id $serviceAppRegAppId --identifier-uris "api://$appRegNameWithoutQuotes" # 添加Scope az ad app update ` --id $serviceAppRegAppId ` --add api.oauth2PermissionScopes @{ adminConsentDescription="admin description" adminConsentDisplayName="admin name" isEnabled=$true id="$uuid" type="User" userConsentDescription="user description" userConsentDisplayName="user name" value="amx.read" }
问题2:处理az ad app show输出时结果不完整
原始JSON文件(from-azure.json)
{ "api":{ "acceptMappedClaims":null, "knownClientApplications":[ ], "oauth2PermissionScopes":[ { "adminConsentDescription":"Read amx data", "adminConsentDisplayName":"Read amx data", "id":"ff9d6262-eb63-4c94-bdfa-0a33372c87bc", "isEnabled":true, "type":"Admin", "userConsentDescription":"Read amx data", "userConsentDisplayName":"Read amx data", "value":"amx.read" } ], "preAuthorizedApplications":[ ], "requestedAccessTokenVersion":2 } }
原处理脚本
$json = Get-Content -Raw -Path "from-azure.json" $apiConfig = $json | ConvertFrom-Json # Expand the knownClientApplications property $apiConfig.api.knownClientApplications = $apiConfig.api.knownClientApplications | Select-Object -ExpandProperty value $apiConfig.api.oauth2PermissionScopes = $apiConfig.api.oauth2PermissionScopes | Select-Object -ExpandProperty value $apiConfig.api.preAuthorizedApplications = $apiConfig.api.preAuthorizedApplications | Select-Object -ExpandProperty value # Output the custom PowerShell object $apiConfig
问题原因
你误用了Select-Object -ExpandProperty value:
knownClientApplications和preAuthorizedApplications是空数组,没有value属性,执行后会被置为$nulloauth2PermissionScopes中的对象没有名为value的属性(你要提取的是对象内部的value字段,而非数组元素的value属性)
修复后的脚本
如果需要提取oauth2PermissionScopes中的所有value值,应该用ForEach-Object遍历:
$json = Get-Content -Raw -Path "from-azure.json" $apiConfig = $json | ConvertFrom-Json # 提取oauth2PermissionScopes中的value字段 $apiConfig.api.oauth2PermissionScopes = $apiConfig.api.oauth2PermissionScopes | ForEach-Object { $_.value } # 空数组无需处理,保持原样即可 # 输出完整结构 $apiConfig | ConvertTo-Json -Depth 3
正确输出
{ "api": { "acceptMappedClaims": null, "knownClientApplications": [], "oauth2PermissionScopes": [ "amx.read" ], "preAuthorizedApplications": [], "requestedAccessTokenVersion": 2 } }
内容的提问来源于stack exchange,提问作者Rob Bowman
相关产品推荐
相关产品推荐

