証明書認証を使用して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.
Azure ADでアプリの権限を与えましたか? 403は認証ではなく認証に失敗したため、証明書が正常に動作している可能性があります。 – juunas
私は、AAD-> App登録 - > appname - > Required Permissionsの順でAppへのアクセス権を追加しました。私は 'Windows Azureサービス管理API'と 'Windows Azure Active Directory'を追加しました。後者については、すべてのアクセス許可を追加しましたが(確かに)、403は引き続きあります。 –
[許可]ボタンを押しましたか?パーミッションを追加すると、パーミッションが必要であることがわかりますが、パーミッションを付与するのは別のアクションです。 – juunas