gpt4 book ai didi

c# - 如何在 Azure 中列出经典虚拟机

转载 作者:太空狗 更新时间:2023-10-29 22:56:38 24 4
gpt4 key购买 nike

我想以编程方式列出和控制 Azure 中的经典虚拟机(旧虚拟机)。对于托管来说这不是问题,有库并且其余 API 正在工作,但是一旦我 calling the old API对于列出经典,我得到了 403(禁止)。

代码没问题吗?我是否需要在其他地方管理旧 API 的凭据?

我的代码在这里:

static void Main(string[] args)
{
string apiNew = "https://management.azure.com/subscriptions/xxxxxxxxxxxxxxxxxxxxxxxx/providers/Microsoft.Compute/virtualMachines?api-version=2018-06-01";
string apiOld = "https://management.core.windows.net/xxxxxxxxxxxxxxxxxxxxxxxx/services/vmimages"

AzureRestClient client = new AzureRestClient(credentials.TenantId, credentials.ClientId, credentials.ClientSecret);

//OK - I can list the managed VMs.
string resultNew = client.GetRequestAsync(apiNew).Result;

// 403 forbidden
string resultOld = client.GetRequestAsync(apiOld).Result;
}

public class AzureRestClient : IDisposable
{
private readonly HttpClient _client;

public AzureRestClient(string tenantName, string clientId, string clientSecret)
{
_client = CreateClient(tenantName, clientId, clientSecret).Result;
}

private async Task<string> GetAccessToken(string tenantName, string clientId, string clientSecret)
{
string authString = "https://login.microsoftonline.com/" + tenantName;
string resourceUrl = "https://management.core.windows.net/";

var authenticationContext = new AuthenticationContext(authString, false);
var clientCred = new ClientCredential(clientId, clientSecret);
var authenticationResult = await authenticationContext.AcquireTokenAsync(resourceUrl, clientCred);
var token = authenticationResult.AccessToken;

return token;
}

async Task<HttpClient> CreateClient(string tenantName, string clientId, string clientSecret)
{
string token = await GetAccessToken(tenantName, clientId, clientSecret);
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
return client;
}

public async Task<string> GetRequestAsync(string url)
{
return await _client.GetStringAsync(url);
}
}

更新1:

回复详情:

HTTP/1.1 403 Forbidden
Content-Length: 288
Content-Type: application/xml; charset=utf-8
Server: Microsoft-HTTPAPI/2.0
Date: Mon, 22 Oct 2018 11:03:40 GMT

HTTP/1.1 403 Forbidden
Content-Length: 288
Content-Type: application/xml; charset=utf-8
Server: Microsoft-HTTPAPI/2.0
Date: Mon, 22 Oct 2018 11:03:40 GMT

<Error xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Code>ForbiddenError</Code>
<Message>The server failed to authenticate the request.
Verify that the certificate is valid and is associated with this subscription.</Message>
</Error>

更新2:

我发现 powershell 命令 Get-AzureVMImage 使用相同的 API,并且它正在 powershell 中工作。 Powershell 要求我首先通过电子邮件和密码通过交互式登录窗口登录 Azure,并且该请求使用 Bearer header 进行身份验证,就像我的代码一样。

如果我从 Powershell 创建的通信中嗅探访问 token (Bearer header ),我就可以成功与该 API 进行通信。

更新 3:已解决,回答如下。

最佳答案

1。调用 List VM Images API 时出现 403 的原因

这是因为您的 Azure AD 注册应用程序未正确使用“Windows Azure 服务管理 API”委派权限。我这样说是因为我看到您的代码是直接使用应用程序身份(ClientCredential)而不是作为用户获取 token 。

请参阅下面的屏幕截图。 Window Azure Service Management API显然不提供任何应用程序权限,唯一可以使用的就是委托(delegate)权限。如果您想了解更多关于两种权限之间的区别,请阅读Permissions in Azure AD 。简而言之,使用委派权限时,应用程序会被委派权限,在调用 API 时充当登录用户。因此必须有一个登录用户。

我能够使用您的代码重现 403 错误,然后使其正常工作并返回经过一些更改的经典虚拟机列表。接下来我将解释所需的更改。

转到您的 Azure AD > 应用注册 > 您的应用 > 设置 > 所需权限:

enter image description here

enter image description here

2。使其发挥作用所需的更改

更改将是作为登录用户获取 token ,而不是直接使用应用程序的 clientId 和 key 。由于您的应用程序是控制台应用程序,因此执行以下操作是有意义的,这将提示用户输入凭据:

var authenticationResult = await authenticationContext.AcquireTokenAsync(resourceUrl, clientId, new Uri(redirectUri), new PlatformParameters(PromptBehavior.Auto));

此外,由于您的应用程序是控制台应用程序,因此最好将其注册为“ native ”应用程序,而不是像现在这样的 Web 应用程序。我这样说是因为可以在用户系统上运行的控制台应用程序或基于桌面客户端的应用程序无法安全地处理应用程序 secret ,因此您不应将它们注册为“Web 应用程序/API”并且不要在其中使用任何 secret ,因为这是安全风险.

总体而言,进行了 2 处更改后,您应该就可以开始了。正如我之前所说,我已经尝试过这些,并且可以看到代码运行良好并获得了经典虚拟机的列表。

a.在 Azure AD 中将您的应用程序注册为 native 应用程序(即应用程序类型应该是 native 而不是 Web 应用程序/API),然后在所需权限中添加“Window Azure 服务管理 API”并按照第 1 点中的早期屏幕截图检查委派权限

enter image description here

b.更改获取token的方式,以便可以按照登录用户使用委托(delegate)权限。当然,登录用户应该有权访问您尝试列出的虚拟机,或者如果您有多个用户,则列表将反射(reflect)当前登录用户有权访问的虚拟机。

这是我修改后的完整工作代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System.Net.Http;
using System.Net.Http.Headers;

namespace ListVMsConsoleApp
{
class Program
{
static void Main(string[] args)
{
string tenantId = "xxxxxx";
string clientId = "xxxxxx";
string redirectUri = "https://ListClassicVMsApp";

string apiNew = "https://management.azure.com/subscriptions/xxxxxxxx/providers/Microsoft.Compute/virtualMachines?api-version=2018-06-01";
string apiOld = "https://management.core.windows.net/xxxxxxxx/services/vmimages";

AzureRestClient client = new AzureRestClient(tenantId, clientId, redirectUri);

//OK - I can list the managed VMs.
//string resultNew = client.GetRequestAsync(apiNew).Result;

// 403 forbidden - should work now
string resultOld = client.GetRequestAsync(apiOld).Result;
}

}

public class AzureRestClient
{
private readonly HttpClient _client;

public AzureRestClient(string tenantName, string clientId, string redirectUri)
{
_client = CreateClient(tenantName, clientId, redirectUri).Result;
}

private async Task<string> GetAccessToken(string tenantName, string clientId, string redirectUri)
{
string authString = "https://login.microsoftonline.com/" + tenantName;
string resourceUrl = "https://management.core.windows.net/";

var authenticationContext = new AuthenticationContext(authString, false);
var authenticationResult = await authenticationContext.AcquireTokenAsync(resourceUrl, clientId, new Uri(redirectUri), new PlatformParameters(PromptBehavior.Auto));

return authenticationResult.AccessToken;
}

async Task<HttpClient> CreateClient(string tenantName, string clientId, string redirectUri)
{
string token = await GetAccessToken(tenantName, clientId, redirectUri);
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
client.DefaultRequestHeaders.Add("x-ms-version", "2014-02-01");
return client;
}

public async Task<string> GetRequestAsync(string url)
{
return await _client.GetStringAsync(url);
}
}
}

关于c# - 如何在 Azure 中列出经典虚拟机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52886735/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com