使用托管身份在Azure中对应用程序服务进行身份验证的应用程序服务

时间:2019-06-11 16:08:46

标签: azure azure-active-directory azure-web-sites azure-web-app-service

我已经在Azure中设置了两个App Services。 “父母”和“孩子”都公开了API端点。

  • 孩子的端点为“ Get”。
  • 父级具有端点“ Get”和“ GetChild”(使用HttpClient在Child上调用“ Get”)。

我希望所有子终结点终结点都需要通过托管身份和AAD进行身份验证,并且希望所有父终结点终结点都允许匿名。但是,在Azure中,我想将父应用程序服务设置为具有调用子应用程序服务的权限。因此,只能通过使用父级端点(或者如果您拥有用户帐户的权限直接使用子级)来访问子级端点。

在Azure门户中:

身份验证/授权

  • 我在两个App Services上都启用了“ App Service身份验证”。
  • 孩子设置为“使用AAD登录”。
  • 父级设置为“允许匿名请求”。
  • 两个都在“身份验证提供程序”下配置了AAD。

身份

  • 将两个App Services都设置为“开”

访问控制(IAM)

  • 孩子有父母作为角色分配,类型=“应用程序服务或功能应用程序”,角色=“贡献者”

使用上述所有设置:

  • 给孩子打电话->获取,需要我登录
  • 给父母打电话->获取,返回预期的200 OK响应
  • 给父母打电话-> GetChild,返回“ 401-您无权查看此目录或页面”

在不使用客户ID /秘密/密钥/等的情况下,我认为托管身份背后的想法是,鉴于上述所有情况,将所有内容都扔出窗外,父母应该可以给孩子打电话吗?如果是这样,我有什么错误设置吗?

1 个答案:

答案 0 :(得分:0)

  
      
  • 给父母打电话-> GetChild,返回“ 401-您无权查看此目录或页面”
  •   
     

正如我所想的那样,不使用客户端ID /秘密/密钥/等   鉴于身份,托管身份的背后是将所有内容扔到窗外   以上所有,父母应该可以给孩子打电话吗?如果是的话   我设置错了吗?

我在当前设置中注意到两件事。

1。使用托管身份获取令牌以从“父母”调用“子级”服务终结点

受管身份仅向您的应用程序服务提供一个身份(没有管理/维护应用程序秘密或密钥的麻烦)。然后,可以使用此身份获取不同Azure资源的令牌。

但是,使用此身份并获取相关资源的令牌仍然是您的应用程序的责任。在这种情况下,相关资源将是您的“子级” API。我认为这可能是您现在所缺少的部分。

Microsoft文档的相关文档-How to use managed identities for App Service and Azure Functions > Obtaining tokens for Azure resources

using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Azure.KeyVault;
// ...
var azureServiceTokenProvider = new AzureServiceTokenProvider();
string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://vault.azure.net");

// change this to use identifierUri for your child app service. 
// I have used the default value but in case you've used a different value, find it by going to Azure AD applications > your app registration > manifest
string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://<yourchildappservice>.azurewebsites.net");

此C#/。NET示例使用Microsoft.Azure.Services.AppAuthentication nuget程序包并获取Azure Key Vault的令牌。对于您的情况,您将https://vault.azure.net替换为“子”服务的identifierUri。默认情况下,通常通常将其设置为https://<yourappservicename>.azurewebsites.net,但是您可以通过转到Azure AD应用程序,然后找到相关的应用程序注册>清单来找到它的价值。您还可以将applicationId用于目标应用程序(即“子”)来获取令牌。

如果您不使用C#/。NET ,则上面相同的Microsoft Docs链接也提供了有关如何使用托管身份和基于 REST的调用来获取令牌的指南任何平台。 Using REST Protocol

这是一篇博客文章,也很好地介绍了-Call Azure AD protected website using Managed Service Identity (MSI)

2。 Azure RBAC角色分配与您可能要使用的Azure AD角色不同

我看到您已经从IAM为父应用程序服务的身份分配了贡献者角色。此角色分配适用于Azure RBAC,并有助于授予管理资源的权限,但Azure AD角色声明的工作方式有所不同。

如果您要为父应用程序分配角色,可以在子应用程序中检查该角色,然后才允许调用,则可以使用另一种方法进行设置。

我首先要提到的是,这种基于角色的设置是针对高级场景的,并不是真正必须执行的。按照上述第1点中的步骤操作,您应该可以从“父母”调用“儿童”服务。

现在,从父级到子级的呼叫正常工作后,您可能希望将对“子级”应用程序服务的访问限制为仅“父级”或一些有效的应用程序。这是实现此目的的两种方法。

这两种方法均在此处的Microsoft文档中进行了说明-Microsoft identity platform and the OAuth 2.0 client credentials flow

与SO帖子和博客相关

方法1-使用访问控制列表

当“子级” API收到令牌时,它可以对令牌进行解码,并从appidiss声明中提取客户端的应用程序ID。然后,它将应用程序与其维护的访问控制列表(ACL)进行比较。

根据您的要求,API可能只向特定客户端授予全部权限的子集或所有权限。

方法2-使用应用程序权限或角色

配置子API应用程序以公开一组应用程序权限(或角色)。

此方法更具说明性,因为您定义了一个应用程序许可权,该许可权需要分配给可以调用您的child-api的任何应用程序。

导航到Azure Active Directory>应用程序注册> child-api应用程序的应用程序注册>清单

使用json这样添加新的应用角色。

"appRoles": [
{
  "allowedMemberTypes": [
    "Application"
  ],
  "displayName": "Can invoke my API",
  "id": "fc803414-3c61-4ebc-a5e5-cd1675c14bbb",
  "isEnabled": true,
  "description": "Apps that have this role have the ability to invoke my child API",
  "value": "MyAPIValidClient"
}]

将应用权限分配给您的前端应用

New-AzureADServiceAppRoleAssignment -ObjectId <parentApp.ObjectId> -PrincipalId <parentApp.ObjectId> -Id "fc803414-3c61-4ebc-a5e5-cd1675c14bbb" -ResourceId <childApp.ObjectId>

现在,在子api收到的auth令牌中,您可以检查角色声明集合必须包含名为“ MyAPIValidClient”的角色,否则可以拒绝带有未授权异常的调用。