Azure Event Hub with Resource Manager Template

05/03/2016

I got a request on email, whether or not it is possible to create Event Hub with Azure Resource Manager templates (ARM). And yes of course it is – but yet again Microsofts documentation is lacking, so instead of just replying to the email I decided to post the answer here, for everyone to benefit from.

As you might know the Event Hub service is owned by the Service Bus team, and it is also located under the service bus tab and the messaging type in the old management portal (manage.windowsazure.com). It does however still have it own ARM resource provider (the backend that exposes the ARM functionality and implements the logic for instantiating a new resource is called a resource provider), it is called Microsoft.EventHub, no surprise there. If you want an event hub and e.g a service bus queue to reside in the same namepace that is possible as long as you create them with the same namespace name.

Currently there is only one version of the resource provider, namely 2014-09-01.

Lets see how a template could look
[js]
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"eventHubName": {
"type": "string",
"metadata": {
"description": "Name of the Event Hub"
}
},
"eventHubSendPrimaryKey": {
"type": "string"
},
"eventHubSendSecondaryKey": {
"type": "string"
},
"eventHubListenPrimaryKey": {
"type": "string"
},
"eventHubListenSecondaryKey": {
"type": "string"
}
},
"variables": {
"eventHubNamespace": "[concat(‘eventHub’,uniqueString(resourceGroup().id))]",
"location": "[resourceGroup().location]",
"sbListenOnlyKeyName": "ListenOnlyKey",
"ehVersion": "2014-09-01",
"defaultSASKeyName": "RootManageSharedAccessKey",
"authRuleResourceId": "[resourceId(‘Microsoft.Eventhub/namespaces/authorizationRules’, variables(‘eventHubNamespace’), variables(‘defaultSASKeyName’))]",
"sendAuthRuleResourceId": "[resourceId(‘Microsoft.Eventhub/namespaces/authorizationRules’, variables(‘eventHubNamespace’), ‘SendOnlyKey’)]",
"listenAuthRuleResourceId": "[resourceId(‘Microsoft.Eventhub/namespaces/authorizationRules’, variables(‘eventHubNamespace’), ‘ListenOnlyKey’)]"
},
"resources": [
{
"apiVersion": "[variables(‘ehVersion’)]",
"name": "[variables(‘eventHubNamespace’)]",
"type": "Microsoft.EventHub/namespaces",
"location": "[variables(‘location’)]",
"resources": [
{
"apiVersion": "[variables(‘ehVersion’)]",
"name": "[parameters(‘eventHubName’)]",
"type": "eventHubs",
"dependsOn": [
"[concat(‘Microsoft.EventHub/namespaces/’, variables(‘eventHubNamespace’))]"
],
"properties": {
"path": "[parameters(‘eventHubName’)]"
}
},
{
"apiVersion": "[variables(‘ehVersion’)]",
"name": "[concat(variables(‘eventHubNamespace’),’/SendOnlyKey’)]",
"type": "Microsoft.EventHub/namespaces/authorizationRules",
"dependsOn": [
"[concat(‘Microsoft.EventHub/namespaces/’, variables(‘eventHubNamespace’))]"
],
"location": "[variables(‘location’)]",
"properties": {
"KeyName": "SendOnlyKey",
"ClaimType": "SendSharedAccessKey",
"ClaimValue": "None",
"PrimaryKey": "[parameters(‘eventHubSendPrimaryKey’)]",
"SecondaryKey": "[parameters(‘eventHubSendSecondaryKey’)]",
"Rights": [ "Send" ],
"Revision": -1
}
},
{
"apiVersion": "[variables(‘ehVersion’)]",
"name": "[concat(variables(‘eventHubNamespace’),’/’,variables(‘sbListenOnlyKeyName’))]",
"type": "Microsoft.EventHub/namespaces/authorizationRules",
"dependsOn": [
"[concat(‘Microsoft.EventHub/namespaces/’, variables(‘eventHubNamespace’))]"
],
"location": "[variables(‘location’)]",
"properties": {
"KeyName": "ListenOnlyKey",
"ClaimType": "ReceiveSharedAccessKey",
"ClaimValue": "None",
"PrimaryKey": "[parameters(‘eventHubListenPrimaryKey’)]",
"SecondaryKey": "[parameters(‘eventHubListenSecondaryKey’)]",
"Rights": [ "Listen" ],
"Revision": -1
}
}
]
}
],
"outputs": {
"NamespaceDefaultConnectionString": {
"type": "string",
"value": "[listkeys(variables(‘authRuleResourceId’), variables(‘ehVersion’)).primaryConnectionString]"
},
"SendOnlyConnectionString": {
"type": "string",
"value": "[listkeys(variables(‘sendAuthRuleResourceId’), variables(‘ehVersion’)).primaryConnectionString]"
},
"ReceiveOnlyConnectionString": {
"type": "string",
"value": "[listkeys(variables(‘listenAuthRuleResourceId’), variables(‘ehVersion’)).primaryConnectionString]"
}
}
}

[/js]
Notice that I dynamically generate the namespace "eventHubNamespace": "[concat('eventHub',uniqueString(resourceGroup().id))]", I do this because it is then possible to delete the entire resource group and recreate it without problems. If you supply a namespace name as a parameter you will not be able to recreate a the resource group with the same namespace within a period of 7 days after deletion. This a special “feature” of service bus namespaces, that I haven’t seen on other Azure resources.

The rest of the template is fairly straight forward, a namespace is created first, then an event hub is created inside the namespace before we create a send and a receive authorization rule, so you can use the Event Hub without using the RootManageSharedAccessKey. To create the send and listen rules we need to supply keys, I have done this as parameters, but you can also generate keys directly from the template by using my sub template trick outlined in the post about service bus queues.

The keys was generated with the following powershell scripts
[powershell]
#
# GenerateKey.ps1
#
$bytes = New-Object Byte[] 32
$rand = [System.Security.Cryptography.RandomNumberGenerator]::Create()
$rand.GetBytes($bytes)
$rand.Dispose()
$key = [System.Convert]::ToBase64String($bytes)
Write-Host $key
[/powershell]

Finally the connection strings are outputted.

You can grab my entire project from github, https://github.com/sjkp/Azure.ARM.EventHub.