How to get a token for specific user assigned managed service identity for Azure App Service?

一曲冷凌霜 提交于 2021-01-29 07:28:04

问题


I am trying to get a msi token for a specific User defined identity. Our app service has 2 user defined identities and I want a token on behalf of one of the user assigned identity.

Here is the code:

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

It is deployed in an azure app service. When I hit this section I see this error: An attempt was made to access a socket in a way forbidden by its access permissions

I tried connecting to http://169.254.169.254 to get the token using kudu console. But this endpoint does not seem to accessible there.

I did try to use AzureServiceTokenProvider from Microsoft.Azure.Services.AppAuthentication for generating msi token but could not find any documentation about how to use it for multiple user assigned identities.

Edit:

Update 1:

I tried to use endpoint from MSI_ENDPOINT environment variable instead of 169.254.169.254. But it looks like MSI_ENDPOINT value is not set when I run the app service. Here is the code I have tried:

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

回答1:


Firstly, this link How to use managed identities for App Service and Azure Functions provides good documentation specific to MSI for App Services.

Here is quick sample code.. to get token for a specific user assigned managed service identity as you've asked in your question.

  • resource - The AAD resource URI of the resource for which a token should be obtained.
  • apiversion - The version of the token API to be used. "2017-09-01" is currently the only version supported.
  • clientId - The ID of the user-assigned identity to be used. If omitted, the system-assigned identity is used.

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

    Overall I see a few changes that you should notice in the sample code above:

    1. Make use of MSI_ENDPOINT to construct URL at runtime
    2. parameter should be clientid and not client_id
    3. parameter object_id is not needed
    4. api version should be "2017-09-01" as documentation in above link says that's the only one supported.
  • About your issue with MSI_ENDPOINT value not being set when you run the app service, please take a look at this note from same link in Microsoft Docs

  • Screenshot from documentation that is relevant for all parameters used



来源:https://stackoverflow.com/questions/54470209/how-to-get-a-token-for-specific-user-assigned-managed-service-identity-for-azure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!