Get-AzAccessToken令牌格式及在Bicep部署脚本中使用问题
我有一个在Azure DevOps中作为Bicep DeploymentScript执行的脚本,原本用于执行Azure SQL Server命令,自今年6月5日微软的破坏性变更后失效。目前已采用对应MS Graph新语法,但仍存在以下问题:
(Get-AzAccessToken -ResourceTypeName MSGraph).Token的格式是什么?- 如何在
Invoke-Sqlcmd中使用该令牌,并从Bicep DeploymentScript返回? - 如何获取令牌字符串并从DeploymentScript返回?
注:已尝试使用$token和$secureToken,均未生效。
现有部署脚本代码
resource identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { name: sqlAdminUmiName } var sqlServerHostname = environment().suffixes.sqlServerHostname var tokenResourceUrl = 'https://${substring(sqlServerHostname, 1)}' resource deploymentScriptServerGroupAssignment 'Microsoft.Resources/deploymentScripts@2020-10-01' = { name: name location: location kind: 'AzurePowerShell' identity: { type: 'UserAssigned' userAssignedIdentities: { '${identity.id}': {} } } properties: { azPowerShellVersion: '8.3' arguments: '-dbHost "${dbHost}" -tokenResourceUrl "${tokenResourceUrl}" -dbName "${dbName}" -fxaName "${fxaName}" ' scriptContent: ''' param( [string] $dbHost, [string] $tokenResourceUrl, [string] $dbName, [string] $fxaName, [string] $dbRoleNames ) echo "Step 0: about to Install-Module Microsoft.Graph -Force" Install-Module -Name SqlServer -Force Import-Module -Name SqlServer $token = (Get-AzAccessToken -ResourceTypeName MSGraph).Token echo "Step 1: token - $token" $secureToken = ConvertTo-SecureString $token -AsPlainText -Force echo "Step 2: secureToken - $secureToken" $query = @() $query += "DROP USER IF EXISTS `"$fxaName`"" $query += "CREATE USER `"$fxaName`" FROM external provider" $query += "ALTER ROLE db_owner ADD MEMBER `"$fxaName`"" $query += "ALTER ROLE db_datareader ADD MEMBER `"$fxaName`"" $query += "ALTER ROLE db_datawriter ADD MEMBER `"$fxaName`"" $query += "ALTER ROLE db_ddladmin ADD MEMBER `"$fxaName`"" $query = $query -join ";" Invoke-Sqlcmd -ServerInstance $dbHost -Database $dbName -AccessToken "$secureToken" -Query $query ''' retentionInterval: 'PT1H' cleanupPreference: 'OnSuccess' forceUpdateTag: currentTime } }
部署错误信息
Microsoft.Data.SqlClient.SqlException (0x80131904): Login failed for user '<token-identified principal>'.
Microsoft.SqlTools.ServiceLayer.BatchParser.BatchParserException: Incorrect syntax was encountered while parsing
同类脚本返回错误(精简片段)
$token = (Get-AzAccessToken -ResourceTypeName MSGraph).Token echo "Step 1: token - $token" $secureToken = ConvertTo-SecureString $token -AsPlainText -Force echo "Step 2: secureToken - $secureToken" Write-Host "##vso[task.setvariable variable=dbToken;isOutput=true]$secureToken" $DeploymentScriptOutputs = @{} $DeploymentScriptOutputs['dbAccess'] = $secureToken
错误信息:
The template output 'dbToken' is not valid: The provided value for the template output 'dbToken' is not valid. Expected a value of type 'String, Uri', but received a value of type 'Object'.
问题1:(Get-AzAccessToken -ResourceTypeName MSGraph).Token的格式
该命令返回的是Base64编码的JWT令牌字符串,由Header、Payload、Signature三部分组成,用.分隔。你可以通过echo $token直接查看完整字符串,但注意不要在生产环境输出敏感令牌内容。
问题2:在Invoke-Sqlcmd中正确使用令牌并返回
你的核心问题有两个:
- 令牌资源目标错误:连接Azure SQL需要的是SQL数据库服务的资源令牌,而非MS Graph的令牌。应使用
Get-AzAccessToken -ResourceUrl $tokenResourceUrl(或直接指定https://database.windows.net/),而非ResourceTypeName MSGraph。 Invoke-Sqlcmd参数类型错误:-AccessToken参数接受明文字符串,不需要将令牌转换为SecureString。
修改后的脚本核心逻辑:
# 替换令牌获取逻辑,目标为SQL资源 $token = (Get-AzAccessToken -ResourceUrl $tokenResourceUrl).Token echo "Step 1: token - $token" # 直接使用明文令牌调用Invoke-Sqlcmd Invoke-Sqlcmd -ServerInstance $dbHost -Database $dbName -AccessToken $token -Query $query
另外,SQL语句拼接时需注意语法规范,建议用Here-String避免引号转义问题:
$query = @" DROP USER IF EXISTS "$fxaName"; CREATE USER "$fxaName" FROM external provider; ALTER ROLE db_owner ADD MEMBER "$fxaName"; ALTER ROLE db_datareader ADD MEMBER "$fxaName"; ALTER ROLE db_datawriter ADD MEMBER "$fxaName"; ALTER ROLE db_ddladmin ADD MEMBER "$fxaName"; "@
问题3:获取令牌字符串并从DeploymentScript返回
$secureToken是SecureString类型,而DeploymentScript的输出仅支持字符串/URI类型,因此直接返回明文令牌$token即可:
# 正确返回令牌字符串到DeploymentScript输出 $DeploymentScriptOutputs = @{} $DeploymentScriptOutputs['dbAccess'] = $token # Azure DevOps任务输出同样使用明文令牌 Write-Host "##vso[task.setvariable variable=dbToken;isOutput=true]$token"
内容的提问来源于stack exchange,提问作者Aiden Dipple

