1

I need to create topic, subscription and SAS policy for azure service bus namespace using shared access policy connectionstring. for that I have used "Microsoft.Azure.ServiceBus" NuGet package.(I am using this NuGet package because I am using .NET Core 2.1).

Note :- Namespace is already created in azure service bus.

What I have tried :-

Now, I can create topic and subscription using following code as

 public static async Task CreateTopicSubscriptionAndSASPolicy()
    {
        string ServiceBusConnectionString = "Endpoint=sb://servicebusnameone.servicebus.windows.net/;SharedAccessKeyName=xxxxx;xxxxxxxxxxxxxxxxxxxxxxx";
        string topic = "TopicOne";
        string subscriptionName = "SubOne";
        var client = new ManagementClient(ServiceBusConnectionString);

        if (!await client.TopicExistsAsync(topic))
        {
            await client.CreateTopicAsync(topic);
        }
        if (!await client.SubscriptionExistsAsync(topic, subscriptionName))
        {
            await client.CreateSubscriptionAsync(new SubscriptionDescription(topic, subscriptionName));
        }

        IEnumerable<AccessRights> accessRights = new[] { AccessRights.Send };
        SharedAccessAuthorizationRule sharedAccessAuthorizationRule = new SharedAccessAuthorizationRule("SendRule", accessRights);
        //TO DO Create SAS Policy....
    }

Now, I need to create SAS policy at namespace level but I am not sure how can I do it? I have also read following Microsoft documentation and stackoverflow question-answer

  1. https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-sas

  2. https://github.com/Huachao/azure-content/blob/master/articles/service-bus/service-bus-shared-access-signature-authentication.md

  3. Shared Access Policy Programatic Creation for Azure Service Bus

  4. Using SAS Token with Azure ServiceBus

  5. Azure Service Bus Shared Access Signature Generation

Question :-

  1. How can I create SAS policy in azure service bus namespace?
  2. There is any way to configure topic/subscriptions while creating? (because while I create topic using above given code it create topic with Max size 1024 MB but I need to set it 5120 MB)?
  3. Apart from this there is any better way(best practice) to create topic, subscription and SAS policy using connection string in .Net Core 2.1?

Note:- Any working example is very helpful to clear understanding.

Tom
  • 47,574
  • 2
  • 16
  • 29
Harish
  • 789
  • 1
  • 7
  • 21

1 Answers1

2

Update 2020/12/22

I have checked the source code of all major packages, there is no way to create the access policy based on namespace with those packages, there only can create on entities.

So, let follow a more basic way, use rest API(The underly logic of those packages is also based on this.).

Below is the code and works fine on my side:

using Microsoft.Azure.Services.AppAuthentication;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp23
{
    class Program
    {
        static void Main(string[] args)
        {
            CallWebAPIAsync().Wait();
        }

        static async Task CallWebAPIAsync()
        {
            AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
            string accessToken = azureServiceTokenProvider.GetAccessTokenAsync("https://management.azure.com/").Result;
            using (var client = new HttpClient())
            {
                client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
                client.BaseAddress = new Uri("https://management.azure.com/");


                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                //PUT Method  
                var jsonString = "{ \"properties\": { \"rights\": [ \"Listen\", \"Send\", \"Manage\" ] } }";
                var httpContent = new StringContent(jsonString, Encoding.UTF8, "application/json");
                HttpResponseMessage response = await client.PutAsync("https://management.azure.com/subscriptions/e5b0xxxxxx9f4c68/resourceGroups/0730BowmanWindow/providers/Microsoft.ServiceBus/namespaces/bowman1012/AuthorizationRules/testbowman?api-version=2017-04-01",httpContent);
                if (response.IsSuccessStatusCode)
                {
                    Console.WriteLine(response.Content.ReadAsStringAsync().Result);
                }
                else
                {
                    Console.WriteLine("Internal server Error");
                }
            }
        }
    }
}

It works fine:

enter image description here

Below is the rest API reference, any doubts please let me know.

https://learn.microsoft.com/en-us/rest/api/servicebus/stable/namespaces%20-%20authorization%20rules/createorupdateauthorizationrule

Update:

.csproj file

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
   
    <PackageReference Include="Azure.Messaging.ServiceBus" Version="7.0.0" />
   
    <PackageReference Include="Microsoft.Azure.ServiceBus" Version="5.1.0" />
  </ItemGroup>

</Project>

Program.cs

using Microsoft.Azure.ServiceBus;
using Microsoft.Azure.ServiceBus.Primitives;
using Azure.Messaging.ServiceBus.Administration;
using System;
using System.Text;

namespace ConsoleApp15
{
    class Program
    {
        static async System.Threading.Tasks.Task Main(string[] args)
        {
            string keyname = "test";
            string sharedaccesskey = "xxxxxx";
            var validityDuration = TimeSpan.FromHours(24);
            TokenScope tokenScope = TokenScope.Entity;

            //Get the SAS based on the namespace.
            var tokenprovider =(SharedAccessSignatureTokenProvider) TokenProvider.CreateSharedAccessSignatureTokenProvider(keyname,sharedaccesskey,validityDuration,tokenScope);
            var token =await tokenprovider.GetTokenAsync("sb://bowman1012.servicebus.windows.net/", TimeSpan.FromHours(24));

            //Send message to service bus queue based on SAS token.
            ServiceBusConnectionStringBuilder builder = new ServiceBusConnectionStringBuilder {
                Endpoint= "sb://bowman1012.servicebus.windows.net/",
                EntityPath= "testbowman",
                SasToken= token.TokenValue
            };
            QueueClient client = new QueueClient(builder);
            Message mes = new Message();
            mes.Body = Encoding.ASCII.GetBytes("This is a test.20201208");
            await client.SendAsync(mes);

            //Create a topic with 5120MB.
            var client1 = new ServiceBusAdministrationClient("Endpoint=sb://bowman1012.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=xxxxxx");
            var topicOptions = new CreateTopicOptions("20201208")
            {
                AutoDeleteOnIdle = TimeSpan.FromDays(7),
                DefaultMessageTimeToLive = TimeSpan.FromDays(2),
                DuplicateDetectionHistoryTimeWindow = TimeSpan.FromMinutes(1),
                EnableBatchedOperations = true,
                EnablePartitioning = false,
                MaxSizeInMegabytes = 5120,
                RequiresDuplicateDetection = true,
                UserMetadata = "some metadata"
            };
            topicOptions.AuthorizationRules.Add(new SharedAccessAuthorizationRule(
                    "allClaims",
                    new[] { AccessRights.Manage, AccessRights.Send, AccessRights.Listen }));
            await client1.CreateTopicAsync(topicOptions);


            Console.WriteLine("Hello World!" + "\n" + token.TokenValue);
        }
    }
}

And works fine on my side:

enter image description here

enter image description here


Original Answer:

How can I create SAS policy in azure service bus namespace?

You can use SharedSecretTokenProvider.BuildKey(string appliesTo, string action) method to create the SAS.

This is the API reference:

https://learn.microsoft.com/en-us/dotnet/api/microsoft.servicebus.sharedaccesssignaturetokenprovider?view=azure-dotnet

Or you can refer to this doc(some simple code):

https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-sas#use-shared-access-signature-authorization

There is any way to configure topic/subscriptions while creating? (because while I create topic using above given code it create topic with Max size 1024 MB but I need to set it 5120 MB)?

Use NamespaceManager.CreateTopic method, this method returns TopicDescription object, you can set the size by the MaxSizeInMegabytes property(in megabytes).

This is the API reference:

https://learn.microsoft.com/en-us/dotnet/api/microsoft.servicebus.namespacemanager.createtopic?view=azure-dotnet

https://learn.microsoft.com/en-us/dotnet/api/microsoft.servicebus.messaging.topicdescription.maxsizeinmegabytes?view=azure-dotnet#Microsoft_ServiceBus_Messaging_TopicDescription_MaxSizeInMegabytes

Apart from this there is any better way(best practice) to create topic, subscription and SAS policy using connection string in .Net Core 2.1?

I'm not sure what you are worried about on this point, maybe you can explain what you are looking for? This method of obtaining is provided by the above official document.

And the method to create subscription:

https://learn.microsoft.com/en-us/dotnet/api/microsoft.servicebus.namespacemanager.createsubscription?view=azure-dotnet

Cindy Pau
  • 13,085
  • 1
  • 15
  • 27
  • It seems that SharedSecretTokenProvider inside the "WindowsAzure.ServiceBus" NuGet package which is not compatible in .NET Core 2.1. – Harish Dec 08 '20 at 07:55
  • @Harish OK, will do a check.:) – Cindy Pau Dec 08 '20 at 07:59
  • @Harish Update the code, it works fine on my side, please have a check. – Cindy Pau Dec 08 '20 at 10:07
  • Thanks for your efforts. I appreciate it. Actually, My question is how can create SAS policy for namespace in azure service bus? – Harish Dec 08 '20 at 12:12
  • @Harish Sorry I made a mistake, I will modify the code tomorrow. Now has something to do... – Cindy Pau Dec 08 '20 at 12:15
  • No problem! I appreciate your effort. – Harish Dec 08 '20 at 12:17
  • @Harish I have found a method, but it is not compatible with .net core 2.1, I will follow up on this issue.:) – Cindy Pau Dec 09 '20 at 11:38
  • Thanks! for this. – Harish Dec 09 '20 at 11:39
  • Do you get any chance to look into it? – Harish Dec 22 '20 at 05:58
  • @Developer I read the source code of several major packages and found that the creation operation is based on entities. So you need to use the basicest REST API to send a request to create the policy. I did not update because I found that I can only use rest api to achieve, but I am not familiar with rest api, so it has been shelved. . . – Cindy Pau Dec 22 '20 at 06:08
  • @Developer I will do it for you now.:) – Cindy Pau Dec 22 '20 at 06:09
  • @Developer I have updated the answer, please have a look. Any doubts please let me know. And sorry for I reply too late.:) – Cindy Pau Dec 22 '20 at 07:11
  • I got an error at azureServiceTokenProvider.GetAccessTokenAsync method. Error :- "Parameters: Connection String: [No connection string specified], Resource: https://management.azure.com/, Authority: . Exception Message: Tried the following 4 methods to get an access token, but none of them worked....". do you have idea why it is? – Harish Dec 22 '20 at 09:16
  • @Developer Have you try to do it on the API reference page? Do you get the format of the request from there? – Cindy Pau Dec 22 '20 at 09:19
  • @Developer I see your error, but it has no matter with the connection string... – Cindy Pau Dec 22 '20 at 09:21
  • Sorry to disturb you. I did not get how do you get token without giving any details. Do you given any access at azure. Could you please help me to understand how do you get token using GetAccessTokenAsync method. – Harish Dec 22 '20 at 10:06