Jeff Saremi
Jeff Saremi

Reputation: 3014

How to create role assignments using Azure Active Directory Graph client in C#?

I'm using this library : Microsoft.Azure.ActiveDirectory.GraphClient class: ActiveDirectoryClient.

I'd like to give an Application (I have the appID) "Owner" access to some subscription. How would I go about doing that? Thanks

Upvotes: 1

Views: 825

Answers (1)

Jeff Saremi
Jeff Saremi

Reputation: 3014

The whole premise of this question is incorrect. The GraphClient is not the right client to manage such authorizations. The proper API library for that is Microsoft.Azure.Management.Authorization and the class AuthorizationManagementClient.

I will post additional notes on the actual sequence of calls.

*** Update ***********

As promised here's the sample code:

    public static async Task<IServicePrincipal> GetServicePrincipalAsync(string accessToken, string tenantId, string clientId)
    {
        var graphClient = NewActiveDirectoryClient(accessToken, tenantId);
        var matches = await graphClient.ServicePrincipals.Where(sp => sp.AppId == clientId).ExecuteAsync();
        return matches.CurrentPage.ToList().FirstOrDefault();
    }
    private static ActiveDirectoryClient NewActiveDirectoryClient(string accessToken, string tenantId)
    {
        TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
        tcs.SetResult(accessToken);
        return new ActiveDirectoryClient(
            new Uri($"{GraphApiBaseUrl}{tenantId}"),
            async () => { return await tcs.Task; });
    }

First you need to get the ObjectId of the principal you want to add. In the case of ServicePricipal I have a function that gets it from the directory like so:

Then using that and a scope ("/subscriptions/{my_subscription_id}", for the entire subscription) you can create a RoleAssignment:

    public static async Task AssignRoleToPrincipalAsync(
        string accessToken, 
        string subscriptionId, 
        string scope, 
        string roleName,
        string principalObjectId)
    {
        using (var client = NewAuthorizationManagementClient(accessToken, subscriptionId))
        {
            RoleDefinition roleDef = (await FindRoleDefinitionAsync(accessToken, subscriptionId, scope, roleName)).FirstOrDefault();
            if (roleDef == null)
                throw new Exception($"Role was not found: {roleName}");
            var props = new RoleAssignmentProperties()
            {
                PrincipalId = principalObjectId,
                RoleDefinitionId = roleDef.Id
            };
            await client.RoleAssignments.CreateAsync(scope, Guid.NewGuid().ToString("N"), props);
        }
    }

    private static AuthorizationManagementClient NewAuthorizationManagementClient(string accessToken, string subscriptionId)
    {
        return new AuthorizationManagementClient(new TokenCredentials(accessToken)) { SubscriptionId = subscriptionId};
    }

***** Update *****
To get the token using Azure.Identity you can use the following snippet

var accessToken = await new AzureCliCredential().GetTokenAsync(  
  new TokenRequestContext(new[] { "https://management.azure.com/.default" }));

var client = new AuthorizationManagementClient(  
  new TokenCredentials(accessToken.Token))
  {
      SubscriptionId = subscription.Data.SubscriptionId
  };

Upvotes: 2

Related Questions