Authorization failure when creating a Stream Analytics job

谁都会走 提交于 2020-01-13 22:42:39

问题


I've been trying (and failing) to create an Azure Stream Analytics job programatically. I was following this example originally:

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

But it pops up a dialog for you to log in. I want to be able to do this server side. It looks like I need to use Azure AD to use the Resource Manager APIs. I've been working my way through this:

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

And the code looks like this:

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);

I can successfully acquire a token, but creating the job fails:

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'

Am I doing something wrong? The app has the delegated permissions set.


回答1:


UPDATE - 08-Dec-2015

There's an easy way to assign roles to Service Principals now. Please see this link for more details: https://azure.microsoft.com/en-in/documentation/articles/resource-group-create-service-principal-portal/.


Original Response

When you grant access to an application to your Azure subscription, behind the scenes a user is created with Service Principal user type in your Azure AD. The code you're using below assumes that you're using this Service Principal user when getting access token.

var clientCredential = new ClientCredential(clientId, appKey);

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

However by default this user is not granted any permissions (RBAC) on your subscription and that's why you're getting the authorization error.

To solve this problem, what you would need to do is grant appropriate role to this user in your subscription. Now you can use PowerShell to do so or you can do it via code using ADAL library + making some web requests.

What I did was I made use of ADAL library to get access tokens and then used Google Postman (or Fiddler) to do other stuff. In my case, it was a web application. Here's what I did:

  1. I logged in into the application as Global Administrator (Subscription Owner) and got a code. Using that code and ADAL library, I got the access token (let's call it token1).

        var authContext = new AuthenticationContext(string.Format("{0}/common", signinEndpoint));//signinEndpoint = https://login.windows.net
        var result = await authContext.AcquireTokenByAuthorizationCodeAsync(code, redirectUri, credential);
    
  2. I copied the tenant id and access token returned to me in result above.

  3. Next thing I did was I found out the object id of the Service Principal user using POSTMAN. This is the GET URL I executed there. For Authorization header, you would need to use Bearer {token1}.

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

  4. After that I acquired another access token (let's call it token2) for Service Management API operation using the code below:

    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. After that I listed the roles in my subscription and picked the role I wanted to assign to my Service Principal user. In my case, I wanted to assign a Reader role so I noted down the role's id. For Authorization header, you would need to use Bearer {token2}.

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

  6. Next is assignment of this role to the user. For this I created a guid as role assignment id and used the following URL:

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

It's going to be a PUT request and this was the request body would be something like:

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

Please ensure that the content-type of the request is set as application/json;odata=verbose and not application/json.

That's pretty much it! After that your code should work just fine :)

Give it a try and see what happens.



来源:https://stackoverflow.com/questions/31471828/authorization-failure-when-creating-a-stream-analytics-job

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!