你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。

在 Azure SQL 数据库 中使用数据库级托管标识(预览版)

适用于:Azure SQL 数据库

数据库级托管标识为 Azure SQL 数据库 中的单个数据库赋予其自己的用户分配的托管标识(UAMI)。 具有标识的数据库会以自身身份向 Azure 存储 进行身份验证,而不是以托管它的逻辑服务器的身份。

如果没有数据库级标识,逻辑服务器上的每个数据库都会共享该服务器的托管标识,因此它们都会访问同一存储。 数据库级身份将访问权限缩小到单一数据库,因此你可以只为每个数据库提供它所需的存储空间。

你选择的是数据库范围的凭证,这也是数据虚拟化查询用来读取 Azure Blob 存储 或 Azure Data Lake Storage (ADLS) Gen2 中 Parquet、CSV 和 Delta 文件的同一凭证。 请在两个凭据标识值中选择:

凭据身份 在以下情况下使用
DATABASE MANAGED IDENTITY 存储账户和数据库在同一个 Microsoft Entra 租户里。
DATABASE FEDERATED CLIENT IDENTITY 存储账户属于另一个租户,通过联邦身份凭证(FIC)访问。

Note

作为预览版功能,本文中介绍的技术受制于 Microsoft Azure 预览版补充使用条款。

Prerequisites

  • 一个运行在逻辑服务器上的 Azure SQL 数据库。 所有服务层级和所有 Azure 区域都支持此功能。
  • 同一订阅中用户分配的托管身份。 背景请参见 Microsoft Entra for Azure SQL 中的 Managed identities。
  • 在目标存储账户上分配角色的权限,如 所有者 或 用户访问管理员。
  • 一个用于存放你想查询的文件的 Azure Blob 存储 或 ADLS Gen2 账户。

Important

数据库在数据库级别只能分配一个用户分配的托管标识,而逻辑服务器则可以有多个。 在分配之前,先规划每个数据库的标识。

如果数据库在 数据库层面使用客户管理的密钥,它已经拥有数据库级别的身份,对于跨租户密钥,则有联邦客户端ID。 这个功能使用了同样的两个设置。 授予现有身份或应用存储访问权限,而不是分配新的身份或应用。 如果你分配了不同的身份或应用,首先要让它访问加密密钥。 否则,更新可能失败,或者数据库可能失去对密钥的访问权限。

选择同租户或跨租户

两个教程都会创建数据库范围的凭证并查询外部数据。 它们的不同之处在于身份如何访问存储账户。

在同一租户中使用数据库级别的身份

步骤 1:创建用户分配的托管标识

创建身份,并记录其 资源ID 和 对象(主体)ID。 你需要资源 ID 才能将该标识分配给数据库。 你只需要对象(主)ID用于跨租户演练,其中它用于标识联邦身份凭证的主体。

az identity create \
    --name <identity-name> \
    --resource-group <resource-group> \
    --location <region>

有关其他方法,请参见 “管理用户分配的托管标识”。

步骤2:将身份分配给数据库

把UAMI分配给 数据库,而不是逻辑服务器。 该任务使用与采用客户管理密钥的数据库级透明数据加密(TDE)相同的机制,详见 数据库级客户管理密钥。 关于完整的分配方法集,请参见 为数据库获取或设置托管身份。

要在 Azure 门户中分配标识:

  1. 进入你的SQL数据库。
  2. 在“安全性”下,选择“标识”。
  3. 在 User-Assigned 托管身份下,选择 添加。
  4. 选择你创建的身份,然后选择 添加。
  5. 选择“保存”。

要使用 Azure CLI 分配该标识,请使用 az sql db update:

az sql db update \
    --resource-group <resource-group> \
    --server <server-name> \
    --name <database-name> \
    --assign-identity \
    --user-assigned-identity-id <identity-resource-id>

要使用 PowerShell 指定它,可以使用 Set-AzSqlDatabase:

Set-AzSqlDatabase -ResourceGroupName <ResourceGroupName> -ServerName <ServerName> -DatabaseName <DatabaseName> -AssignIdentity -UserAssignedIdentityId <UserAssignedIdentityId>

身份 资源ID 看起来像 /subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<identity-name>。 在 Azure 门户中的托管身份的属性下找到它。

步骤3:授予身份对存储的访问权限

赋予托管身份对存储账户的读取权限:

  1. 转到存储帐户。
  2. 选择“访问控制”(IAM)。
  3. 选择“添加”>“添加角色分配”。
  4. 选择 存储 Blob 数据读取者角色,然后选择 下一步。
  5. 在 分配访问权限给 中,选择 托管标识。
  6. 选择 “选择成员”,选择你用户分配的托管标识,然后选择 “选择”。
  7. 选择审核 + 分配。

对于ADLS Gen2的更细粒度访问,可以在特定目录上设置访问控制列表(ACL),而不是在账户级别分配角色。 欲了解更多信息,请参见 Azure Data Lake Storage 中的访问控制列表。

步骤4:创建数据库范围的凭据

连接到你的 用户数据库,而不是 master,并创建凭证:

CREATE DATABASE SCOPED CREDENTIAL MyDBIdentityCred
WITH IDENTITY = 'DATABASE MANAGED IDENTITY';

这个凭证不需要机密,也不需要数据库主密钥。 该引擎在查询时解析分配给数据库的标识。

服务器级对应的版本使用不同的标识值。 比较:

-- Server-level identity: every database on the logical server shares this access
CREATE DATABASE SCOPED CREDENTIAL MyServerIdentityCred
WITH IDENTITY = 'MANAGED IDENTITY';

-- Database-level identity: only this database has this access
CREATE DATABASE SCOPED CREDENTIAL MyDBIdentityCred
WITH IDENTITY = 'DATABASE MANAGED IDENTITY';

完整语法请参见 CREATE DATABASE SCOPED CREDENTIAL。

步骤5:创建外部数据源

创建一个指向你的容器的外部数据源,并附加凭证。 使用与你存储类型相匹配的前缀:

存储类型 位置前缀
Azure Blob 存储 abs://
ADLS Gen2 adls://
CREATE EXTERNAL DATA SOURCE MyExternalStorage
WITH (
    LOCATION = 'abs://<container>@<storage-account>.blob.core.windows.net',
    CREDENTIAL = MyDBIdentityCred
);

步骤6:查询数据

用 ad hoc OPENROWSET查询文件:

SELECT TOP 100 *
FROM OPENROWSET(
    BULK 'sales/2026/*.parquet',
    DATA_SOURCE = 'MyExternalStorage',
    FORMAT = 'parquet'
) AS externalData;

或者定义一个外部表用于重复查询:

CREATE EXTERNAL FILE FORMAT ParquetFormat
WITH (FORMAT_TYPE = PARQUET);

CREATE EXTERNAL TABLE dbo.Sales
(
    OrderId int,
    OrderDate date,
    Amount decimal(10, 2)
)
WITH (
    LOCATION = 'sales/2026/',
    DATA_SOURCE = MyExternalStorage,
    FILE_FORMAT = ParquetFormat
);

SELECT TOP 100 * FROM dbo.Sales;

跨租户使用联邦客户端身份

当你的数据库在一个租户里,存储账户在另一个租户时,使用这条路径。 多租户应用注册承载两者之间的信任关系:数据库的UAMI是该应用联邦身份凭证的对象,存储租户授予应用的服务主体对数据的访问权限。

该模式与 适用于透明数据加密的跨租户客户管理密钥 相匹配,因此如果你已经使用该功能,设置看起来很熟悉。

步骤1:注册多租户应用

在存放数据库的租户中,在 Microsoft Entra ID 中注册一个多租户应用,并注明其应用程序(客户端)ID。

有关详细信息,请参阅将应用程序注册到 Microsoft 标识平台。

步骤2:添加联邦身份凭证

给该应用程序添加一个联邦身份凭据,使其信任数据库的用户分配托管身份。 应用程序和托管身份必须属于同一个 Microsoft Entra 租户。

  1. 在应用注册中,选择 证书和密码>联合身份凭据>添加凭据。
  2. 对于 联合凭证场景,选择 托管身份。
  3. 选择你在同租户演练的步骤 1中创建的托管身份。
  4. 确认自动填写的 发行机构 标识的是你的租户。 对于Azure公有云,颁发者是 https://login.microsoftonline.com/<tenant-id>/v2.0。
  5. 确保 Audience 是 api://AzureADTokenExchange,即 Azure 公有云的值。
  6. 输入一个唯一的凭证名称,然后保存。

凭据的主题是被管理身份的 对象(主体)ID,而不是其客户端 ID。 如果你手动配置凭证,要精确复制对象(主体)ID,因为主题区分大小写。 Microsoft Entra ID 在保存凭证时接受错误的发行者、主体或受众值,但令牌交换随后失败。

欲了解更多信息,请参见“配置应用以信任托管身份”。

在持有存储账户的租户中:

  1. 管理员向多租户应用授予同意,该应用在该租户中创建服务主体。
  2. 将 存储 Blob 数据读取器 角色分配给该服务主体,并在该存储帐户上进行分配。 按照 步骤 3:授予身份对存储的访问权限 操作,但对于 分配访问权限给,选择 用户、组或服务主体,然后选择应用程序的服务主体。

步骤4:在数据库中设置联邦客户端ID

在持有数据库的租户中,将用户分配的管理身份分配给数据库,并将步骤1中的应用程序(客户端)ID设置为 联邦客户端ID:

  1. 进入你的SQL数据库。
  2. 在“安全性”下,选择“标识”。
  3. 在 User-Assigned 托管身份下,检查同一租户流程的 步骤 1 中的身份是否被列出。 如果不是,选择 添加,选择标识,然后选择 添加。
  4. 在 联邦客户端身份下,选择应用,然后选择 保存。

用Azure CLI设置:

az sql db update \
    --resource-group <resource-group> \
    --server <server-name> \
    --name <database-name> \
    --assign-identity \
    --user-assigned-identity-id <identity-resource-id> \
    --federated-client-id <application-client-id>

用PowerShell设置:

Set-AzSqlDatabase -ResourceGroupName <ResourceGroupName> -ServerName <ServerName> -DatabaseName <DatabaseName> -AssignIdentity -UserAssignedIdentityId <UserAssignedIdentityId> -FederatedClientId <ApplicationClientId>

步骤5:创建凭据和查询

CREATE DATABASE SCOPED CREDENTIAL MyCrossTenantCred
WITH IDENTITY = 'DATABASE FEDERATED CLIENT IDENTITY';

CREATE EXTERNAL DATA SOURCE PartnerStorage
WITH (
    LOCATION = 'adls://<container>@<storage-account>.dfs.core.windows.net',
    CREDENTIAL = MyCrossTenantCred
);

然后创建一个外部表,或者像OPENROWSET中那样,对运行PartnerStorage。

比较服务器级和数据库级标识

特性 服务器级托管身份 数据库级托管身份
标识范围 逻辑服务器 单一数据库
凭证语法 IDENTITY = 'MANAGED IDENTITY' IDENTITY = 'DATABASE MANAGED IDENTITY'
跨租户存储访问 不支持。 改用共享访问签名 在数据库上设置的联合客户端 ID,用于与 IDENTITY = 'DATABASE FEDERATED CLIENT IDENTITY' 一起使用
存储RBAC粒度 服务器上的每个数据库都有一个标识 每个数据库一个标识
暴露范围 服务器上的所有数据库都共享相同的访问设置 仅限于一个数据库
标识类型 系统分配的或用户分配的 仅限用户指定
需要数据库主密钥 No No

这两种凭证可以共存于同一逻辑服务器及其数据库中。 选择最适合您安全需求的凭据。

地理复制与故障切换

你将标识分配给数据库,因此每个副本都有自己的分配。 在切换前,将地理次级配置得与主副本相同:

  • 将主数据库使用的相同用户分配的托管标识分配给次级数据库。
  • 授予该身份与步骤 3:授予该身份对存储的访问权限中所述相同的存储访问权限。
  • 对于跨租户访问,在二级数据库上设置相同的 联邦客户端身份 。

当你这样配置两个副本时,使用数据库范围凭证的查询在故障切换后依然能正常工作。 该需求与 数据库级客户管理密钥相匹配,而该密钥也需要在每个副本上配置身份。

同样的配置适用于主动异地复制和故障转移组。

Limitations

  • 仅限 Azure SQL 数据库。 Azure SQL 托管实例、SQL Server 和 Azure Synapse Analytics 不支持这些凭证身份。
  • 仅限出站认证。 该功能不改变用户和应用程序向数据库进行身份验证的方式。
  • 在 master 数据库中不受支持。 在用户数据库中创建凭证。
  • 仅限用户分配的托管身份。 系统分配的托管身份其作用域限定为逻辑服务器,因此不能作为数据库级身份。
  • 每个数据库只有一个用户分配的托管身份。
  • 本预览仅涵盖数据虚拟化:CREATE EXTERNAL TABLE 和带有 DATA_SOURCE 的 OPENROWSET。 其他出站功能,如 sp_invoke_external_rest_endpoint,不在作用范围内。

Troubleshoot

创建数据库范围的凭证并不能确认数据库身份是否能获得令牌或访问存储。 错误在你创建外部数据源或运行使用凭证的查询时出现。

数据库身份未配置(错误15858)

你可以在为数据库分配用户分配的托管身份之前,使用 IDENTITY = 'DATABASE MANAGED IDENTITY' 创建一个凭证。 如果查询使用了该凭证,而数据库没有可用于获取令牌的标识,查询将失败,并出现 15858 错误:

Cannot obtain a Microsoft Entra ID token to access storage. Error message: 'Azure SQL Server or Database identity is not configured. Please follow the steps in "Assign a Microsoft Entra managed identity to your Azure SQL" (https://aka.ms/SQLDBMSI)'.

按照 步骤2的描述,为数据库分配一个用户分配的管理身份,赋予其存储账户访问权限,然后重新尝试查询。 仅为逻辑服务器分配身份并不会配置数据库级身份。 如果数据库分配已生效且错误依旧,请联系 Microsoft 支持部门 调查数据库身份配置问题。

Note

追踪标志4675以及使用托管身份备份和恢复到URL中的删除并重建步骤,适用于Azure虚拟机上的SQL Server。 它们不适用于Azure SQL 数据库中的数据库级托管身份。

无法找到或引用凭证(错误46516)

当你创建外部数据源时,Azure SQL 数据库会检查该凭证是否存在于当前数据库中,并且你是否有权限引用它。 如果任一检查都失败,会出现错误46516:

The specified credential cannot be found or the user does not have permission to perform this action.

在包含外部数据源的数据库中创建凭据,检查凭证名称,并确保你有权限引用该凭据。

令牌获取失败(错误15858)

当数据库无法获得Microsoft Entra令牌,且令牌提供者返回理由时,错误15858包含了该理由:

Cannot obtain a Microsoft Entra ID token to access storage. Error message: '<details>'.

使用嵌套错误消息来找出令牌请求失败的原因。 对于跨租户访问,检查应用程序、存储租户中的管理员同意以及联邦身份凭证,详见 “将应用程序配置为信任托管身份”。

读取外部数据时,该标识还需要被授予存储数据角色。 对于同一租户访问,在容器或存储账户上将 Storage Blob Data Reader 授予数据库的用户分配托管身份。 对于跨租户访问,将访问权限授予该应用程序在存储租户中的服务主体。 有关详细信息,请参阅分配用于访问 Blob 数据的 Azure 角色。

文件不存在或无法访问(错误4860)

当文件缺失或无法读取时,会出现错误4860:

Cannot bulk load. The file "<path>" does not exist or you don't have file access rights. See https://go.microsoft.com/fwlink/?LinkId=2374938 for more information.

检查文件是否存在于配置位置。 然后检查请求所用的身份是否可以通过存储数据角色访问它,或者对于 ADLS Gen2,通过路径上的访问控制列表(ACL)访问它。

网络访问被阻断(错误42121和16539)

当逻辑服务器关联到不允许出站流量流向存储账户的网络安全边界时,会出现错误42121:

The operation could not be completed because attempts to connect were denied by the configured Network Security Perimeter.

在边界配置文件中添加存储账户主机名的出站访问规则,或者将存储账户关联到相同的边界。 欲了解更多信息,请参见 Azure SQL 数据库 的网络安全边界。

当逻辑服务器的出站网络被限制,且存储账户不在服务器的出站防火墙规则中时,会出现错误16539:

Operation failed since the external data source '<external-data-source>' has underlying storage account that is not in the list of Outbound Firewall Rules on the server. Please add this storage account to the list of Outbound Firewall Rules on your server and retry the operation.

在外部数据源的位置为确切的存储主机名添加一个出站防火墙规则。 欲了解更多信息,请参见Azure SQL 数据库 和 Azure Synapse Analytics 的出站防火墙规则。

跨租户配置缺失或错误(错误16561和16562)

跨租户查询可能因以下任一错误或错误 4860而失败:

External table '<table-name>' is not accessible because content of directory cannot be listed.
External table '<table-name>' is not accessible because location does not exist or it is used by another process.

这些错误意味着查询无法到达这些文件。 身份可能没有所需的存储角色,网络访问可能被阻断,存储位置可能无法解析,或者令牌可能是属于错误的租户。 要修复此问题,请执行以下操作:

  • 赋予相应的存储数据角色。
  • 允许网络访问存储账户。
  • 将容器包含在外部数据源位置。
  • 使用 DATABASE FEDERATED CLIENT IDENTITY,并按照步骤4中的说明,在数据库上设置联邦客户端 ID。
  • 确认联邦身份凭证的主体与托管身份的对象(主体)ID完全匹配。

故障切换后查询失败

如果故障切换后查询因令牌或授权错误而失败,新的主节点可能没有原主节点所用的用户分配的托管标识。 或者该标识可能在该存储帐户上没有角色分配。 为两个副本分配相同的身份并赋予其存储访问权限,如 地理复制和故障切换中所述。

常见问题解答

服务器级和数据库级凭证能否共存于同一服务器上?

是的,在同一个逻辑服务器和同一个数据库里。 每个凭据的 IDENTITY 值决定查询使用的身份:MANAGED IDENTITY 使用服务器身份,DATABASE MANAGED IDENTITY 使用数据库的身份。

我可以使用系统分配的托管身份吗?

No. 系统分配的托管身份属于逻辑服务器,所以你不能把它范围限定到一个数据库。 使用用户分配的托管标识。

哪些服务层级和地区支持这个预览?

所有Azure SQL 数据库服务层级,涵盖所有Azure区域。

我需要数据库主密钥吗?

No. DATABASE MANAGED IDENTITY和DATABASE FEDERATED CLIENT IDENTITY都不使用秘密,因此不需要主密钥。

这个功能能和 sp_invoke_external_rest_endpoint 一起使用吗?

不在此预览中。 预览内容涵盖了数据虚拟化。