A simulator that provides endpoints to mimic the functionality of Azure Event Grid topics and subscribers and is compatible with the Microsoft.Azure.EventGrid
client library. NOTE: Currently only the EventGrid
event schema is supported. Support for the CloudEvent
schema may be added at a future date.
Topics and their subscribers are configured in the appsettings.json
file.
You can add multiple topics. Each topic must have a unique port. Each topic can have multiple subscribers. An example of one topic with one subscriber is shown below.
{
"topics": [
{
"name": "MyAwesomeTopic",
"port": 60101,
"key": "TheLocal+DevelopmentKey=",
"subscribers": [
{
"name": "LocalAzureFunctionSubscription",
"endpoint": "http://localhost:7071/runtime/webhooks/EventGrid?functionName=PersistEventToDb",
"disableValidation": true
}
]
}
]
}
name
: The name of the topic. It can only contain letters, numbers, and dashes.port
: The port to use for the topic endpoint. The topic will listen onhttps://0.0.0.0:{port}/
.key
: The key that will be used to validate theaeg-sas-key
oraeg-sas-token
header in each request. If this is not supplied then no key validation will take place.subscribers
: The subscriptions for this topic.
name
: The name of the subscriber. It can only contain letters, numbers, and dashes.endpoint
: The subscription endpoint url. Events received by topic will be sent to this address.disableValidation
:false
(the default) subscription validation will be attempted each time the simulator starts.true
to disable subscription validation.
dangerousAcceptAnyServerCertificateValidator
: Set totrue
to accept any server certificate. This is useful when testing with self signed certificates.
When a subscription is added to Azure Event Grid it first sends a validation event to the subscription endpoint. The validation event contains a validationCode
which the subscription endpoint must echo back. If this does not occur then Azure Event Grid will not enable the subscription.
More information about subscription validation can be found at https://docs.microsoft.com/en-us/azure/event-grid/webhook-event-delivery.
The Azure Event Grid Simualator will mimick this validation behaviour at start up but it can be disabled using the disableValidation
setting (above).
Event filtering is configurable on each subscriber using the filter model defined here: https://docs.microsoft.com/en-us/azure/event-grid/event-filtering. This page provides a full guide to the configuration options available and all parts of this guide are currently supported. For ease of transition, explicit limitations have also been adhered to. The restrictions mentioned have been further modified (https://azure.microsoft.com/en-us/updates/advanced-filtering-generally-available-in-event-grid/) and these new less restrictive filtering limits have been observed.
Extending the example above to include a basic filter which will only deliver events to the subscription if they are of a specific type is illustrated below.
{
"topics": [
{
"name": "MyAwesomeTopic",
"port": 60101,
"key": "TheLocal+DevelopmentKey=",
"subscribers": [
{
"name": "LocalAzureFunctionSubscription",
"endpoint": "http://localhost:7071/runtime/webhooks/EventGrid?functionName=PersistEventToDb",
"filter": {
"includedEventTypes": ["my.eventType"]
}
}
]
}
]
}
This can be extended to allow subject filtering:
"filter": {
"subjectBeginsWith": "/blobServices/default/containers/mycontainer/log",
"subjectEndsWith": ".jpg",
"isSubjectCaseSensitive": true
}
or advanced filtering:
"filter": {
"advancedFilters": [
{
"operatorType": "NumberGreaterThanOrEquals",
"key": "Data.Key1",
"value": 5
},
{
"operatorType": "StringContains",
"key": "Subject",
"values": ["container1", "container2"]
}
]
}
Note: you can also specify the configuration file to use by setting the ConfigFile
command line argument, e.g.
AzureEventGridSimulator.exe --ConfigFile=/path/to/config.json
There's a published image available on the ↗ Docker hub called pmcilreavy/azureeventgridsimulator:latest
.
The image is not configured with any topics or subscribers. The configuration can be passed in via command line environment variables (as below) or via a json file.
Here's an example of running a container based on that image and passing in the configuration via environment variables to create 1 topic with 2 subscribers.
In this example the folder C:\src\AzureEventGridSimulator\docker
on the host is being shared with the container. Note: see the notes section further below on how to create a certificate file.
docker run `
--detach `
--publish 60101:60101 `
-v C:\src\AzureEventGridSimulator\docker:/aegs `
-e ASPNETCORE_ENVIRONMENT=Development `
-e ASPNETCORE_Kestrel__Certificates__Default__Path=/aegs/azureEventGridSimulator.pfx `
-e ASPNETCORE_Kestrel__Certificates__Default__Password=Y0urSup3rCrypt1cPa55w0rd! `
-e TZ=Australia/Brisbane `
-e AEGS_Topics__0__name=ExampleTopic `
-e AEGS_Topics__0__port=60101 `
-e AEGS_Topics__0__key=TheLocal+DevelopmentKey= `
-e AEGS_Topics__0__subscribers__0__name=RequestCatcherSubscription `
-e AEGS_Topics__0__subscribers__0__endpoint=https://azureeventgridsimulator.requestcatcher.com/ `
-e AEGS_Topics__0__subscribers__0__disableValidation=true `
-e AEGS_Topics__0__subscribers__1__name=AzureFunctionSubscription `
-e AEGS_Topics__0__subscribers__1__endpoint=http://host.docker.internal:7071/runtime/webhooks/EventGrid?functionName=ExampleFunction `
-e AEGS_Topics__0__subscribers__1__disableValidation=true `
-e AEGS_Serilog__MinimumLevel__Default=Verbose `
pmcilreavy/azureeventgridsimulator:latest
There is a docker-compose.yml
file in the src folder that you can use (or modify) to build your own Docker image.
docker-compose up --build `
--force-recreate `
--remove-orphans `
--detach
Once configured and running, requests are posted
to a topic endpoint. The endpoint of a topic will be in the form: https://localhost:<configured-port>/api/events?api-version=2018-01-01
.
curl -k -H "Content-Type: application/json" -H "aeg-sas-key: TheLocal+DevelopmentKey=" -X POST "https://localhost:60101/api/events?api-version=2018-01-01" -d @Data.json
Data.json
[
{
"id": "8727823",
"subject": "/example/subject",
"data": {
"MyProperty": "This is my awesome data!"
},
"eventType": "Example.DataType",
"eventTime": "2019-01-01T00:00:00.000Z",
"dataVersion": "1"
}
]
An example request that you can import into Postman can be found in the AzureEventGridSimulator repo here https://github.com/pmcilreavy/AzureEventGridSimulator/blob/master/src/Azure%20Event%20Grid%20Simulator.postman_collection.json.
var client = new EventGridClient(new TopicCredentials("TheLocal+DevelopmentKey="));
await client.PublishEventsWithHttpMessagesAsync(
topicHostname: "localhost:60101",
events: new List<EventGridEvent> { <your event> });
Azure Event Grid only accepts connections over https and so the simulator only supports https too.
The simulator will attempt to use the dotnet development certificate to secure each topic port. You can ensure that this certificate is installed and trusted by running the following command.
dotnet dev-certs https --trust
You can also generate a certificate file (suitable for using with a Docker container) like so.
dotnet dev-certs https --export-path ./docker/azureEventGridSimulator.pfx --password Y0urSup3rCrypt1cPa55w0rd!
A topic can have 0 to n subscribers. When a request is received for a topic, the events will be forwarded to each of the subscribers with the addition of an aeg-event-type: Notification
header. If the message contains multiple events, they will be sent to each subscriber one at a time inline with the Azure Event Grid behaviour. "Event Grid sends the events to subscribers in an array that has a single event. This behavior may change in the future." https://docs.microsoft.com/en-us/azure/event-grid/event-schema
The simulator supports both: aeg-sas-key
or aeg-sas-token
request headers. Using aeg-sas-key
is the simplest way. Just set the value of the aeg-sas-key
to the same key
value configured for the topic. Using an aeg-sas-token
is more secure as the key
is hashed but it's a bit trickier to set up. More information on sas token
can be found here https://docs.microsoft.com/en-us/azure/event-grid/security-authentication#sas-tokens.
If the incoming request contains either an aeg-sas-token
or an aeg-sas-key
header and there is a Key
configured for the topic then the simulator will validate the key and reject the request if the value in the header is not valid.
If you want to skip the validation then set the Key
to null in appsettings.json
.
Azure Event Grid imposes certain size limits to the overall message body and to the each individual event. The overall message body must be <= 1Mb and each individual event must be <= 64Kb. These are the advertised size limits. My testing has shown that the actual limits are 1.5Mb and 65Kb.
Ensures that the properties of each event meets the minimum requirements.
Field | Description |
---|---|
Id | Must be a string. Not null or whitespace. |
Subject | Must be a string. Not null or whitespace. |
EventType | Must be a string. Not null or whitespace. |
EventTime | Must be a valid date/time. |
MetadataVersion | Must be null or 1 . |
Topic | Leave null or empty. Event Grid will populate this field. |
DataVersion | Optional. e.g. 1 . |
Data | Optional. Any custom object. |
There are a couple of similar projects out there. What I found though is that they don't adequately simulate an actual Event Grid Topic endpoint.
Azure Event Grid only excepts connections over https and the Microsoft.Azure.EventGrid
client only sends requests over https. If you're posting events to an Event Grid topic using custom code then maybe this isn't an issue. If you are using the client library though then any test endpoint must be https.
Typically an event grid topic endpoint url is like so: https://topic-name.location-name.eventgrid.azure.net/api/events. Note that all the information needed to post to a topic is contained in the host part. The Microsoft.Azure.EventGrid
client will essentially reduce the url you give it down to just the host part and prefix it with https (regardless of the original scheme).
It posts the payload to https://host:port and drops the query uri. All of the existing simulator/ emulator projects I found don't support https and use a the query uri to distinguish between the topics. This isn't compatible with the Microsoft.Azure.EventGrid
client.
Some features that could be added if there was a need for them: -
CloudEvent
schema support.- Subscriber retries & dead lettering. https://docs.microsoft.com/en-us/azure/event-grid/delivery-and-retry
- Certificate configuration in
appsettings.json
. - Subscriber token auth
- Better Docker support.
- Maybe a web based console for admin stats etc.