使用用户分配托管身份通过SSMS连接Azure SQL Server失败
用户分配托管身份连接Azure SQL DB失败排查与解决
问题概述
- 环境:Azure SQL DB通过私有端点供SQL Server 2017 VM访问,已启用Entra ID仅认证
- 正常连接方式:服务主体、带MFA的Entra ID账户均可成功连接
- 失败场景:使用用户分配托管身份连接时,SSMS和PowerShell均返回相同错误:
ManagedIdentityCredential authentication is unavailable. The requested identity has not been assigned to this resource.
Status: 400 (Bad Request)
Content: {"error":"invalid_request","error_description":"Identity not found"} - 已完成的配置动作:
- 托管身份加入Azure SQL管理员组
- 身份拥有SQL服务器的
Contributor、SQL DB的SQL DB Contributor权限 - 已授予Graph API的
User.Read.All、GroupMember.Read.All、Application.Read.All角色 - 数据库内执行授权语句:
CREATE USER "sql-managed-identity" FROM EXTERNAL PROVIDER; ALTER ROLE db_datareader ADD MEMBER "sql-managed-identity"; ALTER ROLE db_datawriter ADD MEMBER "sql-managed-identity"; GO - 尝试用托管身份名称、Client ID、Object ID登录,均失败
排查与解决步骤
1. 确认托管身份已分配到发起连接的资源
错误核心是目标资源无法识别托管身份,需重点检查:
- 若从SQL VM发起连接:
- 进入Azure门户的SQL VM资源页,导航至「身份」→「用户分配」标签
- 确认目标托管身份已添加到列表中,未添加则点击「添加」完成分配
- 若从本地/其他客户端发起:
确保客户端能访问Azure实例元数据服务(IMDS:http://169.254.169.254),且输入的Client ID/Object ID无拼写错误
2. 验证SQL DB用户与托管身份的匹配性
执行以下SQL语句,确认创建的外部用户与托管身份的Object ID一致:
SELECT name, principal_id, sid FROM sys.database_principals WHERE name = 'sql-managed-identity';
- 将返回的
sid转换为GUID格式,与托管身份的Object ID(Azure门户托管身份资源页可查)对比 - 若不匹配,删除现有用户后重新创建:
DROP USER "sql-managed-identity"; CREATE USER [托管身份Object ID] FROM EXTERNAL PROVIDER; -- 或使用准确的显示名称 ALTER ROLE db_datareader ADD MEMBER [托管身份Object ID]; ALTER ROLE db_datawriter ADD MEMBER [托管身份Object ID]; GO
3. 确认Entra ID管理员组权限生效
- 进入Azure SQL服务器资源页,导航至「Azure Active Directory」→「设置管理员」
- 确认托管身份所属的组已被设置为SQL服务器的Entra ID管理员,未设置则添加该组
- 组权限生效存在延迟,建议等待10-15分钟后重试
4. 排查私有端点与网络策略
- 确认SQL VM所在虚拟网络与SQL DB私有端点的虚拟网络已通过对等互联/VPN连通
- 检查SQL DB防火墙规则,确保允许SQL VM的子网访问(私有端点场景下,可开启「允许Azure服务和资源访问此服务器」或配置子网规则)
- 验证SQL VM能正常访问Azure IMDS,托管身份认证依赖此服务
5. 验证PowerShell连接语法
使用PowerShell连接时,需明确指定托管身份的Client ID,示例脚本:
$clientId = "托管身份的Client ID" $serverName = "different-vnet-sql.database.windows.net" $databaseName = "你的数据库名" $credential = New-Object Azure.Identity.ManagedIdentityCredential -ArgumentList $clientId $connectionString = "Server=tcp:$serverName,1433;Database=$databaseName;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" $connection = New-Object System.Data.SqlClient.SqlConnection($connectionString) $connection.AccessToken = $credential.GetToken("https://database.windows.net/.default").Token $connection.Open()
- 确保
GetToken的资源URI为https://database.windows.net/.default,此为SQL DB认证的标准资源地址
内容的提问来源于stack exchange,提问作者ekrof
相关产品推荐
相关产品推荐

