7

我正在尝试使用 AAD 帐户连接到 Azure SQL DB,作为我的 Azure 管道的一部分。大致我有以下几点:

具有关联服务连接的 Azure 管道。AAD 管理员设置为(连接的)服务主体的 Azure SQL DB。获取服务主体的持有者令牌的 Azure CLI 任务。

然后我有一个使用不记名令牌连接到数据库的 Azure Powershell 脚本:

$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 手动测试了这个,使用服务连接服务主体登录,请求不记名令牌,然后连接到数据库(使用上面的代码)并且这有效。

如果我比较 Pipeline 测试和 Azure CLi 手动测试的不记名令牌,它们是相同的(除了 exp、uti 和 aio)

有任何想法吗?

4

4 回答 4

1

根据这个文档

这种身份验证方法允许中间层服务获取 JSON Web Tokens (JWT)

您需要使用id_token进行 Azure AD 身份验证。从您的脚本来看,您似乎正在使用管道环境访问令牌。

另一方面,您可以导航到Azure 门户 -> Azure Sql -> 查询编辑器页面。然后您可以选择Active Directory authentication并检查您是否可以成功登录数据库。

天青

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

AAD 管理员

此外,您还可以使用 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 Cloud shell 中运行 Azure CLI 命令:

az login

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

然后你可以获得访问令牌。

访问令牌

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

更新2:

得到它 。如果您将服务主体设置为 AD Admin。手动服务主体类型的服务连接可以工作。

手动的

例如:

- 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。

于 2020-06-24T04:27:11.830 回答
0

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

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

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

于 2020-07-09T10:59:12.320 回答
0

az account get-access-token对我不起作用。然后我将代码完全更改为此并且它有效..这里是一个示例(也注销任何以前的登录,因为有时 $authResult 处于错误状态并且没有访问令牌)。您可以根据自己的需要进行调整。

$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

我还建议将 Sql server AAD 管理员设置为 AAD 组,并将 servcie 主体设置为该组的成员。以这种方式管理起来更容易。

于 2020-07-14T22:34:12.083 回答
0

我知道这是一个有点老的问题,但我遇到了完全相同的问题,在我的情况下,这是由于尝试在我们的 Azure DevOps 管道中的同一 Azure CLI 任务中运行令牌请求和 SQL 命令。

当我将 SQL 命令切换到标准 PowerShell 任务并将令牌作为参数传递时,由于某种原因,这解决了针对数据库的登录问题。我将令牌请求保留在现有的 Azure CLI 任务中,但使用令牌的内容设置了一个输出变量。

我真的不知道为什么会这样......我知道你已经指出你的令牌请求和 SQL 调用已经在单独的脚本中,但我想知道问题是否可能是 SQL 调用在 Azure PowerShell 任务中反对只是一个普通的 PowerShell 吗?Azure PowerShell 任务正在使用的经过身份验证的服务连接与打开数据库连接的调用之间可能存在一些奇怪的交互。

希望这对某人有所帮助-感觉有必要发帖,因为这是一个让我知道我并不孤单的问题

---编辑---

我已切换到将单个脚本作为 Azure PowerShell 任务运行,该任务使用以下方式获取令牌:

(Get-AzAccessToken -ResourceUrl https://database.windows.net).Token

而不是 Azure CLI 命令az account get-access-token

这样就可以毫无问题地在同一脚本中打开 SQL 连接。

于 2021-10-25T15:27:50.597 回答