连接到Azure SQL数据库AAD的Azure管道-用户“登录失败

y4ekin9u  于 2022-12-04  发布在  其他
关注(0)|答案(5)|浏览(274)

我正在尝试使用AAD帐户连接到Azure SQL DB,作为我的Azure管道的一部分。大致如下:
具有关联服务连接的Azure管道。AAD管理员设置为(连接的)服务主体的Azure SQL DB。获取服务主体的承载令牌的Azure CLI任务。
然后,我有一个Azure Powershell脚本,它使用不记名令牌连接到DB:

$conn = new-object System.Data.SqlClient.SqlConnection
$conn.ConnectionString = "Server=tcp:$($sqlServer),1433;Initial Catalog=$($sqlDB);Persist Security Info=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" 
$conn.AccessToken = $env:ACCESSTOKEN
$conn.Open()

这将导致以下错误:

Login failed for user '<token-identified principal>

允许运行管道的代理通过SQL Server防火墙。
在DB日志中,错误代码为18456,状态为132(AAD故障)。
我已经使用Azure CLI手动测试了这一点,使用服务连接服务主体登录,请求承载令牌,然后连接到数据库(使用上面的代码),这是可行的。
如果我比较管道测试和Azure CLi手动测试的不记名令牌,它们是相同的(除了exp、uti和aio)
有什么想法吗?

ilmyapht

ilmyapht1#

根据该文档:
此身份验证方法允许中间层服务获取JSON Web令牌(JWT)
你需要使用id_tokens进行Azure AD身份验证。从你的脚本来看,你似乎正在使用管道环境访问令牌。
另一方面,你可以导航到Azure门户-〉Azure SQL -〉查询编辑器页面,然后你可以选择Active Directory authentication,并检查你是否可以成功登录到数据库。

如果您在此页面中遇到Login failed for user '<token-identified principal>问题,您可以尝试在SQL Server上将目标帐户添加为Active Directory admin,或创建Map到Azure AD标识的包含用户。

此外,您还可以使用Azure AD帐户和密码登录Azure SQL。
脚本:

$conn = new-object System.Data.SqlClient.SqlConnection
$conn.ConnectionString = "Server=tcp:$($sqlServer),1433;Initial Catalog=$($sqlDB);Persist Security Info=False;User ID:User account;Password=Password;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Authentication=Active Directory Password;" 
$conn.Open()

更新:

对于访问令牌:
您可以尝试在Azure Clould shell中运行Azure CLI命令:

az login

az account get-access-token --resource https://database.windows.net

然后你就能拿到通行令牌了。

根据我的测试,如果您使用此访问令牌连接Azure Sql,它可以按预期工作。

更新2:

获取它。如果您将服务主体设置为AD管理员。则手动服务主体类型服务连接可以工作。

例如:

- task: AzureCLI@2
  displayName: 'Azure CLI '
  inputs:
    azureSubscription: manual service connection name
    scriptType: ps
    scriptLocation: inlineScript
    inlineScript: |
     
     az account get-access-token --resource https://database.windows.net
  enabled: false

访问令牌可用于连接Azure Sql。

l3zydbqr

l3zydbqr2#

请尝试将连接字符串更改为;

"Data Source=<SQLServerName>.database.windows.net,1433;Initial Catalog=<dbName>;"

您使用的访问令牌应该是正确的,因为您是从“www.example.com“生成的https://database.windows.net/。

bhmjp9jg

bhmjp9jg3#

az account get-access-token did NOT work for me. then I completely changed code to this and it worked.. .here is a sample (also logout any previous logins as sometimes $authResult was in faulted state and did not have the access token within). You can tweak this to your needs.

$tenant = "xxxx-xxxx-xxxxxx"
$applicationId = $(Get-AzADServicePrincipal -DisplayName "MyServicePrincipal").ApplicationId
$clientSecret = "yyyy-yyyyy-yyyy" 
$subscriptionId = "xyxy-xyxy-xyxy-xyxy"

$secstr = New-Object -TypeName System.Security.SecureString
$clientSecret.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)}
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $applicationId, $secstr

Connect-AzAccount -Tenant $tenant -SubscriptionId $subscriptionId -ServicePrincipal -Credential $cred

$resourceAppIdURI = 'https://database.windows.net/'

$authority = ('https://login.windows.net/{0}' -f $tenant)
$ClientCred = [Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential]::new($applicationId, $clientSecret)
$authContext = [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext]::new($authority)
$authResult = $authContext.AcquireTokenAsync($resourceAppIdURI, $ClientCred)
$Token = $authResult.Result.AccessToken

$conn = New-Object System.Data.SqlClient.SQLConnection 
$SQLServerName = "sql-myApplicationDbServer-dev.database.windows.net"
$DatabaseName = 'sqldb-myApplicationDb-dev'

$conn.ConnectionString = "Data Source=$SQLServerName;Initial Catalog=$DatabaseName;Connect Timeout=30"
$conn.AccessToken = $($Token)
conn.Open() -- works for me

i'd also suggest to set the Sql server AAD admin to an AAD group, and make the servcie principal as a member of that group. Its easier to manage that way.

rvpgvaaj

rvpgvaaj4#

我知道这是一个有点老的问题,但我遇到了这个完全相同的问题,在我的情况下,这是由于试图在我们Azure DevOps管道中的同一Azure CLI任务中运行令牌请求和SQL命令。
当我将SQL命令切换到标准PowerShell任务并将令牌作为参数传入时,由于某种原因,这解决了针对数据库的登录问题。我将令牌请求保留在现有Azure CLI任务中,但使用令牌的内容设置了一个输出变量。
我真的搞不懂为什么会这样...我知道您已经指出令牌请求和SQL调用已经在单独的脚本中,但我想知道问题是否可能是SQL调用是在Azure PowerShell任务中,而不是在普通PowerShell任务中?Azure PowerShell任务正在使用的经过身份验证的服务连接与打开DB连接的调用之间存在一些奇怪的交互。
希望这能帮助一些人无论如何-感觉被迫张贴,因为这是一个如此的问题,让我知道我不是一个人😂
---编辑---
我已经切换到将单个脚本作为Azure PowerShell任务运行,该任务使用以下命令获取令牌:
(Get-AzAccessToken -ResourceUrl https://database.windows.net).Token
而不是Azure CLI命令az account get-access-token
这样就可以在同一脚本中打开SQL连接,而不会出现问题。

k97glaaz

k97glaaz5#

Azure PowerShell应用程序
资源访问令牌=(获取-AzAccessToken-资源URL https://database.windows.net).令牌
Azure命令行界面
$token = az帐户获取访问令牌--资源https://database.windows.net/--查询“访问令牌”--输出tsv
正如您所看到的,URI中有一个微小的差异(这使得所有的差异)。

相关问题