我一直在尝试(并且失败)以编程方式创建Azure Stream Analytics作业。我最初是在关注这个例子:
https://azure.microsoft.com/en-gb/documentation/articles/stream-analytics-dotnet-management-sdk/
但它会弹出一个对话框供您登录。我希望能够做到这个服务器端。看起来我需要使用Azure AD来使用Resource Manager 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'
我做错了吗?该应用已设置委派权限。
答案 0 :(得分:4)
更新 - 2015年12月8日
现在可以轻松地将角色分配给服务主体。有关详细信息,请参阅此链接:https://azure.microsoft.com/en-in/documentation/articles/resource-group-create-service-principal-portal/。
原始回复
当您向Azure订阅授予对应用程序的访问权限时,将在Azure AD中使用Service Principal
用户类型创建用户。您在下面使用的代码假定您在获取访问令牌时使用此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应用程序。这就是我的所作所为:
我以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);
我复制了上面result
返回给我的租户ID和访问令牌。
接下来我做的是使用POSTMAN找到Service Principal
用户的对象ID。这是我在那里执行的GET URL。对于Authorization
标头,您需要使用Bearer {token1}
。
https://graph.windows.net/{subscription-id}/servicePrincipals?api-version=1.5&$filter=appId eq '{app-client-id}'
之后,我使用以下代码获取了另一个访问令牌(让我们称之为token2
)以进行Service Management 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/
之后,我在订阅中列出了角色,并选择了我想要分配给Service Principal
用户的角色。在我的情况下,我想分配一个Reader
角色,所以我记下了角色的ID。对于Authorization
标头,您需要使用Bearer {token2}
。
https://management.azure.com/subscriptions/{subscription-id}/providers/Microsoft.Authorization/roleDefinitions?api-version=2015-06-01
接下来是将此角色分配给用户。为此我创建了一个guid role 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
。
几乎就是这样!之后你的代码应该可以正常工作:)
尝试一下,看看会发生什么。