Last weeks I was developing an Azure Function with an Event Grid Trigger using the new V2 Runtime (in .Net Core) and because the changes from V1 some things where not working anymore as expected.
In this post I will show you how to create an Event Grid subscription to an Azure Function with an Event Grid Trigger in the V2 Runtime.
Nuget
One of the changes in the V2 runtime is that now the functions bindings (HTTP, Storage Queue, Timer, Event Grid etc..) are now provided in separate Nuget packages, called “binding extensions”.
For an Event Grid Trigger we need the Microsoft.Azure.WebJobs.Extensions.EventGrid Nuget package (at least version 2.0.0 or higher). If you create an Azure Function with an Event Grid trigger from the Portal the UI will alert you that you need this extension and it will be installed for you behind the scenes.
It’s important to install the package because it has to be present in the bin directory of the function app otherwise the following steps will not work.
If you are using a precompiled C# function after installing the Nuget package you have to publish the Function in Azure.
SystemKey
To create an Event Grid Subscription to the function we need a SystemKey, the endpoints to get this keys are changed in V2, unfortunately at the moment of writing the documentation has not been updated. I have created an issue for this and Microsoft is working to update the docs.
The right endpoint to get the SystemKey is:
http://{functionappname}.azurewebsites.net/admin/host/systemkeys/eventgrid_extension?code={masterkey}
Where the MasterKey is the “_master” key of your function app.
App Setting
Before we can do the call to get the SystemKey we need to set/add the AzureWebJobsSecretStorageType
app setting to ‘files‘, because this issue due to changes in the Azure Function V2 Runtime.
Deployment
After all the previous steps are done we can now generate the SystemKey and use it to create an Event Grid Subscription to the function endpoint.
I have created a Gist with a PowerShell script to do all the work needed:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
#.SYNOPSIS | |
# Creates Event Grid Subscription. | |
#.DESCRIPTION | |
# Creates an Event Grid Subscription (Topic type: Azure Subscription) to a Function App V2 | |
#.OUTPUTS | |
# Progress messages | |
# | |
Param( | |
[string]$ResourceGroupName, | |
[string]$FunctionAppName, | |
[string]$FunctionName, | |
[string]$EventGridSubscriptionName, | |
[string]$FunctionUrl="azurewebsites.net" | |
) | |
Function Get-AppServicePublishingCredentials($resourceGroupName, $functionAppName) | |
{ | |
$resourceType = "Microsoft.Web/sites/config" | |
$resourceName = "$functionAppName/publishingcredentials" | |
$publishingCredentials = Invoke-AzureRmResourceAction –ResourceGroupName $resourceGroupName –ResourceType $resourceType –ResourceName $resourceName –Action list –ApiVersion 2015–08–01 –Force | |
return $publishingCredentials | |
} | |
function Get-EncodedCredentials($resourceGroupName, $functionAppName) | |
{ | |
$publishingCredentials = Get-AppServicePublishingCredentials $resourceGroupName $functionAppName | |
$pair = "$($publishingCredentials.Properties.PublishingUserName):$($publishingCredentials.Properties.PublishingPassword)" | |
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair)) | |
return $encodedCreds | |
} | |
function Get-MasterAPIKey($encodedCreds, $functionAppName) | |
{ | |
$result = Invoke-RestMethod –Uri "https://$functionAppName.scm.$FunctionUrl/api/functions/admin/masterkey" –Headers @{Authorization=("Basic {0}" -f $encodedCreds)} | |
return $result.masterKey | |
} | |
function Get-EventGridExtensionSystemKey($functionAppName, $masterKey) | |
{ | |
$result = Invoke-RestMethod ("https://$functionAppName.$FunctionUrl/admin/host/systemkeys/eventgrid_extension?code=" + $masterKey) | |
return $result.value | |
} | |
function Create-EventGridSubscription($functionAppName, $functionName, $systemKey, $eventGridSubscriptionName) | |
{ | |
$functionEndpointURL = "https://" + $functionAppName + ".$FunctionUrl/runtime/webhooks/eventgrid?functionName=" + $functionName + "&code=" + $systemkey +"" | |
$subscriptionID=(Get-AzureRmContext).Subscription.Id | |
New-AzureRmDeployment ` | |
–Name egdeployment ` | |
–Location westeurope ` | |
–TemplateUri https://raw.githubusercontent.com/Azure/azure–quickstart–templates/master/101–event–grid–resource–events–to–webhook/azuredeploy.json ` | |
–eventSubName $eventGridSubscriptionName ` | |
–endpoint $functionEndpointURL | |
} | |
# Get the Encoded Publish Credentials, so we can call Kudu API to get master key | |
$encodedCreds = Get-EncodedCredentials $ResourceGroupName $FunctionAppName | |
Write-Output "This is the encodedCreds: $encodedCreds" | |
# Get master key to call Event Grid Extension API | |
$masterKey = Get-MasterAPIKey $encodedCreds $FunctionAppName | |
Write-Output "This is the masterKey: $masterkey" | |
# Get Event Grid SystemKey, so we can create the Event Grid Webhook | |
$systemKey = Get-EventGridExtensionSystemKey $FunctionAppName $masterkey | |
Write-Output "This is the SystemKey: $systemKey" | |
Write-Output "Creating the Event Grid Subscription:" | |
Create–EventGridSubscription $FunctionAppName $FunctionName $systemKey $EventGridSubscriptionName |
In the PowerShell script I use an ARM Template (from the Azure Quickstart Gallery) to create the Event Grid Subscription at Azure Subscription level (sorry for the confusing subscription words).
If you want to create the Event Grid Subscription at Resource Group level use the New-AzureRmResourceGroupDeployment cmdlet instead (at line 49), providing the Resource Group name you want to link.
Hey Marco,
I believe that the end point in Get-EventGridExtensionSystemKey should be “http” and not “https” – you can also remove the access token parameter from that function since it is also not used.
Hope this helps!
LikeLike
I doubt about https, but I will remove the token, it’s indeed not used in the function
LikeLike
Hello Macro,
Thank you for this…I am having issues replicating what you have done here and was wondering if you can help out.
I first had issues with the parameters and then had to hard code the masterkey and systemkey. Despite doing this I got the following error message.
################################################################################
the deployment ‘egdeployment’ failed with error(s). Showing 1 out of 1 error(s). Status Message: The resource operation completed with
| terminal provisioning state ‘Failed’. (Code: ResourceDeploymentFailure) – Webhook validation handshake failed for
| https://azltrialfuncapp.alipfunctionapp.azurewebsites.net/runtime/webhooks/EventGrid. Http POST request failed with response code Unknown. For
| troublehooting, visit https://aka.ms/esvalidation. Activity id:07cbd4ac-324d-4656-a239-77aac33e51f2, timestamp: 6/12/2020 4:25:26 PM (UTC). (Code:Url
| validation) CorrelationId: 27ee89bf-526a-4116-b8ce-c4cbc44574d7
#################################################################################
Please any idea what I might be doing wrong
LikeLike
Hello Michael,
is the webhook you are trying to reach behind a firewall? Is it accessible from the internet?
LikeLike