使用azure活动目录进行身份validation时,发生Azurepipe理库API调用时出错

我的公司正在研究关于Azure的报告。 我们只希望我们的客户给我们只读凭证供我们使用。 我做了一些研究,看起来Azure Active Directory就是这样做的。 所以我正在寻找使用只读的Azure目录应用程序进行身份validation。

为了让我开始,我正在关注这个使用Azure Active Directorypipe理API的博客。

https://msdn.microsoft.com/en-us/library/azure/dn722415.aspx

除了方法显示非常不友好,它不起作用=(

以全局pipe理员身份login后出现此错误:

“AADSTS90014:请求主体必须包含以下参数:”client_secret或client_assertion“。

做了一些研究,发现这种authentication方式是原生应用程序,而不是networking应用程序(尽pipe博客文章说的其他明智..)。 所以我做了一个调整。 我的GetAuthorizationHeader现在看起来像这样:

private static string GetAuthorizationHeader() { AuthenticationResult result = null; var context = new AuthenticationContext("https://login.windows.net/" + ConfigurationManager.AppSettings["tenantId"]); string clientId = ConfigurationManager.AppSettings["clientId"]; string clientSecret = ConfigurationManager.AppSettings["clientSecret"]; ClientCredential clientCred = new ClientCredential(clientId, clientSecret); var thread = new Thread(() => { result = context.AcquireToken( "https://management.core.windows.net/", clientCred); }); thread.SetApartmentState(ApartmentState.STA); thread.Name = "AquireTokenThread"; thread.Start(); thread.Join(); if (result == null) { throw new InvalidOperationException("Failed to obtain the JWT token"); } string token = result.AccessToken; return token; } 

我能够获得访问令牌(YAY)。 但是现在,当我尝试使用Azurepipe理库客户端时,出现此错误:

“ForbiddenError:服务器无法validation请求,请validation证书是否有效,并且与此订阅相关联。

我在我的应用程序中检查了我的权限。 它看起来不错。 我试图让所有的东西都看到,如果这会有所作为。

我仔细检查了我的tenantId,clientId和subscriptionId,都很好看。

我确定我正在使用的订阅是指向我的应用程序所在的AD。

我尝试制作一个新的密钥。

我的猜测是这个问题: 在这里输入图像描述 但是在这个UI中,我无法为该属性select任何值。 我不确定这是由于错误还是未完成的function。 我在这里错过了什么?

谢谢

以下是我的完整代码供参考:

 class Program { static void Main(string[] args) { var token = GetAuthorizationHeader(); var credential = new TokenCloudCredentials(ConfigurationManager.AppSettings["subscriptionId"], token); using (var computeClient = new ComputeManagementClient(credential)) { var images = computeClient.VirtualMachineOSImages.List(); } } private static string GetAuthorizationHeader() { AuthenticationResult result = null; var context = new AuthenticationContext("https://login.windows.net/" + ConfigurationManager.AppSettings["tenantId"]); string clientId = ConfigurationManager.AppSettings["clientId"]; string clientSecret = ConfigurationManager.AppSettings["clientSecret"]; ClientCredential clientCred = new ClientCredential(clientId, clientSecret); var thread = new Thread(() => { result = context.AcquireToken( "https://management.core.windows.net/", clientCred); }); thread.SetApartmentState(ApartmentState.STA); thread.Name = "AquireTokenThread"; thread.Start(); thread.Join(); if (result == null) { throw new InvalidOperationException("Failed to obtain the JWT token"); } string token = result.AccessToken; return token; } } 

编辑:已取得进展。 正如我与Gaurav讨论的那样,我需要抛弃Azurepipe理库,因为从现在起,它似乎不支持Azure资源pipe理器(ARM)API! 所以相反,我做了原始的Web请求。 它按预期工作。 如果我删除我的AD应用程序的angular色访问,我得到访问被拒绝。 当我有了它,我得到的数据。

我不确定的一件事是让我的应用程序自动添加到新的资源。

另外,有没有办法列出我的AD应用程序可访问的资源组?

新代码:

  class Program { static void Main(string[] args) { var token = GetAuthorizationHeader(); string subscriptionId = ConfigurationManager.AppSettings["subscriptionId"]; string resourceGroupName = ConfigurationManager.AppSettings["resourceGroupName"]; var uriListMachines = string.Format("https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Compute/virtualmachines?api-version=2015-05-01-preview", subscriptionId, resourceGroupName); var t = WebRequest.Create(uriListMachines); t.ContentType = "application/json"; t.Headers.Add("Authorization", "Bearer " + token); var response = (HttpWebResponse)t.GetResponse(); string result = ""; using (var reader = new StreamReader(response.GetResponseStream())) { result = reader.ReadToEnd(); } //Original Attempt: //var credential = new TokenCloudCredentials(ConfigurationManager.AppSettings["subscriptionId"], token); //using (var client = CloudContext.Clients.CreateComputeManagementClient(credential)) //{ // var images = client.VirtualMachineVMImages.List(); //} } private static string GetAuthorizationHeader() { AuthenticationResult result = null; var context = new AuthenticationContext("https://login.windows.net/" + ConfigurationManager.AppSettings["tenantId"]); string clientId = ConfigurationManager.AppSettings["clientId"]; string clientSecret = ConfigurationManager.AppSettings["clientSecret"]; ClientCredential clientCred = new ClientCredential(clientId, clientSecret); var thread = new Thread(() => { result = context.AcquireToken( "https://management.core.windows.net/", clientCred); }); thread.SetApartmentState(ApartmentState.STA); thread.Name = "AquireTokenThread"; thread.Start(); thread.Join(); if (result == null) { throw new InvalidOperationException("Failed to obtain the JWT token"); } string token = result.AccessToken; return token; } } 

编辑编辑:我想通了我挂了。 OLD门户中创build的资源将获得自己独特的资源组。

从我能告诉你不能添加在旧门户现有资源组(boooo)中所做的资源。 在新门户中创build的资源将能够将资源分配给现有的组(也就是让angular色访问我的AD应用程序的组)。

这真是一团糟! 但至less我知道现在发生了什么。

我相信你正处在正确的轨道上,为什么你会遇到这个问题。

这是发生了什么事情:

本质上执行Service Management APIdelegated permission and not an application permissiondelegated permission and not an application permission 。 换句话说,API是在获取令牌的用户的上下文中执行的。 现在,您正在为您的应用程序获取该令牌(由客户端ID /秘密指定)。 但是,您的应用程序无法访问Azure订阅,因为在Azure AD中为此应用程序创build的用户logging是“ Service Principal ”types。 由于此服务负责人无权访问您的Azure订阅,因此您将收到此Forbidden Error (因为您根本没有使用证书,所以我必须说错误是误导性的)。

有几件事你可以做:

  1. 切换到Azure资源pipe理器(ARM)API – ARM API是下一代的服务pipe理API(SM API),Azure只朝着这个方向发展。 它独占了Azure AD令牌。 如果可能的话,利用它来pipe理你的Azure资源(尽pipe你需要记住,截至今天,并不是所有的Azure资源都可以通过ARM API来pipe理)。 他们这样做的方式是把你的服务负责人,并使用新的Azure Portal分配给一个特定的angular色。 请参阅此链接了解更多详细信息: https : //azure.microsoft.com/en-in/documentation/articles/resource-group-create-service-principal-portal/ 。
  2. 使用X509证书 – 您始终可以使用基于X509证书的授权来授权您的SM API请求。 有关更多详细信息,请参阅此链接: https : //msdn.microsoft.com/en-us/library/azure/ee460782.aspx#bk_cert 。 这种方法的缺点是,应用程序(或任何可以访问此证书的人)将获得对Azure订阅的完全访问权限,并且可以在其中执行所有操作(包括删除资源)。
  3. 为用户而不是应用程序获取令牌 – 这是您可以采取的另一种方法。 本质上要求您的用户通过您的控制台应用程序login到Azure AD并获取该用户的令牌。 同样,请记住,此用户必须是您的Azure订阅中的Co-Admin ,并且与SM API一样将具有对Azure订阅的完全访问权限,因此不存在Role-based access control概念。