为什么我使用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与Bearer令牌一起使用。我可以访问其他资源,例如https://management.azure.com/subscriptions/{subscription-id}/resourcegroups?api-version=2017-05-10,但是不能访问https://management.core.windows.net/{subscription-id}/services/hostedservices资源。
  • 我正在邮递员上对此进行测试。

解决方案

问题与证书配置有关

$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云服务是Can I use...。因此,我们需要使用Azure服务管理API对其进行管理。如果要调用API,则需要进行X509客户端证书身份验证。有关更多详细信息,请参阅Azure classic resource

详细步骤如下

  1. 将证书上传到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
    

    b将.cer文件上传到Azure(订阅->您的订阅->管理证书) document

  2. 代码(例如,我在订阅中列出了云服务)

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

enter image description here

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...