0

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

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

谢谢!

4

2 回答 2

2

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

在此处输入图像描述

湾。获取访问令牌

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);
                        }
                    }
                }
            }
  }

在此处输入图像描述

更多详细信息,请参阅文档

于 2020-03-04T08:26:33.607 回答
0

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

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

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

于 2020-03-05T19:59:18.637 回答