azure - 为什么我使用 Azure 服务管理 API 得到 403?
问题描述
我想使用 Azure API 管理 ( management.core.windows.net
) 重新启动角色实例(参考 Microsoft 文档:https ://docs.microsoft.com/en-us/rest/api/compute/cloudservices/rest-reboot-role-instance )但我收到了 403 作为回应。
要求:
https://management.core.windows.net/{subscription-id}/services/hostedservices/{hosted-service}/deploymentslots/staging/roleinstances/{role-instance-name}?comp=reboot`
Headers:
- Authorization: Bearer {token}
- Content-Type: application/xml
- x-ms-version: 2010-10-28
- Content-Length: 0
Body: Empty
响应正文:
<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>
我通过调用(参考 Microsoft 文档:https ://docs.microsoft.com/en-us/azure/active-directory/azuread-dev/v1-oauth2-client-creds-grant-flow #service-to-service-access-token-request):
https://login.microsoftonline.com/{tenant_id}/oauth2/token
Headers:
- Content-Type: application/x-www-form-urlencoded
Body:
- grant_type: client_credentials,
- client_id: {client_id}
- client_secret: {client_secret}
- resource: https://management.core.windows.net/
任何想法?请求或 Azure 门户端是否缺少任何配置?是否management.core.windows.net
已弃用,因为我可以使用management.azure.com
?
笔记:
- 我已经在 Azure 端配置了权限:我为此创建了一个
app registration
,用于授予权限的密钥为contributor
; management.azure.com
API 与不记名令牌一起使用。我可以访问其他资源,例如https://management.azure.com/subscriptions/{subscription-id}/resourcegroups?api-version=2017-05-10
但我无法访问这些https://management.core.windows.net/{subscription-id}/services/hostedservices
资源。- 我正在 Postman 上对此进行测试。
解决方案
问题与证书配置有关
$cert = New-SelfSignedCertificate -Subject "CN=Azure Management API" -CertStoreLocation "cert:\LocalMachine\My" -KeyLength 2048 -KeySpec "KeyExchange" -NotAfter (Get-Date).AddMonths(360)
$password = ConvertTo-SecureString -String "strong-password-here" -Force -AsPlainText
Export-PfxCertificate -Cert $cert -FilePath ".\azure-management-api.pfx" -Password $password
Export-Certificate -Type CERT -Cert $cert -FilePath .\azure-management-api.cer
注意证书的重要性.pfx
代码
var cert = new X509Certificate2( File.ReadAllBytes( "your-certificate-path.pfx" ), "your_password" );
var httpClientHandler = new HttpClientHandler
{
UseProxy = false,
ClientCertificateOptions = ClientCertificateOption.Manual
};
httpClientHandler.ClientCertificates.Add( cert );
var httpClient = new HttpClient( httpClientHandler );
httpClient.DefaultRequestHeaders.Add( "Accept", "application/xml" );
httpClient.DefaultRequestHeaders.Add( "Host", "management.core.windows.net" );
httpClient.DefaultRequestHeaders.Add( "x-ms-version", "2010-10-28" );
var uri = $"https://management.core.windows.net/{subscriptionId}/services/hostedservices";
Console.WriteLine( $"GET {uri} [{httpClient.DefaultRequestVersion}]" );
foreach ( var header in httpClient.DefaultRequestHeaders )
{
Console.WriteLine( $"{header.Key} {header.Value.First()}" );
}
var response = httpClient.GetAsync( uri )
.GetAwaiter()
.GetResult();
var content = response.Content.ReadAsStringAsync()
.GetAwaiter()
.GetResult();
Console.WriteLine( $"{(int)response.StatusCode} {response.StatusCode}" );
Console.WriteLine( content );
httpClient.Dispose();
httpClientHandler.Dispose();
解决方案
根据您的描述,您要管理 Azure 云服务。Azure 云服务是Azure 经典资源。所以我们需要使用 Azure 服务管理 API 来管理它。如果我们要调用API,我们需要做X509客户端证书认证。更多详细信息,请参阅文档
详细步骤如下
将证书上传到 Azure 创建证书
$cert = New-SelfSignedCertificate -DnsName yourdomain.cloudapp.net -CertStoreLocation "cert:\LocalMachine\My" -KeyLength 2048 -KeySpec "KeyExchange" $password = ConvertTo-SecureString -String "your-password" -Force -AsPlainText Export-PfxCertificate -Cert $cert -FilePath ".\my-cert-file.pfx" -Password $password Export-Certificate -Type CERT -Cert $cert -FilePath .\my-cert-file.cer
代码(例如,我在订阅中列出了云服务)
static async Task Main(string[] args)
{
var _clientHandler = new HttpClientHandler();
_clientHandler.ClientCertificates.Add(GetStoreCertificate("the cert's thumbprint" ));
_clientHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
String uri = string.Format("https://management.core.windows.net/{0}/services/hostedservices", "subscription id");
using (var _client = new HttpClient(_clientHandler))
using (var request = new HttpRequestMessage(HttpMethod.Get, uri)) {
request.Headers.Add("x-ms-version", "2014-05-01");
request.Headers.Add("Accept", "application/xml");
//request.Headers.Add("Content-Type", "application/xml");
using (HttpResponseMessage httpResponseMessage = await _client.SendAsync(request)) {
string xmlString = await httpResponseMessage.Content.ReadAsStringAsync();
Console.WriteLine(httpResponseMessage.StatusCode);
Console.WriteLine(xmlString);
}
}
}
private static X509Certificate2 GetStoreCertificate(string thumbprint)
{
X509Store store = new X509Store("My", StoreLocation.LocalMachine);
try
{
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection certificates = store.Certificates.Find(
X509FindType.FindByThumbprint, thumbprint, false);
if (certificates.Count == 1)
{
return certificates[0];
}
}
finally
{
store.Close();
}
throw new ArgumentException(string.Format(
"A Certificate with Thumbprint '{0}' could not be located.",
thumbprint));
}
推荐阅读
- c# - 检查是否有人在我的 Windows 窗体 C# 中仅单击一个图片框
- hybris - Hybris 后台菜单更改为 hMC 菜单
- reactjs - 如何防止网页样式受到注入 chrome 扩展样式的影响
- javascript - npm 安装的问题
- ios - iOS Unity 应用程序中的位置权限字符串
- python - Python中使用相同数据的三个子图
- javascript - 将调用的块相对于父块 JS 居中
- android-lifecycle - 我们应该在 Fragment/Activity 中注销 Flow 集合吗?
- c++ - C++ 使用 date.h 从当前时间减去天数
- android - Android onItemClick 方法不适用于 0 以外的 id 项