无法使用工作负载身份从 Kubernetes (AKS) Web 应用容器连接到 Azure SQL

问题描述 投票:0回答:1

我有一个托管 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

那么有人可以帮助我理解我错过了什么吗?为了先解决一些问题,只是澄清一下:

  • 当我切换到基于密码的连接字符串时,连接工作正常,因此我们不需要谈论网络
  • 工作负载身份已经可以正常连接到其他 Azure 资源

非常感谢您的宝贵时间,我很高兴这是一篇很长的文章:)

sql-server azure kubernetes azure-managed-identity workload-identity
1个回答
0
投票

我的情况的答案是,我使用的第三方库引用了旧版本的

Microsoft.Data.SqlClient

WorkloadIdentityCredential
仅从该库的 v5.1.4 起才受支持,如 在此记录。添加对此版本或更高版本的显式引用使我的 OP 中描述的设置正常工作:)

© www.soinside.com 2019 - 2024. All rights reserved.