2

我一直在尝试(但失败)以编程方式创建 Azure 流分析作业。我最初是在关注这个例子:

https://azure.microsoft.com/en-gb/documentation/articles/stream-analytics-dotnet-management-sdk/

但它会弹出一个对话框让您登录。我希望能够做到这一点服务器端。看来我需要使用 Azure AD 才能使用资源管理器 API。我一直在努力解决这个问题:

https://msdn.microsoft.com/en-us/library/azure/dn790557.aspx#bk_portal

代码如下所示:

var authContext = new AuthenticationContext("https://login.microsoftonline.com/{tenant id}/oauth2/token");
var clientId = "{app client id}";
var appKey = "{app key}";
var subscriptionId = "{subscription id}";
var clientCredential = new ClientCredential(clientId, appKey);

var result = authContext.AcquireToken("https://management.core.windows.net/", clientCredential);
var creds = new TokenCloudCredentials(subscriptionId, result.AccessToken);

var client = new StreamAnalyticsManagementClient(creds);

var jobCreateParameters = new JobCreateOrUpdateParameters
        {
            Job = new Job
            {
                Name = streamAnalyticsJobName,
                Location = "North Europe",
                Properties = new JobProperties
                {
                    EventsOutOfOrderPolicy = EventsOutOfOrderPolicy.Adjust,
                    Sku = new Sku
                    {
                        Name = "Standard"
                    }
                }
            }
        };

 var jobCreateResponse = client.StreamingJobs.CreateOrUpdate(resourceGroupName, jobCreateParameters);

我可以成功获取令牌,但创建作业失败:

AuthorizationFailed: The client 'REDACTED' with object id 'REDACTED' does not have authorization to perform action 'Microsoft.StreamAnalytics/streamingjobs/write' over scope '/subscriptions/REDACTED/resourcegroups/REDACTED/providers/Microsoft.StreamAnalytics/streamingjobs/REDACTED'

难道我做错了什么?该应用程序具有委派权限集。

4

1 回答 1

4

更新 - 2015 年 12 月 8 日

现在有一种简单的方法可以将角色分配给服务主体。有关更多详细信息,请参阅此链接:https ://azure.microsoft.com/en-in/documentation/articles/resource-group-create-service-principal-portal/ 。


原始回复

当您授予对 Azure 订阅的应用程序的访问权限时,会在后台使用Service Principal您的 Azure AD 中的用户类型创建一个用户。您在下面使用的代码假定您Service Principal在获取访问令牌时正在使用此用户。

var clientCredential = new ClientCredential(clientId, appKey);

var result = authContext.AcquireToken("https://management.core.windows.net/", clientCredential);
var creds = new TokenCloudCredentials(subscriptionId, result.AccessToken);

但是,默认情况下,该用户没有被授予您订阅的任何权限 (RBAC),这就是您收到授权错误的原因。

要解决此问题,您需要做的是在您的订阅中为该用户授予适当的角色。现在您可以PowerShell这样做,也可以通过代码使用 ADAL 库 + 发出一些 Web 请求来完成。

我所做的是使用 ADAL 库来获取访问令牌,然后使用Google Postman(或Fiddler)做其他事情。就我而言,它是一个 Web 应用程序。这是我所做的:

  1. Global Administrator我以(订阅所有者)身份登录应用程序并获得了code. 使用那个code和 ADAL 库,我得到了访问令牌(我们称之为token1)。

        var authContext = new AuthenticationContext(string.Format("{0}/common", signinEndpoint));//signinEndpoint = https://login.windows.net
        var result = await authContext.AcquireTokenByAuthorizationCodeAsync(code, redirectUri, credential);
    
  2. 我复制了result上面返回给我的租户 ID 和访问令牌。

  3. 接下来我Service Principal使用 POSTMAN 找到了用户的对象 ID。这是我在那里执行的 GET URL。对于Authorization标题,您需要使用Bearer {token1}.

    https://graph.windows.net/{subscription-id}/servicePrincipals?api-version=1.5&$filter=appId eq '{app-client-id}'

  4. token2之后,我使用以下代码为服务管理 API 操作获取了另一个访问令牌(我们称之为):

    authContext = new AuthenticationContext(string.Format("{0}/{1}", signinEndpoint, result.TenantId));
    result = await authContext.AcquireTokenSilentAsync(serviceManagementApiEndpoint, credential, new UserIdentifier(request.UserInfo.UniqueId, UserIdentifierType.UniqueId));//serviceManagementApiEndpoint = https://management.core.windows.net/
    
  5. 之后,我列出了订阅中的角色并选择了我想分配给我的Service Principal用户的角色。就我而言,我想分配一个Reader角色,所以我记下了角色的 ID。对于Authorization标题,您需要使用Bearer {token2}.

    https://management.azure.com/subscriptions/{subscription-id}/providers/Microsoft.Authorization/roleDefinitions?api-version=2015-06-01

  6. 接下来是将此角色分配给用户。为此,我创建了一个 guidrole assignment id并使用了以下 URL:

    https://management.azure.com/subscriptions/{subscription-id}/providers/microsoft.authorization/roleassignments/{role-assignment-id}?api-version=2015-06-01

这将是一个PUT请求,请求正文将类似于:

{
"properties":
    {
        "roleDefinitionId": "{role id of the selected role from step 5}",
        "principalId": "{id of the service principal from step 3"
    }
} 

请确保content-type请求的 设置为application/json;odata=verbose而不是application/json

差不多就是这样!之后,您的代码应该可以正常工作:)

试一试,看看会发生什么。

于 2015-07-17T13:29:57.393 回答