Event Hub Publisher Policy in Action

The 2.6 SDK released last week included some important enhancements to the client experience of working with Event Hubs. This blog will describe using SAS based publisher policy with Event Hubs.

This High Level Overview of SAS with Service Bus explains the background of SAS – the rest of this blog will show SAS in action.

If you don’t already have one you’ll need to create an Event Hub in the Azure portal.

 

Once that’s done click on your Event Hub

From here you can click on the Configure tab to get to the Share Access Policies at the bottom of the page.

The first thing to do here will be to create a new Policy. Do this by typing in a name and selection the permissions – in our case only check the Send box.

From here whenever you click the Connection Information within the context of your Event Hub you will see a SAS policy as shown below.

 

Clicking this brings up the dialog below.

Here’s where a lot of people get lost with SAS – what we have here is the Policy, not a SAS token. We can use this policy to send to Event Hub, but since you can only have a limited number of policies (and it’s a small number) you would need to share this key with all your senders. This method of sharing keys with multiple senders exposes the keys directly to the senders and greatly increases the change of the keys being lost or misused. A SAS Key is like a private key and the Key Name (the policy name we typed in) is like the public key. It’s safe to share public keys, but not private ones. Worse still once you have shared the SAS Key (the private key) if you ever needed to regenerate this key (done by clicking the Regenerate button back in that Configure screen where you create this policy) it would stop everyone who has this key from sending to your Event Hub.

Instead we can use this Policy to create a SAS Token – which is a time bound permission for a specific publisher using this policy (i.e. it allows a specific identity to send to this Event Hub, inheriting the Send permission from the Policy that creates the token).

If this all sounds complex it’s really not that bad. Here’s how you do it:

Create a .NET application, I used a Console application, and pull in the latest NuGet for Service Bus – ALWAYS use NuGet to source your packages. Copy out that Connection String from the portal shown in the image above. To make my life easier I may put this in Notepad or somewhere temporary while working.

Create variables for a publisher identity and an Event Hub name, these will be useful shortly.

 

 string publisherId = "1";
string eventHubName = "ingresshub";

Now I need to create a SAS Token from the Send SAS Policy that I created in the portal. Fortunately there is a method that does this for you shown below.

 string token = SharedAccessSignatureTokenProvider.GetPublisherSharedAccessSignature(
 new Uri("sb://techreadypt.servicebus.windows.net/"),
 eventHubName, publisherId, "Send",
 "<YOUR PRIMARY KEY>",
 new TimeSpan(0, 5, 0));

The first parameter is the URI of my Service Bus namespace. The second is the name of my Event Hub. The third is the publisher identity I wish to create – any unique identifier for the publisher will do, it’s your responsibility to pick and manage these. Fourth is the name of the policy that is used to create this token – in our case Send (which you typed into the portal earlier). The fifth parameter is the Primary Key for this policy – you can find this after the SharedAccessKey= part of the connection string you copied out of the portal. The sixth parameter is the timespan you wish for this token to be valid – again the choice here is yours and depends a largely on your specific scenario.

Once you have this token it can be used by an Event Hub publisher. You must provide this to your publishers either at registration time or in some other method that you determine is appropriate for your needs. Once a publisher has this token sending events to the Event Hub is three simple steps.

1) Create a connection string to the Event Hub using this token. The four parameters here are fairly self-explanatory. Be sure the URI does not have the Event Hub name in it, that’s the second parameter.

 var connStr = ServiceBusConnectionStringBuilder.CreateUsingSharedAccessSignature(
 new Uri("sb://techreadypt.servicebus.windows.net/"),
 eventHubName,
 publisherId,
 token);

2) Create an EventHubSender – it’s not really worth creating an EventHubClient here as all you can do is send with this token.

 var sender = EventHubSender.CreateFromConnectionString(connStr);

3) Call send on the EventHubSender and use an EventData object to send your data.

 sender.Send(new EventData(Encoding.UTF8.GetBytes("Hello Event Hub")));

That was easy! Now you have a unique publisher identity that is secure and has a lifetime that is in your control – at least at creation time. Suppose, however, that you want to block this publisher from sending to the Event Hub. Until the SAS Token you provided them expires there isn’t a way in SAS to do this – so Event Hubs enables publisher revocation. To do this you’ll need a connection string to your Service Bus namespace that has Manage permissions. For your entire namespace by default this will be called RootManageSharedAccessKey. If you don’t have a UNIX background you should be aware that Root means something very powerful and scary – I always create a separate Manage policy, which you now know how to do, and I create it at the Event Hub level so it is scoped only to the Event Hub and not the entire Namespace. After doing this you can copy out the Manage connection string from the portal and instantiate a NamespaceManager object using that connection string.

 var nsm = Microsoft.ServiceBus.NamespaceManager.CreateFromConnectionString(manageString);

This is a powerful object that allows you to do even more than the Azure portal with regards to Service Bus – that’s why using a scoped Manage policy is a good idea. It is with this object that we can revoke individual publishers as shown:

 nsm.RevokePublisher(eventHubName,publisherId);

After performing the revocation calling the same send code from above will result in a Microsoft.ServiceBus.Messaging.PublisherRevokedException with the message: "Publisher: 1, was revoked access to Send messages to EventHub.” You can list the revoked publishers from an Event Hub using the method shown below.

 var revokedPublishers = nsm.GetRevokedPublishers(eventHubName);

It is worth noting here that if not carefully managed this list can grow quite large and the results will be paged in pages of 100. In addition to counting as management calls (ingress) the results are counted as egress traffic and large lists can result in throttling if you don’t have many Throughput Units.

Finally you can restore a publisher with this method.

 nsm.RestorePublisher(eventHubName, publisherId);

Publisher policy is a simple and powerful capability of Event Hubs that can be used to protect your processing pipeline. It is, however, important to remember that real security lies in short token lifetimes and being careful with your keys - much like how you would with your house keys, but not giving them to people you don't trust and changing your locks if you lose them.