1
votes

I have been working on a POC related to Azure Event Grid integration with Azure Function. I am stuck on the Event delivery Security as mentioned here.

I am using Event Grid Trigger which is sent by built-in Event grid Subscription in Azure Blob Storage. I have added an access token as a query parameter in WebHook endpoint as mentioned in the above URL.

But I cannot access that parameter in the Function code. Can someone share a sample for doing this?

FYI - Below is the function definition in my code.

[FunctionName("EventGridFunc")]
 public static void Run([EventGridTrigger]EventGridEvent eventGridEvent, 
 TraceWriter log)
 {
   log.Info("Received a trigger.");
   log.Info(eventGridEvent.Data.ToString());
 }
1

1 Answers

0
votes

The full subscriberUrl for EventGridTrigger function has the following format:

https://{FunctionAppName}.azurewebsites.net/admin/extensions/EventGridExtensionConfig?functionName={EventGridTriggerFunctionName}&code={masterKey}

As you can see, the EventGridTrigger is basically a special HttpTrigger (push) function with a "hidden pre-processing" of the event message for its validation.

Update:

I didn't see a way how to obtain a query string in the EventGridTrigger. However, there are few workarounds for your solution such as:

  • using an Application settings
  • using an Azure Key Vault for storing a secret
  • using a HttpTrigger instead of EventGridTrigger

The following code snippet shows an example of the HttpTrigger function for EventGrid (version 2018-05-01-preview) subscriber:

#r "Newtonsoft.Json"

using System.Net;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Linq;
using System.Threading.Tasks;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, IDictionary<string, string> query, TraceWriter log)
{
    log.Info("C# HTTP trigger function processed an EventGrid request.");

    log.Info($"\nHeaders:\n\t{string.Join("\n\t", req.Headers.Where(i => i.Key.StartsWith("aeg-")).Select(i => $"{i.Key}={i.Value.First()}"))}");
    log.Info($"\nQuery:\n\t{string.Join("\n\t", query.Select(i => $"{i.Key}={i.Value}"))}");

    string eventGridValidationHeader = req.Headers.FirstOrDefault( x => string.Compare(x.Key,"Aeg-Event-Type", true) == 0).Value?.FirstOrDefault().Trim();

    // media type = application/json or application/cloudevents+json 
    string jsontext = null;
    var jtoken = JToken.Parse(await req.Content.ReadAsStringAsync());
    log.Info($"\n{jtoken.ToString(Newtonsoft.Json.Formatting.Indented)}");

    if (jtoken is JArray)
        jsontext = jtoken.SingleOrDefault<JToken>().ToString();
    else if (jtoken is JObject)
        jsontext = jtoken.ToString();

    var eventGridEvent = JsonConvert.DeserializeAnonymousType(jsontext, new { EventType = "", Data = new JObject()});
    if (string.IsNullOrEmpty(eventGridValidationHeader) || string.IsNullOrEmpty(eventGridEvent?.EventType) || eventGridEvent?.Data == null)
    {
        return req.CreateErrorResponse(HttpStatusCode.BadRequest, "No EventGrid message.");
    }

    if (eventGridValidationHeader == "SubscriptionValidation" && eventGridEvent.EventType == "Microsoft.EventGrid.SubscriptionValidationEvent")
    {
        log.Verbose(@"Event Grid Validation event received.");
        return req.CreateResponse(HttpStatusCode.OK, JsonConvert.DeserializeObject(JsonConvert.SerializeObject(new { validationResponse = ((dynamic)eventGridEvent.Data).validationCode })));               
    }

    #region Event Processing 

    // for testing a retry delivery policy 
    //return req.CreateResponse(HttpStatusCode.BadRequest, "Testing");

    #endregion

    return req.CreateResponse(HttpStatusCode.NoContent);    
}