Provisioning Service Bus Topics with Access rules through code

Recently, I was architecting a multi-tenant solution. The solution enables each tenant to have multiple devices connected. The devices are then able to communicate with the server component, but also, the server component needs to be able to communicate with each of the devices. To do that, we also needed a way to be able to specify security rules for those new topics.

The approach we ended up taking was using Service Bus Topics. Specifically, each tenant gets its own topic instance, and each device underneath that tenant gets its own Subscription. I already talked about creating a subscription with a custom Authorization rule. In that post, I showed you how to copy the access rules from a topic. But in this one, I wanted to show how to create those rules.

private void CreateTopic(string topicName, ServiceBusConnectionData serviceBusConnectionData)
{
    // First, we need to get the general housekeeping done
    var serviceBusUri =
        ServiceBusEnvironment.CreateServiceUri("sb", serviceBusConnectionData.Namespace, String.Empty).ToString().Trim('/');


    var tokenProvider =
        TokenProvider.CreateSharedAccessSignatureTokenProvider(serviceBusConnectionData.AccountName,
            serviceBusConnectionData.Key);


    // to create a topic, we need a namespace manager
    var namespaceManager = new NamespaceManager(serviceBusUri, tokenProvider);


    // and to create a topic with access rules, we need a topic description
    var topicDescription = new TopicDescription(topicName);


    // We actually generate a random key to use as a password for our rule     
    var pass = SharedAccessAuthorizationRule.GenerateRandomKey(); 


    topicDescription.Authorization.Add(new SharedAccessAuthorizationRule("read", pass,
        new[] {AccessRights.Listen}));


    namespaceManager.CreateTopic(topicDescription);
}

The main pieces of the code are the last lines, related to generating a random key and adding a new authorization rule. I could not find any single documentation on this topic online (that talked about this), so it was a matter of giving it a try. But it works.