本文介绍如何为 Azure 应用服务和 Azure Functions 应用程序创建托管标识,以及如何使用它访问其他资源。
注意
从 2024 年 6 月 1 日开始,新创建的应用服务应用可以生成使用命名约定 <app-name>-<random-hash>.<region>.chinacloudsites.cn
的唯一默认主机名。 例如: myapp-ds27dh7271aah175.westus-01.chinacloudsites.cn
。 现有应用名称保持不变。
myapp-ds27dh7271aah175.chinanorth3-01.chinacloudsites.cn
借助 Azure Active Directory (Azure AD) 的托管标识,应用可以轻松访问其他受 Azure AD 保护的资源(如 Azure Key Vault)。 标识由 Azure 平台托管,无需设置或转交任何机密。 有关 Azure AD 中的托管标识的详细信息,请参阅 Azure 资源的托管标识 。
你的应用程序可以被授予两种类型的标识:
系统分配的标识与你的应用程序相绑定,如果删除应用,标识也会被删除 。 一个应用只能具有一个系统分配的标识。
用户分配的标识 是可以分配给应用的独立 Azure 资源。 一个应用可以具有多个用户分配的标识。
托管标识配置特定于槽。 若要在门户中为部署插槽配置托管标识,请先访问该插槽。 若要在 Azure 门户中查找 Microsoft Entra 租户中 Web 应用或部署槽位的托管标识,请直接从租户的概述 页面中进行搜索。 通常,槽名称与 <app-name>/slots/<slot-name>
类似。
若要执行本文中的步骤,必须对 Azure 资源拥有一组最低权限。 所需的特定权限因方案而异。 下表总结了最常见的方案:
展開資料表
情景
必需的权限
内置角色示例
创建系统分配的标识
Microsoft.Web/sites/write
在应用上方或 Microsoft.Web/sites/slots/write
在槽上方
网站参与者
创建用户分配的标识
Microsoft.ManagedIdentity/userAssignedIdentities/write
用于创建标识的资源组
托管的标识参与者
将用户分配的标识分配给应用
Microsoft.Web/sites/write
在应用上方、Microsoft.Web/sites/slots/write
在槽上方或 对标识的 Microsoft.ManagedIdentity/userAssignedIdentities/*/assign/action
权限
网站参与者 和托管标识操作员
创建 Azure 角色分配
Microsoft.Authorization/roleAssignments/write
超过目标资源范围
基于角色的访问控制管理员 或用户访问管理员
若要启用系统分配的托管标识,请使用以下说明。
在 Azure 门户中 ,转到应用的页面。
在左侧菜单中,选择“设置” >“标识” 。
在“系统分配”选项卡中,将“状态”切换为“启用” 。 然后,选择“保存”。
运行 az webapp identity assign
命令:
az webapp identity assign --resource-group <group-name> --name <app-name>
运行 Set-AzWebApp -AssignIdentity
命令:
Set-AzWebApp -AssignIdentity $true -ResourceGroupName <group-name> -Name <app-name>
运行 Update-AzFunctionApp -IdentityType
命令:
Update-AzFunctionApp -ResourceGroupName <group-name> -Name <function-app-name> -IdentityType SystemAssigned
可以使用 Azure 资源管理器模板自动部署 Azure 资源。 若要了解详细信息,请参阅 “在应用服务中自动执行资源部署 ”和 “在 Azure Functions 中自动执行资源部署 ”。
可以通过在资源定义中包含以下属性来创建具有标识的任何类型 Microsoft.Web/sites
资源:
"identity": {
"type": "SystemAssigned"
}
添加系统分配的标识将告知 Azure 为应用程序创建和管理标识。
例如,Web 应用的模板可能如下 JSON 所示:
{
"apiVersion": "2022-03-01",
"type": "Microsoft.Web/sites",
"name": "[variables('appName')]",
"location": "[resourceGroup().location]",
"identity": {
"type": "SystemAssigned"
},
"properties": {
"name": "[variables('appName')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
"hostingEnvironment": "",
"clientAffinityEnabled": false,
"alwaysOn": true
},
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
]
}
创建网站时,它包含以下属性:
"identity": {
"type": "SystemAssigned",
"tenantId": "<tenant-id>",
"principalId": "<principal-id>"
}
该 tenantId
属性标识身份所属的 Microsoft Entra 租户。 该 principalId
属性是应用程序的新标识的唯一标识符。 在Microsoft Entra ID 中,服务主体的名称与为应用服务或 Azure Functions 实例提供的名称相同。
如果需要在模板的后续阶段引用这些属性,请使用 reference()
模板函数 和 'Full'
选项,如以下示例所示:
{
"tenantId": "[reference(resourceId('Microsoft.Web/sites', variables('appName')), '2018-02-01', 'Full').identity.tenantId]",
"objectId": "[reference(resourceId('Microsoft.Web/sites', variables('appName')), '2018-02-01', 'Full').identity.principalId]",
}
若要创建具有用户分配标识的应用,请创建标识,然后将其资源标识符添加到应用配置。
根据这些说明 创建用户分配的托管标识资源。
在应用页面的左侧菜单中,选择 “设置 >标识 ”。
选择 “已分配的用户 ”,然后选择“ 添加 ”。
搜索之前创建的标识,选择该标识,然后选择“ 添加 ”。
完成这些步骤后,应用将重启。
创建用户分配的标识:
az identity create --resource-group <group-name> --name <identity-name>
az webapp identity assign
运行命令,将标识分配给应用:
az webapp identity assign --resource-group <group-name> --name <app-name> --identities <identity-id>
目前不支持使用 Azure PowerShell 在应用服务中添加用户分配的标识。
创建用户分配的标识:
Install-Module -Name Az.ManagedServiceIdentity -AllowPrerelease
$userAssignedIdentity = New-AzUserAssignedIdentity -Name <identity-name> -ResourceGroupName <group-name> -Location <region>
运行 Update-AzFunctionApp -IdentityType UserAssigned -IdentityId
命令以在 Functions 中分配标识:
Update-AzFunctionApp -Name <app-name> -ResourceGroupName <group-name> -IdentityType UserAssigned -IdentityId $userAssignedIdentity.Id
可以使用 Azure 资源管理器模板自动部署 Azure 资源。 若要了解详细信息,请参阅 “在应用服务中自动执行资源部署 ”和 “在 Azure Functions 中自动执行资源部署 ”。
可以通过在资源定义中包含以下块来创建具有标识的任何类型 Microsoft.Web/sites
资源。 将 <resource-id>
替换为所需身份的资源 ID。
"identity": {
"type": "UserAssigned",
"userAssignedIdentities": {
"<resource-id>": {}
}
}
注意
一个应用程序可以同时具有系统分配的标识和用户分配的标识。 在这种情况下,该 type
属性为 SystemAssigned,UserAssigned
.
添加用户分配的类型告知 Azure 使用为应用程序指定的用户分配标识。
例如,Web 应用的模板可能如下 JSON 所示:
{
"apiVersion": "2022-03-01",
"type": "Microsoft.Web/sites",
"name": "[variables('appName')]",
"location": "[resourceGroup().location]",
"identity": {
"type": "UserAssigned",
"userAssignedIdentities": {
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('identityName'))]": {}
}
},
"properties": {
"name": "[variables('appName')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
"hostingEnvironment": "",
"clientAffinityEnabled": false,
"alwaysOn": true
},
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('identityName'))]"
]
}
创建网站时,它包含以下属性:
"identity": {
"type": "UserAssigned",
"userAssignedIdentities": {
"<resource-id>": {
"principalId": "<principal-id>",
"clientId": "<client-id>"
}
}
}
principalId
属性是用于 Microsoft Entra 管理的标识的唯一标识符。 该 clientId
属性是应用程序的新标识的唯一标识符。 使用它来指定在运行时调用期间要使用的标识。
你需要配置目标资源,以允许从应用进行访问。 对于大多数 Azure 服务,可以通过 创建角色分配 来配置目标资源。
某些服务使用 Azure 基于角色的访问控制以外的机制。 若要了解如何使用标识配置访问权限,请参阅每个目标资源的文档。 若详细了解支持 Microsoft Entra 令牌的资源,请参阅支持 Microsoft Entra 身份验证的 Azure 服务 。
例如,如果 请求令牌 以访问 Azure Key Vault 中的机密,则还必须创建一个角色分配,允许托管标识处理目标保管库中的机密。 否则,Key Vault 会拒绝你的调用,即使你使用了有效的令牌。 Azure SQL 数据库和其他服务也是如此。
重要
用于托管标识的后端服务将为每个资源 URI 维护缓存约 24 小时。 对托管标识的组或角色成员身份的更改可能需要几个小时才能生效。 目前无法在托管身份过期之前强制刷新其令牌。 如果更改托管标识的组或角色成员身份来添加或删除权限,可能需要等待几个小时,才能让使用该标识的 Azure 资源具有正确的访问权限。
有关组或角色成员身份的替代方法,请参阅使用托管标识进行授权的限制 。
通过托管标识,应用可以获取 Azure 资源的令牌,这些资源 Microsoft Entra ID 有助于保护,例如 Azure SQL 数据库、Azure Key Vault 和 Azure 存储。 这些令牌表示访问资源的应用程序,而不是应用程序的任何特定用户。
应用服务和 Azure Functions 提供了内部可访问的 REST 终结点 以用于检索令牌。 可以使用标准 HTTP GET
请求从应用内部访问 REST 终结点。 可以使用每种语言的通用 HTTP 客户端实现请求。
对于 .NET、JavaScript、Java 和 Python,Azure 标识客户端库提供了基于此 REST 终结点的抽象,并简化了开发体验。 连接到其他 Azure 服务非常简单,只需要将凭据对象添加到特定于服务的客户端。
原始 HTTP GET
请求使用 两个提供的环境变量 ,如以下示例所示:
GET /MSI/token?resource=https://vault.azure.cn&api-version=2019-08-01 HTTP/1.1
Host: <ip-address-:-port-in-IDENTITY_ENDPOINT>
X-IDENTITY-HEADER: <value-of-IDENTITY_HEADER>
示例响应可能如以下示例所示:
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token": "eyJ0eXAi…",
"expires_on": "1586984735",
"resource": "https://vault.azure.cn",
"token_type": "Bearer",
"client_id": "00001111-aaaa-2222-bbbb-3333cccc4444"
}
此响应与Microsoft Entra 服务到服务访问令牌请求的响应 相同。 要访问密钥保管库,请将access_token
的值添加到客户端与保管库的连接。
使用以下脚本通过指定 Azure 服务的资源 URI 从本地终结点检索令牌:
$resourceURI = "https://<Entra-resource-URI-for-resource-to-obtain-token>"
$tokenAuthURI = $env:IDENTITY_ENDPOINT + "?resource=$resourceURI&api-version=2019-08-01"
$tokenResponse = Invoke-RestMethod -Method Get -Headers @{"X-IDENTITY-HEADER"="$env:IDENTITY_HEADER"} -Uri $tokenAuthURI
$accessToken = $tokenResponse.access_token
有关 REST 终结点的详细信息,请参阅本文后面的 REST 终结点参考 。
删除系统分配的标识时,会从 Microsoft Entra ID 中删除标识。 删除应用资源本身时,也会自动从 Microsoft Entra ID 中删除系统分配的标识。
在应用页面的左侧菜单中,选择 “设置 >标识 ”。
按照标识类型执行步骤:
对于系统分配的标识:在系统分配 选项卡上,将状态 切换为关闭 。 然后,选择“保存”。
对于用户分配的标识:选择 “用户分配 ”选项卡,选中标识的复选框,然后选择“ 删除 ”。 请选择“是”以确认。
若要删除系统分配的标识,请使用以下命令:
az webapp identity remove --resource-group <group-name> --name <app-name>
若要删除一个或多个用户分配的标识,请使用以下命令:
az webapp identity remove --resource-group <group-name> --name <app-name> --identities <identity-id1> <identity-id2> ...
还可以在--identities
中指定[system]
来移除系统分配的标识。
若要删除应用服务的系统分配标识,请 Set-AzWebApp -AssignIdentity
运行以下命令:
Set-AzWebApp -AssignIdentity $false -Name <app-name> -ResourceGroupName <group-name>
若要删除 Azure PowerShell 中的所有标识(仅限 Azure Functions),请运行以下命令:
# Update an existing function app to have IdentityType "None".
Update-AzFunctionApp -Name <function-app-name> -ResourceGroupName <group-name> -IdentityType None
若要删除 ARM 模板中的所有标识,请使用以下代码:
"identity": {
"type": "None"
}
注意
还可以设置仅禁用本地令牌服务的应用程序设置: WEBSITE_DISABLE_MSI
但是,它将标识保持不变。 工具仍然显示该托管身份处于开启或启用状态。 因此,不建议使用此设置。
具有托管标识的应用通过定义两个环境变量使此终结点可用:
IDENTITY_ENDPOINT
:本地令牌服务的 URL。
IDENTITY_HEADER
:有助于缓解服务器端请求伪造(SSRF)攻击的标头。 平台将对该值进行轮换。
该 IDENTITY_ENDPOINT
变量是应用可从中请求令牌的本地 URL。 若要获取资源的令牌,请向此终结点发出 HTTP GET
请求。 包括以下参数:
展開資料表
参数名称
在
说明
resource
查询
应获取其令牌的资源的 Microsoft Entra 资源 URI。 此资源可以是 支持Microsoft Entra 身份验证 或任何其他资源 URI 的 Azure 服务之一。
api-version
查询
要使用的令牌 API 版本。 请使用 2019-08-01
。
X-IDENTITY-HEADER
标头
IDENTITY_HEADER
环境变量的值。 此标头用于帮助缓解 SSRF 攻击。
client_id
查询
(可选)要使用的用户分配的标识的客户端 ID。 它不能用于包含 principal_id
、mi_res_id
、或 object_id
的请求。 如果省略所有 ID 参数(client_id
、principal_id
、object_id
和 mi_res_id
),则使用系统分配的标识。
principal_id
查询
(可选)要使用的用户分配的标识的主体 ID。 参数 object_id
是可以改用的别名。 它不能用于包含 client_id
、 mi_res_id
或 object_id
。 如果省略所有 ID 参数(client_id
、principal_id
、object_id
和 mi_res_id
),则使用系统分配的标识。
mi_res_id
查询
(可选)要使用的用户分配的标识的 Azure 资源 ID。 它不能用于包含 principal_id
、 client_id
或 object_id
。 如果省略所有 ID 参数(client_id
、principal_id
、object_id
和 mi_res_id
),则使用系统分配的标识。
重要
如果您正在尝试获取用户分配身份的令牌,请包含一个可选的属性。 否则,令牌服务会尝试获取系统分配的身份令牌,该身份可能存在,也可能不存在。
请考虑以下教程: