如何为 Azure App Service 的特定用户分配托管服务标识获取令牌?
How to get a token for specific user assigned managed service identity for Azure App Service?
我正在尝试为特定用户定义的身份获取 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 应用程序服务中。当我点击此部分时,我看到此错误:
试图以访问权限禁止的方式访问套接字
我尝试连接到 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;
}
首先,此 link 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));
}
总的来说,我在上面的示例代码中发现了一些您应该注意的变化:
- 利用MSI_ENDPOINT在运行时构造URL
- 参数应该是 clientid 而不是 client_id
- 不需要参数 object_id
- api 版本应为“2017-09-01”,因为上面的文档 link 说这是唯一受支持的版本。
关于您在 运行 应用服务时未设置 MSI_ENDPOINT 值的问题,请查看 Microsoft 中同一 link 的此注释文档
与所用所有参数相关的文档的屏幕截图
我正在尝试为特定用户定义的身份获取 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 应用程序服务中。当我点击此部分时,我看到此错误: 试图以访问权限禁止的方式访问套接字
我尝试连接到 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;
}
首先,此 link 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)); }
总的来说,我在上面的示例代码中发现了一些您应该注意的变化:
- 利用MSI_ENDPOINT在运行时构造URL
- 参数应该是 clientid 而不是 client_id
- 不需要参数 object_id
- api 版本应为“2017-09-01”,因为上面的文档 link 说这是唯一受支持的版本。
关于您在 运行 应用服务时未设置 MSI_ENDPOINT 值的问题,请查看 Microsoft 中同一 link 的此注释文档
与所用所有参数相关的文档的屏幕截图