如何使用在托管资源组中具有权限的身份部署托管应用程序?

Posted

技术标签:

【中文标题】如何使用在托管资源组中具有权限的身份部署托管应用程序?【英文标题】:How to deploy a managed application with an identity having permissions within the managed resource group? 【发布时间】:2020-09-04 19:21:33 【问题描述】:

将市场托管应用程序产品/服务部署到客户订阅时,您可以在与托管应用程序关联的托管资源组中创建一个身份。但是,为了使该身份具有任何权限,必须为其分配一个角色。

当发布者和客户在同一个租户中时,可以按预期创建角色分配,并且身份在托管资源组内具有权限。

但是,当客户在不同的租户(和活动目录)中时,我收到以下错误:

在租户“[PUBLISHER TENANT ID]”中找不到委托人。如果您尝试将此角色分配放在租户“[客户租户 ID]”中,则必须指定 delegatedManagedIdentityResourceId 属性

查看提到的delegatedManagedIdentityResourceId,它很快就变得很毛茸茸,我不确定这是我想要走的路,或者它是否能让我到达我需要的地方,即拥有一个身份在托管资源组中有权在托管资源组中执行读/写操作。

谢谢。

【问题讨论】:

【参考方案1】:

所以我有以下运气:

    创建一个以 resourceGroup().id 作为所有者的托管身份 - 此身份似乎只限于客户的租户(我无法使用身份执行任何需要任何类型的订阅/资源访问的任何事情......有趣的是以发布者身份登录时,我可以看到此身份被授予 Owner,但以客户身份登录时什么也没透露?

    创建第二个托管身份 - 并将 (1) 托管身份设置为 delegatedManagedIdentityResourceId 这似乎生成了一个托管身份,该身份现在仅限于客户,因此第二个身份似乎能够分配给它的角色.

我仍然不完全确定我为什么需要这样做...但是现在当我将我的消费者托管身份分配给托管解决方案中的虚拟机时,该虚拟机能够访问托管资源组中的所有资源.而为 VM 分配第一个托管标识给我带来了问题。

ARM

        
            "type": "Microsoft.ManagedIdentity/userAssignedIdentities",
            "apiVersion": "2018-11-30",
            "name": "publisherMI",
            "location": "[parameters('location')]"
        ,
        
            "type": "Microsoft.Authorization/roleAssignments",
            "apiVersion": "2021-04-01-preview",
            "name": "[guid('bootstrapRoleAssignmentId')]",
            "dependsOn": [
                "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'publisherMI')]"
            ],
            "properties": 
                "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions/', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]",
                "principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'publisherMI'), '2018-11-30').principalId]",
                "scope": "[resourceGroup().id]",
                "principalType": "ServicePrincipal"
            
        ,
        
            "type": "Microsoft.ManagedIdentity/userAssignedIdentities",
            "apiVersion": "2018-11-30",
            "name": "consumerMI",
            "location": "[parameters('location')]"
        ,
        
            "type": "Microsoft.Authorization/roleAssignments",
            "apiVersion": "2021-04-01-preview",
            "name": "[guid('consumerMiRoleAssignmentId')]",
            "dependsOn": [
                "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'consumerMI')]",
                "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'publisherMI')]"
            ],
            "properties": 
                "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions/', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]",
                "principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'consumerMI'), '2018-11-30').principalId]",
                "scope": "[resourceGroup().id]",
                "principalType": "ServicePrincipal",
                "delegatedManagedIdentityResourceId" : "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'publisherMI')]"
            
        ,

【讨论】:

【参考方案2】:

对于在市场上发布的托管应用程序,您知道发布者和客户存在于不同的租户中。

现在,当客户部署应用程序时,其意图是发布者将管理托管资源组中的资源。因此,作为模板一部分发生的任何角色分配都将发生在 PUBLISHER 的租户中。因此,这意味着在查找要分配给角色定义的委托人时,部署将仅在 PUBLISHER 租户中查找委托人。

在像您这样的情况下,托管身份是作为模板本身的一部分创建的,身份是在客户租户中创建的,但如果您尝试创建角色分配,它将失败,因为它找不到身份本身在发布者租户中。要解决此问题,您需要指定“delegatedManagedIdentityResourceId”属性。它的值应该是为其创建托管标识的资源的 resourceId。

对于系统分配的标识,这将是具有标识的资源的资源 id(例如,函数应用程序 \ 逻辑应用程序的资源 id) 对于分配的用户,它将是身份本身的资源 ID。

【讨论】:

【参考方案3】:

我遇到了完全相同的问题。我的案例还涉及通过市场报价发布托管应用程序。 实际上有两个相关的问题。

    在部署期间将角色分配给托管资源组将失败。

请注意,这是客户租户中的用户从市场部署此托管应用程序。但是,此 roleAssignments 块正在尝试从发布者的租户中定位主体。但是系统生成的身份是在客户的租户中创建的,因为托管应用程序毕竟是部署到客户的租户中的。

2.

从 mainTemplate.json 创建的托管标识(用户托管标识或系统托管标识)无法访问 mainTemplate.json 中的任何资源。 这是由于市场创建的拒绝声明。因此,即使角色分配以模板中的资源为目标,部署也会显示成功,但不会创建实际分配。

因此解决方法是在发布者的 AD 中创建一个应用程序并将其添加到一个专用组中,如 here 所讨论的那样

然后为此应用程序创建一个客户端密码。这将赋予此客户端 ID 对所有资源的完全权限(毕竟在 admin 组中)。 然后,在托管资源组中运行的任何应用程序代码都必须使用凭据向 AD 进行身份验证。应创建一个密钥保管库来存储凭据,以防止客户读取它。

归根结底,如果您的应用程序代码需要执行 azure 管理 API 来读取信息,则需要这种方法。

【讨论】:

【参考方案4】:

托管标识资源只能访问其自己的租户中的资源。目前托管身份不支持跨租户场景。请参考微软官方documentation中的已知问题。

【讨论】:

以上是关于如何使用在托管资源组中具有权限的身份部署托管应用程序?的主要内容,如果未能解决你的问题,请参考以下文章

托管标识 - 如何在本地调试

使用托管服务身份支持代表流程

如何将 MEAN 堆栈部署到我的托管服务器?

在 Azure 中整合托管标识与身份验证/授权标识

系统分配的托管标识的 Azure ARM 角色分配第一次运行失败

使用身份验证托管的 Blazor Wasm 上出现 Azure 500 错误