2017-05-14 9 views
0

証明書認証を使用してAzure Resource Rate APIを呼び出すことができるコンソールアプリケーションを作成しようとしています。このため、私は次のブランチGitHub linkを使用しました。証明書認証を使用してAzure Resource Rate APIを呼び出すときに403を取得する

403エラーが発生します。 Azure ADにWebアプリケーションを追加しました。マニフェストでは、次のPowerShellコマンドを使用して署名した証明書の主要な資格情報をコピーしました。

$cert=New-SelfSignedCertificate -Subject "CN=RateCardCert" 
-CertStoreLocation "Cert:\CurrentUser\My" -KeyExportPolicy Exportable -KeySpec Signature 
$bin = $cert.RawData $base64Value = [System.Convert]::ToBase64String($bin) 
$bin = $cert.GetCertHash() 
$base64Thumbprint = [System.Convert]::ToBase64String($bin) 
$keyid = [System.Guid]::NewGuid().ToString() 
$jsonObj = @ customKeyIdentifier=$base64Thumbprint;keyId=$keyid;type="AsymmetricX509Cert";usage="Verify";value=$base64Value} 
$keyCredentials=ConvertTo-Json @($jsonObj) | Out-File "keyCredentials.txt" 

コンソールアプリケーションでは、トークンを取得するために次の関数を使用します。

public static string GetOAuthTokenFromAAD_ByCertificate(string TenanatID, string ClientID, string CertificateName) 
    { 
     //Creating the Authentication Context 
     var authContext = new AuthenticationContext(string.Format("https://login.windows.net/{0}", TenanatID)); 
     //Console.WriteLine("new authContext made"); 
     //Creating the certificate object. This will be used to authenticate 
     X509Certificate2 cert = null; 
     //Console.WriteLine("empty 'cert' made, null"); 
     //The Certificate should be already installed in personal store of the current user under 
     //the context of which the application is running. 
     X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser); 


     try 
     { 
      //Trying to open and fetch the certificate 
      store.Open(OpenFlags.ReadOnly); 
      var certCollection = store.Certificates; 
      var certs = certCollection.Find(X509FindType.FindBySubjectName, CertificateName, false); 
      //Checking if certificate found 
      if (certs == null || certs.Count <= 0) 
      { 
       //Throwing error if certificate not found 
       throw new Exception("Certificate " + CertificateName + " not found."); 
      } 
      cert = certs[0]; 
     } 
     finally 
     { 
      //Closing the certificate store 
      store.Close(); 
     } 

     //Creating Client Assertion Certificate object 
     var certCred = new ClientAssertionCertificate(ClientID, cert); 

     //Fetching the actual token for authentication of every request from Azure using the certificate 
     var token = authContext.AcquireToken("https://management.core.windows.net/", certCred); 

     //Optional steps if you need more than just a token from Azure AD 
     //var creds = new TokenCloudCredentials(subscriptionId, token.AccessToken); 
     //var client = new ResourceManagementClient(creds); 

     //Returning the token 
     return token.AccessToken; 
    } 

これは、リクエストにURLとプットを作る(XXXXの部分は、私はAzureのADに登録したWebアプリケーションのクライアントIDに置き換えられます)コードの一部です。

//Get the AAD User token to get authorized to make the call to the Usage API 
     string token = GetOAuthTokenFromAAD_ByCertificate("<MyTenantName.onmicrosoft.com", "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "RateCardCert"); 


      // Build up the HttpWebRequest 
     string requestURL = String.Format("{0}/{1}/{2}/{3}", 
        ConfigurationManager.AppSettings["ARMBillingServiceURL"], 
        "subscriptions", 
        ConfigurationManager.AppSettings["SubscriptionID"], 
        "providers/Microsoft.Commerce/RateCard?api-version=2015-06-01-preview&$filter=OfferDurableId eq 'MS-AZR-0044P' and Currency eq 'EUR' and Locale eq 'nl-NL' and RegionInfo eq 'NL'"); 
     HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestURL); 

     // Add the OAuth Authorization header, and Content Type header 
     request.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + token); 
     request.ContentType = "application/json"; 

     // Call the RateCard API, dump the output to the console window 
     try 
     { 
      // Call the REST endpoint 
      Console.WriteLine("Calling RateCard service..."); 
      HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
      Console.WriteLine(String.Format("RateCard service response status: {0}", response.StatusDescription)); 
      Stream receiveStream = response.GetResponseStream(); 

      // Pipes the stream to a higher level stream reader with the required encoding format. 
      StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8); 
      var rateCardResponse = readStream.ReadToEnd(); 
      Console.WriteLine("RateCard stream received. Press ENTER to continue with raw output."); 
      Console.ReadLine(); 
      Console.WriteLine(rateCardResponse); 
      Console.WriteLine("Raw output complete. Press ENTER to continue with JSON output."); 
      Console.ReadLine(); 

      // Convert the Stream to a strongly typed RateCardPayload object. 
      // You can also walk through this object to manipulate the individuals member objects. 
      RateCardPayload payload = JsonConvert.DeserializeObject<RateCardPayload>(rateCardResponse); 

      Console.WriteLine(rateCardResponse.ToString()); 
      response.Close(); 
      readStream.Close(); 
      Console.WriteLine("JSON output complete. Press ENTER to close."); 
      Console.ReadLine(); 
     } 
     catch(Exception e) 
     { 
      Console.WriteLine(String.Format("{0} \n\n{1}", e.Message, e.InnerException != null ? e.InnerException.Message : "")); 
      Console.ReadLine(); 
     } 

私はもう何をすべきか分かりません。私はここで何が欠けていますか?

コンソールの

完全復帰がある:あなたがAzureのリソース管理APIを呼び出している

、しかし、あなたは唯一のAzure上の権限を与えた:

Calling RateCard Service... The remote server returned an error: (403) Forbidden.

+0

Azure ADでアプリの権限を与えましたか? 403は認証ではなく認証に失敗したため、証明書が正常に動作している可能性があります。 – juunas

+0

私は、AAD-> App登録 - > appname - > Required Permissionsの順でAppへのアクセス権を追加しました。私は 'Windows Azureサービス管理API'と 'Windows Azure Active Directory'を追加しました。後者については、すべてのアクセス許可を追加しましたが(確かに)、403は引き続きあります。 –

+0

[許可]ボタンを押しましたか?パーミッションを追加すると、パーミッションが必要であることがわかりますが、パーミッションを付与するのは別のアクションです。 – juunas

答えて

1

コメントでチャットした後に問題が見つかりました。サービス管理API。アプリのサービスプリンシパルをサブスクリプションの役割に追加する必要があります。サブスクリプション、アクセス制御(IAM)ブレードを見つけて、そこでアプリケーションをロールに追加します。あなたはその名前でそれを見つけることができるはずです。

サービスプリンシパルをリソースグループのロールに追加することもできます。また、その機能を制限する場合は、特定のリソースまで追加することもできます。

関連する問題