SQL 用户分配的托管标识的 Azure 连接错误 'Login failed for user'

SQL Azure connection error with User Assigned Managed Identity 'Login failed for user'

我有一个分配了 user assigned managed identity 的函数应用程序,它使用它连接到 SQL 数据库。这几天工作正常,但突然停止工作,没有对 db 或函数应用程序进行任何更改。

Error: Login failed for user '<ClientId>@<TenantId>'.

我在网上搜索,找到ways to look into a more detailed error in sys.event_log. As per this, I see that error is 18456, and state is 68. Unfortunately state 68 for error 18456 is not documented anywhere. (Official doc)。

这就是我创建 SqlConnection 的方式(请注意,这在之前是有效的,并且相同的代码在其他地方也能以完全相同的设置工作):

SqlConnection connection = new SqlConnection("Server=tcp:myserver.database.windows.net,1433;Database=MyDb;");
connection.AccessToken = await new AzureServiceTokenProvider("RunAs=App;AppId=<ClientId>").GetAccessTokenAsync("https://database.windows.net/");

用户是使用以下方法在数据库中创建的:

CREATE USER [<Name of user assigned identity>] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [<Name of user assigned identity>];
ALTER ROLE db_datawriter ADD MEMBER [<Name of user assigned identity>];

有没有关于我接下来可以查看的地方的指示?

注:

  1. 使用 Azure Function Runtime 2.0(dotnet 核心)
  2. 使用 Microsoft.Azure.Services.AppAuthentication 1.4.0(最新稳定版)。

要利用用户分配的身份,您需要提供额外的配置。请参阅 connection string support 了解 AppAuthentication 库。

创建 SQL 用户时,确保使用用户分配的身份 资源的名称而不是站点名称。

Managed Identity 绑定的服务是否已删除并重新创建?如果是这样,Azure AD 中的指纹已更改,这是 SQL 服务器识别的内容。不幸的是,这可能是使用 SQL 数据库的托管身份的少数缺点之一,据我所知,这是唯一需要这样做的服务。尝试删除并重新创建用户,看看是否可行。

如果进行 CI/CD 部署,在每次重新部署连接到它的服务时,有一个简单的 SQL 脚本来删除并重新创建数据库中的用户将是有益的。

如:

BEGIN
DROP USER [MSI NAME]
    CREATE USER [MSI NAME] FROM  EXTERNAL PROVIDER;
    ALTER ROLE db_datareader ADD MEMBER [MSI NAME];
    ALTER ROLE db_datawriter ADD MEMBER [MSI NAME];
END
GO

我找不到根本原因,但我发布了帮助我畅通无阻的内容,希望将来能对其他人有所帮助。

出于某种原因,所有形式的身份验证(服务器的 AAD 管理员除外)在此服务器上均失败。所以不仅user assigned identity authentication failed(上面问题中有描述),contained user auth failed。从数据库中删除用户分配的身份并重新添加无效:

DROP USER [<Name of user assigned identity>];
CREATE USER [<Name of user assigned identity>] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [<Name of user assigned identity>];
ALTER ROLE db_datawriter ADD MEMBER [<Name of user assigned identity>];

同样删除包含的用户并重新创建也不起作用。

DROP USER [ContainedUser];
CREATE USER [ContainedUser] WITH PASSWORD='******';
ALTER ROLE db_owner ADD MEMBER [ContainedUser];

我还注意到次级(即副本)工作正常,而 auth 正在与它作对。所以基本上我的结论是我的小学有问题,不确定到底是什么。

所以我决定重新创建数据库:

  • 我对辅助进行了故障转移。
  • 删除复制link,然后删除坏服务器。 (仅仅删除数据库并执行下面的其余步骤是不够的,我试过了)
  • 重新创建了服务器。
  • 重新配置复制,以便在新服务器上创建数据库作为辅助服务器。
  • 进行了另一次故障转移,以便新创建的数据库成为主数据库。
  • 所有验证工作正常。

我最近遇到了一个非常相似的错误,我只是在将来有人发现问题的情况下发帖。

我得到的错误:Microsoft.Data.SqlClient.SqlException (0x80131904): Login failed for user ''.

这不是一个非常具有描述性的异常,因为实际原因是因为我在建立 SQL 连接时拼错了数据库名称。如果您考虑一下,这是有道理的,因为它找不到我正在寻找的数据库,因此无法连接到其中作为外部提供者创建的托管身份用户。因此 user 之后的 '' 在异常中。

当我将拼写错误的数据库名称改回实际数据库名称时,身份验证再次成功。