【问题标题】:How to get access token to pull Azure Monitor metrics for a specific subscription?如何获取访问令牌以提取特定订阅的 Azure Monitor 指标?
【发布时间】:2020-06-16 08:27:24
【问题描述】:

我们需要生成一个 AAD 访问令牌,该令牌可用于客户端查询特定订阅的 Azure Monitor 指标(通过 Fluent API)。所以要求是: 1. token 只能用于查询特定订阅的指标,不能用于查询其他的指标 2. 只能从 Azure Monitoring 查询指标(我相信是通过 ARM)

我们如何: 1.获取访问令牌? 2. Azure Management Fluent SDK,如何直接使用token?

谢谢!

【问题讨论】:

    标签: azure-active-directory access-token azure-resource-manager azure-monitoring microsoft-identity-platform


    【解决方案1】:

    1.如何获取访问令牌以列出 Azure 资源指标

    一个。创建服务主体并为 sp 分配 Reader 角色。 (我使用 Azure CLI 来执行此操作)

    az login
    az account set --subscription "<your subscription id>"
    az ad sp create-for-rbac -n "readMetric" --role Reader
    

    b.获取访问令牌

    POST /<your sp tenant>/oauth2/token HTTP/1.1
    Host: login.microsoftonline.com
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=client_credentials
    &client_id=<your sp appid>
    &client_secret=<your sp password>
    &resource=https://management.azure.com/
    

    c。列出一个 Azure 资源的指标

    GET https://management.azure.com/{resource id}/providers/microsoft.insights/metrics?api-version=2018-01-01&metricnames=""
    Authorization : Bearer <access_token>
    

    2. Azure Management Fluent SDK,如何直接使用token?

    关于问题,请参考以下步骤

    static async Task Main(string[] args)
            {
           /*
               Please install sdk Microsoft.IdentityModel.Clients.ActiveDirectory and Microsoft.Azure.Management.Fluent 
    
          */
    
                var tenantId = "<your sp tenant>";
                var clientId = "<your sp appId>";
                var clientSecret = "<your sp password>";
                var subscriptionId = "<your subscription id>";
                var context = new AuthenticationContext("https://login.microsoftonline.com/" + tenantId, false);
                var credential = new ClientCredential(clientId: clientId, clientSecret: clientSecret);
                var result = await context.AcquireTokenAsync("https://management.azure.com/", credential);
    
                var token = result.AccessToken;
                var tokenCredentials = new TokenCredentials(token);
                var azureCredentials = new AzureCredentials(
                    tokenCredentials,
                    tokenCredentials,
                    tenantId,
                    AzureEnvironment.AzureGlobalCloud);
                var client = RestClient
                    .Configure()
                    .WithEnvironment(AzureEnvironment.AzureGlobalCloud)
                    .WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
                    .WithCredentials(azureCredentials)
                    .Build();
                var azure = Microsoft.Azure.Management.Fluent.Azure
                              .Authenticate(client, tenantId)
                              .WithSubscription(subscriptionId);
                var resourceId = "/subscriptions/e5b0fcfa-e859-43f3-8d84-5e5fe29f4c68/resourceGroups/jimtest/providers/Microsoft.Compute/virtualMachines/testvm";
                foreach (var metricDefinition in await azure.MetricDefinitions.ListByResourceAsync(resourceId))
                {
                    var metricCollection = await metricDefinition.DefineQuery()
                                    .StartingFrom(DateTime.UtcNow.AddMinutes(-5))
                                    .EndsBefore(DateTime.UtcNow)
                                    .ExecuteAsync();
                    Console.WriteLine("Metrics for '" + resourceId + "':");
                    Console.WriteLine("Namespacse: " + metricCollection.Namespace);
                    Console.WriteLine("Query time: " + metricCollection.Timespan);
                    Console.WriteLine("Time Grain: " + metricCollection.Interval);
                    Console.WriteLine("Cost: " + metricCollection.Cost);
                    foreach (var metric in metricCollection.Metrics)
                    {
                        Console.WriteLine("\tMetric: " + metric.Name.LocalizedValue);
                        Console.WriteLine("\tType: " + metric.Type);
                        Console.WriteLine("\tUnit: " + metric.Unit);
                        Console.WriteLine("\tTime Series: ");
                        foreach (var timeElement in metric.Timeseries)
                        {
                            Console.WriteLine("\t\tMetadata: ");
                            foreach (var metadata in timeElement.Metadatavalues)
                            {
                                Console.WriteLine("\t\t\t" + metadata.Name.LocalizedValue + ": " + metadata.Value);
                            }
                            Console.WriteLine("\t\tData: ");
                            foreach (var data in timeElement.Data)
                            {
                                Console.WriteLine("\t\t\t" + data.TimeStamp
                                        + " : (Min) " + data.Minimum
                                        + " : (Max) " + data.Maximum
                                        + " : (Avg) " + data.Average
                                        + " : (Total) " + data.Total
                                        + " : (Count) " + data.Count);
                            }
                        }
                    }
                }
      }
    

    更多详情请参考document

    【讨论】:

    • 谢谢。请参阅我的单独回复,因为评论太长了。所以基本上我们的服务有一个可以访问多个订阅的 SP。但是,客户端无法访问 SP;它需要向我们的服务请求访问令牌,该令牌仅限于其订阅;然后它使用令牌进行查询(这可以通过 REST API 轻松完成,但不确定 Fluent SDK)。
    • @YuWang 我认为问题已经解决了。如果您还有其他顾虑,我建议您创建一个新问题。
    • 不,不是。我知道如何创建自定义角色、如何创建 SP 以及如何获取令牌。但问题是如果 SP 具有针对多个订阅的多个角色的权限,如何确定获得的令牌的范围。我们不想使用多个 SP。
    【解决方案2】:

    让我再澄清一下我的问题。

    该服务有一个 SP,该 SP 已经有权向 ARM 查询多个订阅。现在有一堆指标客户端正在为每个单独的订阅做指标查询工作。由于安全原因,这些客户端无法访问服务SP;为了查询指标,建议是,对于每个单独的客户端,它可以首先从服务请求一个令牌用于其订阅,并使用该令牌来查询指标。

    现在,每当服务收到来自客户端的令牌请求时,它应该向 AAD 请求访问令牌,该令牌仅限于相应的订阅(因为默认情况下 SP 可以访问多个订阅),然后分发回客户。我们不希望客户端使用获取的令牌来查询另一个订阅的指标或读取指标以外的资源。

    【讨论】:

    • 如果不希望访问令牌读取其他资源,可以创建自定义角色来实现。更多详情请参考docs.microsoft.com/en-us/azure/azure-monitor/platform/…
    • SP 需要在多个订阅中具有多个角色(例如,监视阅读器和贡献者)。我需要知道如何使用此 SP 获取令牌,该令牌仅:1. 具有监视阅读器角色(但没有贡献者权限)。 2. 只针对一个订阅。
    • 据我所知,我们没有办法实现它。当我们使用sp获取access token时,access token会包含sp的所有权限吗?
    猜你喜欢
    • 1970-01-01
    • 2018-06-18
    • 1970-01-01
    • 2012-01-18
    • 1970-01-01
    • 1970-01-01
    • 2012-01-19
    • 1970-01-01
    • 2018-02-17
    相关资源
    最近更新 更多