我有一个托管 Web 应用程序的 Azure Kubernetes 集群,我想与 Azure SQL 数据库进行通信。
我已经验证,使用基于密码的连接字符串时,与 SQL 的连接工作正常,如下所示:
Server=tcp:{DatabaseServerName}.database.windows.net,1433;Initial Catalog={DatabaseName};User ID={UserName};Password=\"{Password}\";Persist Security Info=False;Integrated Security=false;MultipleActiveResultSets=True;Encrypt=True;TrustServerCertificate=False;
该应用程序还已经拥有一个工作负载身份,该身份已经可以连接到其他资源(例如密钥保管库)。换句话说,我有一个服务帐户,其
azure.workload.identity/client-id
注释设置为托管身份的客户端 ID(我们称之为 {UserClientId}
),pod 具有标签 azure.workload.identity/use=true
,并且托管身份本身已正确设置与联合凭证。 Pod 本身添加了以下环境变量:
AZURE_AUTHORITY_HOST : https://login.microsoftonline.com/
AZURE_CLIENT_ID : {UserClientId}
AZURE_FEDERATED_TOKEN_FILE : /var/run/secrets/azure/tokens/azure-identity-token
AZURE_TENANT_ID : {MyTenantId}
应用程序中的DefaultAzureCredentials
成功获取了与分配了适当RBAC角色的资源一起使用的令牌。
完成所有这些工作后,我认为使用 SQL 连接使用托管身份会非常容易,因为我之前已经在 Azure 函数中完成了此操作。
我首先将托管身份注册为数据库上的外部用户,如下所示:
IF NOT EXISTS (SELECT 1 FROM sys.database_principals WHERE [name] = '{AppUserName}')
BEGIN
CREATE USER [{AppUserName}] WITH DEFAULT_SCHEMA=[dbo], SID = {AppUserSid}, TYPE = E
END
IF IS_ROLEMEMBER('db_owner','{AppUserName}') = 0
BEGIN
ALTER ROLE db_owner ADD MEMBER [{AppUserName}]
END
这里,
{AppUserName}
是托管身份的实际名称,{AppUserSid}
是通过此Powershell函数运行的客户端ID(上面的{UserClientId}
)的表示:
Function ConvertTo-Sid {
param (
[string]$appId
)
[guid]$guid = [System.Guid]::Parse($appId)
foreach ($byte in $guid.ToByteArray()) {
$byteGuid += [System.String]::Format("{0:X2}", $byte)
}
return "0x" + $byteGuid
}
完成后,我只需将本文顶部提到的连接字符串替换为以下内容:
Server=tcp:{DatabaseServerName}.database.windows.net,1433;Initial Catalog={DatabaseName};User ID={UserClientId};Authentication=Active Directory Managed Identity;Persist Security Info=False;Integrated Security=false;MultipleActiveResultSets=True;Encrypt=True;TrustServerCertificate=False;
因此,用户 ID 成为工作负载身份的托管身份的客户端 ID。我以为一切都会顺利。但我却得到了以下 SQL 异常:
{
"id": "28795643",
"outerId": "5601771",
"type": "Microsoft.Data.SqlClient.SqlException",
"message": "Received a non-retryable error. Identity Response Code: BadRequest, Response: {\"error\":\"invalid_request\",\"error_description\":\"Identity not found\"}",
"severityLevel": "Error",
"parsedStack": [
{
"level": 0,
"method": "Microsoft.Data.SqlClient.AzureManagedIdentityAuthenticationProvider+<AcquireTokenAsync>d__13.MoveNext",
"assembly": "Microsoft.Data.SqlClient, Version=2.0.20168.4, Culture=neutral, PublicKeyToken=23ec7fc2d6eaa4a5",
"line": 0
}
]
}
关键部分:
Identity not found
那么有人可以帮助我理解我错过了什么吗?为了先解决一些问题,只是澄清一下:
非常感谢您的宝贵时间,我很高兴这是一篇很长的文章:)
我的情况的答案是,我使用的第三方库引用了旧版本的
Microsoft.Data.SqlClient
。
WorkloadIdentityCredential
仅从该库的 v5.1.4 起才受支持,如 在此记录。添加对此版本或更高版本的显式引用使我的 OP 中描述的设置正常工作:)