1

我正在尝试获取特定用户定义身份的 msi 令牌。我们的应用服务有 2 个用户定义的身份,我想要一个代表用户分配身份的令牌。

这是代码:

        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(
            "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/&object_id=<ObjectId>&client_id=<clientId>");

        req.Headers["Metadata"] = "true";
        req.Method = "GET";

        try
        {
            // Call /token endpoint
            HttpWebResponse response = (HttpWebResponse)req.GetResponse();

            // Pipe response Stream to a StreamReader, and extract access token
            StreamReader streamResponse = new StreamReader(response.GetResponseStream());
            string stringResponse = streamResponse.ReadToEnd();
            Dictionary<string, string> list =
                 JsonConvert.DeserializeObject<Dictionary<string, string>>(stringResponse);
            string accessToken = list["access_token"];

            System.IO.File.WriteAllText(@".\Log.txt", accessToken);
        }
        catch (Exception e)
        {
            string errorText = String.Format("{0} \n\n{1}", e.Message, e.InnerException != null ? e.InnerException.Message : "Acquire token failed");
            System.IO.File.WriteAllText(@".\Log.txt", errorText);
            throw;
        }

它部署在 azure app 服务中。当我点击此部分时,我看到此错误:尝试以访问权限禁止的方式访问套接字

我尝试连接到http://169.254.169.254以使用 kudu 控制台获取令牌。但是这个端点似乎在那里无法访问。

在此处输入图像描述

我确实尝试使用 Microsoft.Azure.Services.AppAuthentication 中的 AzureServiceTokenProvider 来生成 msi 令牌,但找不到任何有关如何将其用于多个用户分配的身份的文档。

编辑:

更新1:

我尝试使用 MSI_ENDPOINT 环境变量中的端点而不是 169.254.169.254。但是当我运行应用服务时,似乎没有设置 MSI_ENDPOINT 值。这是我尝试过的代码:

   var endpoint = Environment.GetEnvironmentVariable("MSI_ENDPOINT");
    string apiVersion = "2018-02-01";
    string resource = "https://management.azure.com/";
    string objectId = "<objectid>";
    string clientId = "<clientId>";

        // Build request to acquire managed identities for Azure resources token
        //HttpWebRequest req = (HttpWebRequest)WebRequest.Create(
        //    "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/&object_id=4aef1720-b3b1-4935-8d68-e330508907fa&client_id=558ecc75-8697-4419-bab9-aa2c87043cfd");

        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(
       String.Format(
            "{0}?resource={1}&api-version={2}&object_id={3}&client_id={4}",
            endpoint,
            resource,
            apiVersion,
            objectId,
            clientId));

        req.Headers["Metadata"] = "true";
        req.Method = "GET";

        try
        {
            // Call /token endpoint
            HttpWebResponse response = (HttpWebResponse)req.GetResponse();

            // Pipe response Stream to a StreamReader, and extract access token
            StreamReader streamResponse = new StreamReader(response.GetResponseStream());
            string stringResponse = streamResponse.ReadToEnd();
            Dictionary<string, string> list =
                 JsonConvert.DeserializeObject<Dictionary<string, string>>(stringResponse);
            string accessToken = list["access_token"];

            System.IO.File.WriteAllText(@".\Log.txt", accessToken);
        }
        catch (Exception e)
        {
            string errorText = String.Format("{0} \n\n{1}", e.Message, e.InnerException != null ? e.InnerException.Message : "Acquire token failed");

            string log = "MSI_ENDPOINT : " + endpoint + "\n";
            log += ("ErrorText : " + errorText + "\n");
            System.IO.File.WriteAllText(@".\Log.txt", errorText);
            throw;
        }
4

1 回答 1

5

首先,此链接How to use managed identities for App Service and Azure Functions提供了特定于 MSI for App Services 的良好文档。

这是快速示例代码.. 为您在问题中提出的特定用户分配的托管服务身份获取令牌。

  • resource - 应为其获取令牌的资源的 AAD 资源 URI。
  • apiversion - 要使用的令牌 API 的版本。“2017-09-01”是目前唯一支持的版本。
  • clientId - 要使用的用户分配身份的 ID。如果省略,则使用系统分配的标识。

    public static async Task<HttpResponseMessage> GetToken(string resource, string apiversion, string clientId)  
    {
        HttpClient client = new HttpClient();   
        client.DefaultRequestHeaders.Add("Secret", Environment.GetEnvironmentVariable("MSI_SECRET"));
        return await client.GetAsync(String.Format("{0}/?resource={1}&api-version={2}&clientid={3}", Environment.GetEnvironmentVariable("MSI_ENDPOINT"), resource, apiversion,clientId));
    }
    

    总的来说,我在上面的示例代码中看到了一些你应该注意到的变化:

    1. 在运行时使用 MSI_ENDPOINT 构造 URL
    2. 参数应该是 clientid 而不是 client_id
    3. 不需要参数 object_id
    4. api 版本应该是“2017-09-01”,因为上面链接中的文档说这是唯一受支持的版本。
  • 关于您在运行应用服务时未设置 MSI_ENDPOINT 值的问题,请查看 Microsoft Docs 中同一链接中的此说明

    在此处输入图像描述

  • 与使用的所有参数相关的文档截图

    在此处输入图像描述

于 2019-02-01T06:04:52.697 回答