简体   繁体   中英

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

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

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

    在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM