我在Azure中设置了两个应用程序服务。”父级和子级都公开APIendpoint。
我希望所有子endpoint都需要通过托管身份和AAD进行身份验证,并且我希望所有父endpoint都允许匿名。但是在Azure中,我希望将父应用服务设置为具有调用子应用服务的权限。因此,子endpoint只能通过使用父endpoint访问(或者如果您对用户帐户拥有直接使用儿童的权限)。
在Azure门户中:
身份验证/授权
身份
访问控制(IAM)
通过以上所有设置:
如果不使用客户端ID/机密/密钥/等等,我认为托管身份背后的想法是把所有这些都扔出窗外,鉴于上述所有情况,父母应该能够给孩子打电话吗?如果是这样,我的设置有什么错误?
扩展已接受的答案。
>
您需要在目标应用注册的清单中定义“应用角色”。这是用于表示资源(API应用服务)的应用注册。
然后,使用Azure CLI将该“应用程序角色”的权限授予企业应用程序(为客户端应用程序设置托管标识时生成的应用程序角色)。有关详细步骤,请参阅本文中的“API和其他Azure AD注册应用程序”https://blog.yannickreekmans.be/secretless-applications-add-permissions-to-a-managed-identity/
授予权限后,您可以使用以下方法检索令牌。下面的代码段使用Azure。Identity(身份),它现在是Azure中托管身份的推荐库。
public class AzureAdTokenRetriever : IAzureAdTokenRetriever
{
private readonly ILogger<AzureAdTokenRetriever> logger;
private readonly IMemoryCache inMemoryCache;
public AzureAdTokenRetriever(
ILogger<AzureAdTokenRetriever> logger,
IMemoryCache inMemoryCache)
{
this.logger = logger;
this.inMemoryCache = inMemoryCache;
}
public async Task<string> GetTokenAsync(string resourceId, string scope = "/.default")
{
var resourceIdentifier = resourceId + scope;
if (inMemoryCache.TryGetValue(resourceIdentifier, out var token))
{
this.logger.LogDebug("Token for {ResourceId} and {Scope} were fetched from cache", resourceId, scope);
return (string)token;
}
var tokenCredential = new DefaultAzureCredential();
var accessToken = await tokenCredential.GetTokenAsync(
new TokenRequestContext(new [] { resourceIdentifier }), CancellationToken.None)
.ConfigureAwait(false);
// Set cache options with expiration 5 minutes before the token expires
var cacheEntryOptions = new MemoryCacheEntryOptions().SetAbsoluteExpiration(accessToken.ExpiresOn.AddMinutes(-5));
inMemoryCache.Set(resourceIdentifier, accessToken.Token, cacheEntryOptions);
this.logger.LogDebug("Token for {ResourceId} and {Scope} saved in cache with expiration of {TokenExpiry}",
resourceId, scope, cacheEntryOptions.AbsoluteExpiration);
return accessToken.Token;
}
}
如果不使用客户端ID/机密/密钥/等等,我认为托管身份背后的想法是把所有这些都扔出窗外,鉴于上述所有情况,父母应该能够给孩子打电话吗?如果是这样,我的设置有什么错误?
对于当前的设置,我注意到两件事。
1.使用托管身份获取令牌以从“父”调用“子”服务endpoint
托管身份仅为您的应用程序服务提供身份(无需管理/维护应用程序机密或密钥)。然后可以使用此标识为不同的Azure资源获取令牌。
但使用此身份并为相关资源获取令牌仍然是您的应用程序的责任。在这种情况下,相关资源将是您的“儿童”API。我认为这可能是您现在缺少的部分。
有关Microsoft文档的相关文档-如何为应用程序服务和Azure功能使用托管身份
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的令牌。在您的示例中,您将用“儿童”服务的标识符Uri替换https://vault.azure.net
。它通常设置为https://
如果您没有使用C#/。NET上的相同Microsoft文档链接还提供了有关如何使用托管身份和来自任何平台的基于REST的调用获取令牌的指导。使用REST协议
这是一篇博文,也很好地介绍了-使用托管服务标识(MSI)调用Azure AD保护网站
2、Azure RBAC角色分配不同于您可能要使用的Azure AD角色
我看到您已从IAM将贡献者角色分配给父应用服务的身份。此角色分配适用于Azure RBAC,有助于授予管理资源的权限,但Azure AD角色声明的工作方式不同。
如果您要做的是为父应用程序分配角色,可以在子应用程序中选中该角色,然后才允许调用,则有不同的设置方法。
首先,我要提到的是,这种基于角色的设置只适用于一些高级场景,并不是必须的。按照上述第1点中的步骤操作后,您应该能够从“父”调用“子”服务。
现在,一旦从父母到孩子的呼叫正常工作,您可能希望将对孩子应用程序服务的访问限制为仅“父母”或少数有效应用程序。这里有两种方法可以实现这一点。
这两种方法都在此处的Microsoft文档中进行了说明-Microsoft identity platform和OAuth 2.0客户端凭据流
相关SO帖子和博客
>
是否有一种方法可以保护仅从特定Azure Logic应用程序调用的Azure函数?
Azure Active Directory-如何将后端API应用注册限制为特定客户端应用注册
https://joonasw.net/view/calling-your-apis-with-aad-msi-using-app-permissions
方法1-使用访问控制列表
当您的“子”API收到令牌时,它可以解码该令牌,并从appid和iss声明中提取客户端的应用程序ID。然后将应用程序与它维护的访问控制列表(ACL)进行比较。
根据您的要求,API可能只授予特定客户端完整权限或所有权限的子集。
方法2-使用应用程序权限或角色
配置您的子API应用程序以公开一组应用程序权限(或角色)。
这种方法更具声明性,因为您定义的应用程序权限需要分配给任何可以调用子api的应用程序。
导航到Azure Active Directory
添加一个新的应用程序角色...使用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接收的身份验证令牌中,您可以检查角色声明集合是否必须包含名为“MyAPIValidClient”的角色,否则您可以拒绝调用,并出现未经授权的异常。
现在我正在使用AAD应用程序使服务成为= AAD应用程序 流程如下所示: 服务A:从托管标识获取令牌 服务A:转到KeyVault,出示令牌并获取AAD应用程序的秘密 服务A:转到AAD,提供一个秘密并为特定资源请求一个令牌 服务A:拨打服务B 服务B:验证令牌和资源 我想知道是否可以向我的服务注册托管标识,因此如果提供托管标识令牌,则服务B可以信任服务A。类似于这样: 服务A:从托管身份获取令牌
我正在尝试设置Azure功能,以将我们的应用程序服务计划扩展到在工作时间更大,在工作时间以外更小。我从这个问题的答案中得出结论。 当我在本地运行它时,它可以工作,并且实际上在我们的Azure应用服务计划上执行了扩展(我相信是通过Azure CLI)。但是,当此Azure Function部署到Azure时,它找不到任何应用服务计划。它点击块并返回。我已为已部署的Azure Function打开托管
我在Azure App Services中部署了一个Docker容器。我有一个可以调用的公共API,它返回“Hello world”。 我想在我的应用程序中使用Azure托管标识,所以我在Azure门户中启用了它。根据以下文档,我启用了“系统分配”功能:https://docs.microsoft.com/en-us/azure/app-service/overview-managed-ident
Azure服务总线支持托管标识访问,但我发现向队列发送消息的唯一方法是使用这种需要代码和服务总线SDK的方法: 来源:https://github.com/Azure-Samples/app-service-msi-servicebus-dotnethttps://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-ma
我已经尝试按照本教程来验证我的服务总线对,但是,我得到了401。 我在设置中使用以下代码: 然后我这样称呼SB客户: 当我调用我得到一个401错误: 失败:Azure Messaging ServiceBus[82]为标识符myqueue-578624f3-f732-4a9b-2ab0-9adc01949a5a创建发送链接时发生异常。错误消息:“系统。UnauthorizedAccessExcep
我们需要从Azure应用程序服务和Azure功能运行访问Azure服务总线(ASB)的应用程序。我们需要使用用户指定的身份进行身份验证。我们编写以下代码,用于系统分配的标识,但不用于用户分配的标识: 引发此错误: 所以核心错误是找不到指定ClientId/ResourceId的MSI 。看起来我们需要指定客户端id。然后我们发现https://github.com/Azure/azure-sdk-