Azure DevOps构建Pipeline生成Azure SQL DB的.bacpac时身份验证失败
目标
配置带有Service Connection的Azure DevOps构建Pipeline,使用sqlpackage.exe从Azure SQL数据库生成.bacpac文件
已完成配置
- DevOps服务连接:已创建名为
myWebAppManagedIdentity的托管身份Web应用,项目设置中服务连接已勾选“授予所有管道访问权限” - Azure SQL数据库权限:已执行以下SQL语句授予
db_owner权限:
CREATE USER [myWebAppManagedIdentity] FROM EXTERNAL PROVIDER; ALTER ROLE db_owner ADD MEMBER [myWebAppManagedIdentity];
- 构建Pipeline的YAML配置:
trigger: - main pool: vmImage: 'windows-latest' variables: sourceServerName: 'some-srv.database.windows.net' sourceDatabaseName: 'somedb' steps: - script: | "C:\Program Files\Microsoft SQL Server\160\DAC\bin\SqlPackage.exe" /Action:Export /TargetFile:"$(Pipeline.Workspace)/s/$(sourceDatabaseName).bacpac" /SourceConnectionString:"Server=tcp:$(sourceServerName),1433;Initial Catalog=$(sourceDatabaseName);Authentication=Active Directory Managed Identity;MultipleActiveResultSets=False;
报错信息
运行Pipeline时返回错误:
"C:\Program Files\Microsoft SQL Server\160\DAC\bin\SqlPackage.exe" /Action:Export /TargetFile:"D:\a\1/s/somedb.bacpac" /SourceConnectionString:"Server=tcp:some-srv.database.windows.net,1433;Initial Catalog=somedb;Authentication=Active Directory Managed Identity;MultipleActiveResultSets=False;
========================== Starting Command Output ===========================
"C:\Windows\system32\cmd.exe" /D /E:ON /V:OFF /S /C "CALL "D:\a_temp\5670cb81-285e-4e1d-8570-a65f39dff472.cmd""
连接到服务器'tcp:some-srv.database.windows.net,1433'上的数据库'somedb'。
*** ManagedIdentityCredential身份验证不可用。请求的标识未分配给此资源。
解决方案
问题根源是微软托管构建池的虚拟机使用自身系统托管身份,而非你创建的myWebAppManagedIdentity服务连接身份。需通过服务连接获取访问令牌,再传递给SqlPackage.exe完成认证:
修正后的YAML配置
trigger: - main pool: vmImage: 'windows-latest' variables: sourceServerName: 'some-srv.database.windows.net' sourceDatabaseName: 'somedb' serviceConnectionName: 'myWebAppManagedIdentity' # 你的服务连接名称 steps: # 通过服务连接登录Azure CLI,获取SQL数据库访问令牌 - task: AzureCLI@2 inputs: azureSubscription: '$(serviceConnectionName)' scriptType: 'ps' scriptLocation: 'inlineScript' inlineScript: | $token = (az account get-access-token --resource https://database.windows.net/ --query accessToken -o tsv) Write-Host "##vso[task.setvariable variable=sqlAccessToken]$token" # 使用访问令牌认证,执行bacpac导出 - script: | "C:\Program Files\Microsoft SQL Server\160\DAC\bin\SqlPackage.exe" ` /Action:Export ` /TargetFile:"$(Pipeline.Workspace)/s/$(sourceDatabaseName).bacpac" ` /SourceServerName:"$(sourceServerName)" ` /SourceDatabaseName:"$(sourceDatabaseName)" ` /AzureADAccessToken:"$(sqlAccessToken)"
关键说明
- AzureCLI任务:指定服务连接
myWebAppManagedIdentity登录,获取Azure SQL资源的访问令牌并存入变量,确保使用目标托管身份。 - SqlPackage参数调整:放弃连接字符串中的托管身份认证,改用
/AzureADAccessToken传递令牌,匹配服务连接的身份权限。 - 确认
myWebAppManagedIdentity已拥有Azure SQL数据库的db_owner权限(已完成配置)。
内容的提问来源于stack exchange,提问作者felixmc

