0
votes

I am trying to create SAS policy for azure service bus namespace using shared access policy connectionstring in .NET Core 2.1.

I can create it using Microsoft.Azure.Management.ServiceBus NuGet package as follows

private static async Task<string> GetToken()
    {
        try
        {
            // Check to see if the token has expired before requesting one.
            // We will go ahead and request a new one if we are within 2 minutes of the token expiring.
            if (tokenExpiresAtUtc < DateTime.UtcNow.AddMinutes(-2))
            {
                Console.WriteLine("Renewing token...");

                var tenantId = appOptions.TenantId;
                var clientId = appOptions.ClientId;
                var clientSecret = appOptions.ClientSecret;

                var context = new AuthenticationContext($"https://login.microsoftonline.com/{tenantId}");

                var result = await context.AcquireTokenAsync(
                    "https://management.core.windows.net/",
                    new ClientCredential(clientId, clientSecret)
                );

                // If the token isn't a valid string, throw an error.
                if (string.IsNullOrEmpty(result.AccessToken))
                {
                    throw new Exception("Token result is empty!");
                }

                tokenExpiresAtUtc = result.ExpiresOn.UtcDateTime;
                tokenValue = result.AccessToken;
                Console.WriteLine("Token renewed successfully.");
            }

            return tokenValue;
        }
        catch (Exception e)
        {
            Console.WriteLine("Could not get a new token...");
            Console.WriteLine(e.Message);
            throw e;
        }
    }
private static async Task CreateSASPolicy()
    {
        try
        {
            if (string.IsNullOrEmpty(namespaceName))
            {
                throw new Exception("Namespace name is empty!");
            }

            var token = await GetToken();

            var creds = new TokenCredentials(token);
            var sbClient = new ServiceBusManagementClient(creds)
            {
                SubscriptionId = appOptions.SubscriptionId,
            };

            List<AccessRights?> list = new List<AccessRights?> { AccessRights.Send };
            var AuthRule = new SBAuthorizationRule { Rights = list };
            var authorizationRuleName = "SendRule"; //policy name
              
            Console.WriteLine("Creating SAS policy...");
            var result = sbClient.Namespaces.CreateOrUpdateAuthorizationRuleAsync(resourceGroupName, namespaceName, authorizationRuleName, AuthRule).Result;
            Console.WriteLine("Created SAS policy successfully.");
        }
        catch (Exception e)
        {
            Console.WriteLine("Could not create a SAS policy...");
            Console.WriteLine(e.Message);
            throw e;
        }
    }

But for above code I need to give at least "Azure Service Bus Data Owner" to the app which we are using to create token.

I have also tried using http client as follows

using (HttpClient httpclient = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true }))
        {
            httpclient.DefaultRequestHeaders.Accept.Add(
                new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

            httpclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
                Convert.ToBase64String(
                    System.Text.ASCIIEncoding.ASCII.GetBytes(
                        string.Format("{0}:{1}", "", accessToken))));

            string baseAddress = @"https://management.core.windows.net/<subscriptionId>/services/ServiceBus/namespaces/<namespace>/AuthorizationRules/";

            var sendRule = new SharedAccessAuthorizationRule("contosoSendAll",
                new[] { AccessRights.Send });
            
            var result = await httpclient.GetAsync(baseAddress).ConfigureAwait(false);
            if (result.IsSuccessStatusCode)
            {
                var response = await result.Content.ReadAsStringAsync().ConfigureAwait(false);
              
            }
        }

It returns 403(Forbidden).

Question :-

  • Is there any way to create SAS policy without giving "Azure Service Bus Data Owner" permission to app? How?
  • Can create SAS policy using shared access policy connectionstring? How?
  • Can create SAS policy by using current login user credentials? How?
1
Could you please describe Q3 in detail?Jim Xu
@JimXu About Q3 - In my application we are using AAD SSO for login. In azure service bus login user has right to manage service bus. so, My question is can I use login user credential to generate token and using that token can I create SAS policy at namespace level?Harish Shisode
Regarding the issue, please refer to docs.microsoft.com/en-us/azure/active-directory/develop/…Jim Xu

1 Answers

1
votes

Can create SAS policy using shared access policy connectionstring? How?

If you use shared access policy connectionstring to create SAS policy, we just can create policy for topic or subscription. For the namespace, we need to implement it with Azure Resource provider API. It the way you are currently using. For more details, please refer to here.

Regarding how to create policy fro the topic or queue, we can use the package Azure.Messaging.ServiceBus.Administration.

For example

ServiceBusAdministrationClient client = new ServiceBusAdministrationClient(connectionString);
   
            QueueProperties queue =await client.GetQueueAsync("myqueue");
            queue.AuthorizationRules.Add( new SharedAccessAuthorizationRule(
                 "manage",
                 new[] { AccessRights.Manage, AccessRights.Send, AccessRights.Listen })
            );
            queue= await client.UpdateQueueAsync(queue);

            foreach (var rule in queue.AuthorizationRules) {
                Console.WriteLine(rule.KeyName);
            }

enter image description here

Is there any way to create SAS policy without giving "Azure Service Bus Data Owner" permission to app? How?

When we use Azure Resource Provider API to create the resource, we should have the right Azure RABC permissions. About creating policy, we need to have permissions Microsoft.ServiceBus/namespaces/authorizationRules/action and Microsoft.ServiceBus/namespaces/authorizationRules/write. If you do not want to use Azure Service Bus Data Owner, you can create a custom role with these permissions. For more details, please refer to here and here.