ARM Template for Event Grid integration with a new Azure Function
TL/DR – Link to the template: https://github.com/jcbrooks92/EventGridAzureFunctionARMTemplate/tree/master
Creating an ARM template with integration between an Azure function and Event Grid requires the general function template, Event Grid resource and lastly a system key from the Azure function that is used to authenticate the validation call from Event Grid.
Update 2/12/2020
There has been a recent update for a preview version of event grid ARM API that supports an endpoint specifically for AzureFunctions. I still need to test out this change to understand its behavior, but I just wanted to provide this update for those that may be interested in testing out the change.
“apiVersion”: “2020-01-01-preview”,
“properties”: {
“destination”: {
“endpointType”: “AzureFunction”,
“properties”: {
“resourceId”: “[resourceId(‘Microsoft.Web/sites/functions/’, parameters(‘AppName’), parameters(‘functionName’))]”
}
}
Update 1/10/2020
The section of creating your own Systemkeys for eventgrid is NO LONGER needed due to the update to the runtime here. In order for the System key to be created the Azure Function job host has to initialize at least once. As a workaround you can generate your own sytem key using the portion of the ARM template below .
{
"name": "default/eventgrid_extension",
"apiVersion": "2018-11-01",
"type": "host/systemkeys",
"properties": {
"name": "eventgrid_extension",
"value": "12345"
},
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('functionAppName'))]"
]
}
Lastly you need to generate the web hook URL that Event Grid will use to authenticate to the function app with the system key. You’ll need to make sure the job host has started in order for the validation to complete. I used a function app deployed with run from package and made the Event Grid Topic creation dependent on the function to provide enough time for the app to deploy prior to the validation occurring. My ‘endpointUrl’ is a value that creates the general webhook URL so the system key just needs to be plugged in.
"functionUrl" : "[concat('https://', variables('FunctionAppName'),'.azurewebsites.net/runtime/webhooks/eventgrid?functionName=', parameters('FunctionName'),'&code=')]",
{
"name": "[concat(parameters('eventGridTopicName'), '/Microsoft.EventGrid/', parameters('eventGridSubscriptionName'))]",
"type": "Microsoft.EventGrid/topics/providers/eventSubscriptions",
"location": "[parameters('location')]",
"apiVersion": "2018-01-01",
"properties": {
"destination": {
"endpointType": "WebHook",
"properties": {
"endpointUrl": "[concat(variables('functionUrl'), listKeys(resourceId('Microsoft.Web/sites/host/', variables('functionAppName'), 'default'),'2016-08-01').systemkeys.eventgrid_extension)]"
}
},
"filter": {
"includedEventTypes": [
"All"
]
}
},
"dependsOn": [
"[parameters('eventGridTopicName')]",
"[resourceId('Microsoft.Web/sites/host/systemkeys', variables('functionAppName'),'default','eventgrid_extension')]"
]
}
Azure Function ARM API Reference : https://github.com/Azure/azure-functions-host/issues/3994
Have you been able to create an event subscription between a domain topic and a function?
I finally got the domain topic subscriptions to work. The key notes from this snippet is the name and type, the name must include both the event grid domain name and topic.
{
“name”: “[concat(variables(‘eventGridDomainName’), ‘/myTopic/Microsoft.EventGrid/subscriptionName’)]”,
“type”: “Microsoft.EventGrid/domains/topics/providers/eventSubscriptions”,
“location”: “[resourceGroup().location]”,
“apiVersion”: “2019-06-01”,
“properties”: {
“destination”: {
“endpointType”: “WebHook”,
“properties”: {
“endpointUrl”: “function URL”
}
},
“filter”: {
“includedEventTypes”: [
“SomeEventType”
]
}
},
“dependsOn”: [
“[resourceId(‘Microsoft.EventGrid/domains’, variables(‘eventGridDomainName’))]”,
“[resourceId(‘Microsoft.EventGrid/domains/topics’, variables(‘eventGridDomainName’), ‘myTopic’)]”,
“[resourceId(‘Microsoft.Web/sites’, variables(‘functionAppName’))]”,
“[resourceId(‘Microsoft.Web/sites/config’, variables(‘functionAppName’), ‘appSettings’)]”
]
},
Hi Ricke,
I’m not as familiar with the EventGrid side of the house. thanks for sharing the solution.
You just rescued me from floundering about in ARM trying to get the syntax right for getting the eventgrid_extension value, with particular reference to the resourceId call. I’m not hugely experienced with ARM so I was struggling a bit! I’m using an ARM snippet in Terraform to create event grid subs for a processing function (TF doesn’t have a native way to get the function validation endpoint yet), and previously we had created an Azure DevOps task group that created and ran a bash script to query the management API. Unfortunately, every time you added a new endpoint to the processing function (for a new event type), you had to add this task group to the pipeline twice: Once for the TF plan and once for TF apply (we have a manual intervention step so you can review proposed changes and abort if you’ve done something stupid – saved us some pain a few times). Trouble was you had to do that for four environments and the pipeline for each getting cluttered. Now, using a small ARM snippet and the new (as of 0.12.6) resource for_each construct in Terraform, we’re able to add new endpoints by simply adding the function names to one variable and the event types to another (would have done it all in one but TF can’t cope with complex objects in the for_each as yet – might still find a way though). This way the pipelines don’t need editing to add a new endpoint and everything is controlled in the repo.
Hi Steve, Glad this blog helped! I’m by no means a expert with ARM but blogged this when the functions team first released the ability to update keys in ARM I figured I’d share my outcome since it wasn’t as straight forward as I hoped.
I have tested deploying azure function subscription with recent update but didn’t have any luck. My template is: –
{
“name”: “[concat(variables(‘eventGridTopicName’), ‘/Microsoft.EventGrid/’, variables(‘myFuncName’))]”,
“type”: “Microsoft.EventGrid/topics/providers/eventSubscriptions”,
“apiVersion”: “2019-01-01”,
“location”: “[parameters(‘location’)]”,
“properties”: {
“topic”: “[concat(‘/subscriptions/’, parameters(‘subscriptionId’),’/resourcegroups/’, parameters(‘resourceGroupName’), ‘/providers/Microsoft.EventGrid/topics/’, variables(‘eventGridTopicName’))]”,
“destination”: {
“endpointType”: “AzureFunction”,
“properties”: {
“resourceId”: “[resourceId(‘Microsoft.Web/sites/functions/’, variables(‘funcAppName’), variables(‘myFuncName’))]”,
“maxEventsPerBatch”: 1,
“preferredBatchSizeInKilobytes”: 64
}
},
“filter”: {
“advancedFilters”: [
{
“operatorType”: “StringIn”,
“key”: “eventType”,
“values”: [
“xyzEvent”
]
},
{
“operatorType”: “StringIn”,
“key”: “subject”,
“values”: [
“xyzEventReceived”
]
}
]
},
“labels”: [],
“eventDeliverySchema”: “EventGridSchema”
},
“dependsOn”: [
“[variables(‘eventGridTopicName’)]”
]
}
and I am getting this error: –
“error”: {
“code”: “InvalidRequest”,
“message”: “Invalid event subscription request: Supplied URL is invalid. It cannot be null or empty and should be a proper HTTPS URL like https://www.example.com.”
}
I believe you’re using the wrong API for the endPointType of Azure Functions. You need to use “apiVersion”: “2020-01-01-preview”.