├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── Bug_report.md │ ├── Event_Schema_Request.md │ ├── Feature_request.md │ ├── Support.md │ └── config.yml └── workflows │ ├── code-coverage.yml │ └── codeql-analysis.yml ├── .gitignore ├── LICENSE ├── README.md ├── build ├── ci-build.yml ├── nuget-release.yml └── variables │ └── build.yml ├── deploy └── arm │ └── testing-infrastructure │ ├── azuredeploy.json │ └── azuredeploy.parameters.json ├── docs ├── README.md ├── babel.config.js ├── docusaurus.build.config.js ├── docusaurus.config.js ├── package-lock.json ├── package.json ├── preview │ ├── 01-index.md │ └── 02-Features │ │ ├── create-custom-events.md │ │ ├── deserializing-events.md │ │ ├── endpoint-validation.md │ │ ├── publishing-events.md │ │ └── running-integration-tests.md ├── sidebars.js ├── src │ ├── css │ │ └── custom.css │ ├── pages │ │ └── index.module.css │ └── prism │ │ ├── dark.js │ │ └── light.js ├── static │ ├── img │ │ ├── arcus.jpg │ │ ├── arcus.png │ │ ├── arcus_for_dark.png │ │ ├── favicon.ico │ │ └── icon.png │ └── media │ │ ├── event-grid-delivery-properties.png │ │ ├── event-grid-traceparent-delivery-properties.png │ │ ├── integration-testing-infrastructure.png │ │ ├── logos │ │ └── armviz.png │ │ └── schematics │ │ └── schematics.drawio ├── versioned_docs │ ├── version-v1.0.0 │ │ ├── 01-index.md │ │ └── 02-Features │ │ │ ├── azure-event-contracts.md │ │ │ ├── endpoint-validation.md │ │ │ └── publishing-events.md │ ├── version-v1.0.1 │ │ ├── 01-index.md │ │ └── 02-Features │ │ │ ├── azure-event-contracts.md │ │ │ ├── endpoint-validation.md │ │ │ └── publishing-events.md │ ├── version-v1.0.2 │ │ ├── 01-index.md │ │ └── 02-Features │ │ │ ├── azure-event-contracts.md │ │ │ ├── endpoint-validation.md │ │ │ └── publishing-events.md │ ├── version-v1.1.0 │ │ ├── 01-index.md │ │ └── 02-Features │ │ │ ├── azure-event-contracts.md │ │ │ ├── endpoint-validation.md │ │ │ └── publishing-events.md │ ├── version-v2.0.0 │ │ ├── 01-index.md │ │ └── 02-Features │ │ │ ├── azure-event-contracts.md │ │ │ ├── deserializing-events.md │ │ │ ├── endpoint-validation.md │ │ │ └── publishing-events.md │ ├── version-v2.1.0 │ │ ├── 01-index.md │ │ └── 02-Features │ │ │ ├── azure-event-contracts.md │ │ │ ├── deserializing-events.md │ │ │ ├── endpoint-validation.md │ │ │ ├── publishing-events.md │ │ │ └── running-integration-tests.md │ ├── version-v2.2.0 │ │ ├── 01-index.md │ │ └── 02-Features │ │ │ ├── azure-event-contracts.md │ │ │ ├── deserializing-events.md │ │ │ ├── endpoint-validation.md │ │ │ ├── publishing-events.md │ │ │ └── running-integration-tests.md │ ├── version-v2.3.0 │ │ ├── 01-index.md │ │ └── 02-Features │ │ │ ├── azure-event-contracts.md │ │ │ ├── deserializing-events.md │ │ │ ├── endpoint-validation.md │ │ │ ├── publishing-events.md │ │ │ └── running-integration-tests.md │ ├── version-v2.4.0 │ │ ├── 01-index.md │ │ └── 02-Features │ │ │ ├── azure-event-contracts.md │ │ │ ├── deserializing-events.md │ │ │ ├── endpoint-validation.md │ │ │ ├── publishing-events.md │ │ │ └── running-integration-tests.md │ ├── version-v3.0.0 │ │ ├── 01-index.md │ │ └── 02-Features │ │ │ ├── create-custom-events.md │ │ │ ├── deserializing-events.md │ │ │ ├── endpoint-validation.md │ │ │ ├── publishing-events.md │ │ │ └── running-integration-tests.md │ ├── version-v3.2.0 │ │ ├── 01-index.md │ │ └── 02-Features │ │ │ ├── create-custom-events.md │ │ │ ├── deserializing-events.md │ │ │ ├── endpoint-validation.md │ │ │ ├── publishing-events.md │ │ │ └── running-integration-tests.md │ └── version-v3.3.0 │ │ ├── 01-index.md │ │ └── 02-Features │ │ ├── create-custom-events.md │ │ ├── deserializing-events.md │ │ ├── endpoint-validation.md │ │ ├── publishing-events.md │ │ └── running-integration-tests.md ├── versioned_sidebars │ ├── version-v1.0.0-sidebars.json │ ├── version-v1.0.1-sidebars.json │ ├── version-v1.0.2-sidebars.json │ ├── version-v1.1.0-sidebars.json │ ├── version-v2.0.0-sidebars.json │ ├── version-v2.1.0-sidebars.json │ ├── version-v2.2.0-sidebars.json │ ├── version-v2.3.0-sidebars.json │ ├── version-v2.4.0-sidebars.json │ ├── version-v3.0.0-sidebars.json │ ├── version-v3.2.0-sidebars.json │ └── version-v3.3.0-sidebars.json └── versions.json ├── media ├── fonts │ ├── Exo2-Black.ttf │ ├── Exo2-BlackItalic.ttf │ ├── Exo2-Bold.ttf │ ├── Exo2-BoldItalic.ttf │ ├── Exo2-ExtraBold.ttf │ ├── Exo2-ExtraBoldItalic.ttf │ ├── Exo2-ExtraLight.ttf │ ├── Exo2-ExtraLightItalic.ttf │ ├── Exo2-Italic.ttf │ ├── Exo2-Light.ttf │ ├── Exo2-LightItalic.ttf │ ├── Exo2-Medium.ttf │ ├── Exo2-MediumItalic.ttf │ ├── Exo2-Regular.ttf │ ├── Exo2-SemiBold.ttf │ ├── Exo2-SemiBoldItalic.ttf │ ├── Exo2-Thin.ttf │ └── Exo2-ThinItalic.ttf └── logo │ ├── arcus-logo.png │ └── arcus-logo.pub ├── netlify.toml └── src ├── Arcus.EventGrid.Core ├── Arcus.EventGrid.Core.csproj ├── EventCorrelationFormat.cs └── Publishing │ ├── EventGridPublisherClientWithTracking.cs │ ├── EventGridPublisherClientWithTrackingOptions.cs │ └── Extensions │ └── AzureClientFactoryBuilderExtensions.cs ├── Arcus.EventGrid.Security.AzureFunctions ├── Arcus.EventGrid.Security.AzureFunctions.csproj └── Extensions │ └── IFunctionsHostBuilderExtensions.cs ├── Arcus.EventGrid.Security.Core ├── Arcus.EventGrid.Security.Core.csproj ├── Extensions │ └── IServiceCollectionExtensions.cs └── Validation │ ├── EventGridSubscriptionValidator.cs │ └── IEventGridSubscriptionValidator.cs ├── Arcus.EventGrid.Security.WebApi ├── Arcus.EventGrid.Security.WebApi.csproj ├── EventGridAuthorizationAttribute.cs ├── EventGridAuthorizationFilter.cs ├── EventGridAuthorizationOptions.cs ├── EventGridSubscriptionValidationActionFilter.cs ├── EventGridSubscriptionValidationAttribute.cs ├── Extensions │ └── FilterCollectionExtensions.cs └── HttpRequestProperty.cs ├── Arcus.EventGrid.Security ├── Arcus.EventGrid.Security.csproj ├── Arcus.EventGrid.snk ├── Attributes │ ├── DynamicEventGridAuthorizationAttribute.cs │ └── EventGridAuthorizationAttribute.cs ├── EventGridSubscriptionValidator.cs └── ResultWithChallenge.cs ├── Arcus.EventGrid.Testing ├── Arcus.EventGrid.Testing.csproj ├── Infrastructure │ └── Hosts │ │ ├── EventConsumerHost.cs │ │ └── ServiceBus │ │ ├── ServiceBusEventConsumerHost.cs │ │ ├── ServiceBusEventConsumerHostOptions.cs │ │ └── SubscriptionBehavior.cs └── Logging │ └── ConsoleLogger.cs ├── Arcus.EventGrid.Tests.Core ├── Arcus.EventGrid.Tests.Core.csproj ├── ArcusAssert.cs └── Events │ ├── Data │ └── CarEventData.cs │ └── EventSchema.cs ├── Arcus.EventGrid.Tests.InMemoryApi ├── Arcus.EventGrid.Tests.InMemoryApi.csproj ├── Controllers │ ├── AuthorizationController.cs │ └── WebhookController.cs └── InMemoryTestApiStartup.cs ├── Arcus.EventGrid.Tests.Integration ├── Arcus.EventGrid.Tests.Integration.csproj ├── Fixture │ ├── EventGridTopicEndpoint.cs │ ├── MockServiceBusEventConsumerHost.cs │ ├── MockServiceBusEventConsumerHostOptions.cs │ ├── TemporaryManagedIdentityConnection.cs │ └── TestConfig.cs ├── Publishing │ ├── EventGridPublisherClientWithTrackingCloudEventsTests.cs │ ├── EventGridPublisherClientWithTrackingEventGridEventTests.cs │ ├── EventGridPublisherClientWithTrackingResilienceTests.cs │ ├── EventGridPublisherClientWithTrackingTests.cs │ └── Fixture │ │ ├── CustomEventGridPublisherClientWithTracking.cs │ │ ├── EndpointCallCount.cs │ │ ├── EventOptionsFixture.cs │ │ └── SabotageMockTopicEndpoint.cs ├── TestCollections.cs ├── WebApi │ ├── Fixture │ │ ├── HealthController.cs │ │ ├── HttpRequestBuilder.cs │ │ ├── TestApiServer.cs │ │ └── TestApiServerOptions.cs │ └── Security │ │ ├── Controllers │ │ ├── EventGridAuthorizationController.cs │ │ └── EventGridSubscriptionValidationController.cs │ │ ├── EventGridAuthorizationAttributeTests.cs │ │ ├── EventGridAuthorizationFilterTests.cs │ │ └── EventGridSubscriptionValidationAttributeTests.cs └── appsettings.json ├── Arcus.EventGrid.Tests.Unit ├── App.config ├── Arcus.EventGrid.Tests.Unit.csproj ├── Artifacts │ ├── EventSamples.Designer.cs │ └── EventSamples.resx ├── Blanks.cs ├── Publishing │ ├── AzureClientFactoryBuilderExtensionsTests.cs │ ├── EventGridPublisherClientWithTrackingOptionsTests.cs │ ├── EventGridPublisherWithTrackingTests.cs │ └── Fixtures │ │ ├── InMemoryEventGridPublisherClient.cs │ │ └── StubEventGridPublisherClientWithTracking.cs ├── Security │ ├── EventGridAuthorizationAttributeTests.cs │ ├── EventGridAuthorizationFilterTests.cs │ ├── EventGridSubscriptionValidationActionFilterTests.cs │ ├── EventGridSubscriptionValidatorTests.cs │ ├── Extensions │ │ ├── FilterCollectionExtensionsTests.cs │ │ └── IServiceCollectionExtensionsTests.cs │ └── Fixture │ │ └── StubFunctionsHostBuilder.cs ├── TestCollections.cs ├── Testing │ ├── EventConsumerHostTests.cs │ ├── Fixture │ │ └── InMemoryEventConsumerHost.cs │ ├── ServiceBusEventConsumerHostOptionsTests.cs │ └── ServiceBusEventConsumerHostTests.cs └── xunit.runner.json ├── Arcus.EventGrid.sln └── Arcus.EventGrid.sln.DotSettings /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # These owners will be the default owners for everything in the repo. 2 | * @stijnmoreels @fgheysels 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 13 | **Expected behavior** 14 | A clear and concise description of what you expected to happen. 15 | 16 | **Additional context** 17 | Add any other context about the problem here. 18 | - Version 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Event_Schema_Request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Request an event schema 3 | about: Request support for a new event schema (version) 4 | 5 | --- 6 | 7 | **Name of the requested event** 8 | 9 | `Arcus.Demo.CarRegistered` 10 | 11 | **Requested data version(s)** 12 | Requested data version(s) for the event 13 | 14 | **Sample Payload** 15 | ```json 16 | [{ 17 | "topic": "/car-lot", 18 | "subject": "/cars/", 19 | "eventType": "Arcus.Demo.CarRegistered", 20 | "eventTime": "2017-06-26T18:41:00.9584103Z", 21 | "id": "831e1650-001e-001b-66ab-eeb76e069631", 22 | "data": { 23 | "licensePlate": "1-TOM-1337" 24 | }, 25 | "dataVersion": "1", 26 | "metadataVersion": "1" 27 | }] 28 | ``` 29 | 30 | **Link to official schema** 31 | https://docs.microsoft.com/en-us/azure/event-grid/event-schema-blob-storage 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | --- 5 | 6 | **Is your feature request related to a problem? Please describe.** 7 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 8 | 9 | **Describe the solution you'd like** 10 | A clear and concise description of what you want to happen. 11 | 12 | **Describe alternatives you've considered** 13 | A clear and concise description of any alternative solutions or features you've considered. 14 | 15 | **Additional context** 16 | Add any other context or screenshots about the feature 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Support.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "Support Question" 3 | about: "I have a question" 4 | 5 | --- 6 | 7 | **Description** 8 | *Give more information about your doubt* 9 | 10 | * Check our [Wiki](https://github.com/arcus-azure/arcus.eventgrid/wiki) 11 | * Check out our general [Arcus](https://github.com/arcus-azure/arcus) repo for non-Event Grid questions 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Ask a question 💬 4 | url: https://github.com/arcus-azure/arcus.eventgrid/discussions/new 5 | about: Ask a question or request support for using Arcus Event Grid. 6 | -------------------------------------------------------------------------------- /.github/workflows/code-coverage.yml: -------------------------------------------------------------------------------- 1 | name: "Code Coverage" 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | # The branches below must be a subset of the branches above 8 | branches: [ main ] 9 | 10 | jobs: 11 | analyze: 12 | name: Analyze 13 | runs-on: ubuntu-latest 14 | permissions: 15 | actions: read 16 | contents: read 17 | 18 | strategy: 19 | fail-fast: false 20 | matrix: 21 | language: [ 'csharp' ] 22 | 23 | steps: 24 | - name: Checkout repository 25 | uses: actions/checkout@v2 26 | - uses: actions/setup-dotnet@v3 27 | with: 28 | dotnet-version: '8.0.x' 29 | dotnet-quality: 'preview' 30 | 31 | - name: Coverlet coverage unit test 32 | run: dotnet test -c Debug -p:coverletOutput=coverage.xml -p:CollectCoverage=true -p:CoverletOutputFormat=opencover -p:Threshold=80 -p:ThresholdStat=Total -p:ExcludeByAttribute=\"Obsolete,GeneratedCodeAttribute,CompilerGeneratedAttribute\" -p:Exclude=\"[Arcus.EventGrid.Tests.*]*\" src/Arcus.EventGrid.Tests.Unit/Arcus.EventGrid.Tests.Unit.csproj 33 | 34 | - name: Codecov 35 | uses: codecov/codecov-action@v3.1.1 36 | if: always() 37 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ main ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main ] 20 | schedule: 21 | - cron: '35 16 * * 4' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'csharp' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://git.io/codeql-language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v2 42 | - uses: actions/setup-dotnet@v3 43 | with: 44 | dotnet-version: '8.0.x' 45 | dotnet-quality: 'preview' 46 | 47 | # Initializes the CodeQL tools for scanning. 48 | - name: Initialize CodeQL 49 | uses: github/codeql-action/init@v2 50 | with: 51 | languages: ${{ matrix.language }} 52 | # If you wish to specify custom queries, you can do so here or in a config file. 53 | # By default, queries listed here will override any specified in a config file. 54 | # Prefix the list here with "+" to use these queries and those in the config file. 55 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 56 | 57 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 58 | # If this step fails, then you should remove it and run the build manually (see below) 59 | - name: Autobuild 60 | uses: github/codeql-action/autobuild@v2 61 | 62 | # ℹ️ Command-line programs to run using the OS shell. 63 | # 📚 https://git.io/JvXDl 64 | 65 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 66 | # and modify them (or add more) to build your code if your project 67 | # uses a compiled language 68 | 69 | #- run: | 70 | # make bootstrap 71 | # make release 72 | 73 | - name: Perform CodeQL Analysis 74 | uses: github/codeql-action/analyze@v2 75 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Arcus 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Arcus - Azure Event Grid 2 | [![Build Status](https://dev.azure.com/codit/Arcus/_apis/build/status/Commit%20builds/CI%20-%20Arcus.EventGrid?branchName=main)](https://dev.azure.com/codit/Arcus/_build/latest?definitionId=734&branchName=main) 3 | [![NuGet Badge](https://buildstats.info/nuget/Arcus.EventGrid?includePreReleases=true)](https://www.nuget.org/packages/Arcus.EventGrid/) 4 | [![codecov](https://codecov.io/gh/arcus-azure/arcus.eventgrid/branch/main/graph/badge.svg?token=32MTRK2HFN)](https://codecov.io/gh/arcus-azure/arcus.eventgrid) 5 | 6 | Azure Event Grid development in a breeze. 7 | 8 | ![Arcus](https://raw.githubusercontent.com/arcus-azure/arcus/master/media/arcus.png) 9 | 10 | # Documentation 11 | All documentation can be found on [here](https://eventgrid.arcus-azure.net/). 12 | 13 | # Customers 14 | Are you an Arcus user? Let us know and [get listed](https://bit.ly/become-a-listed-arcus-user)! 15 | 16 | # How do I run the integration tests? 17 | In order to run the integration tests, you will need to do the following: 18 | 1. Setup the infrastructure ([docs](https://eventgrid.arcus-azure.net/features/running-integration-tests#azure-infrastructure)) 19 | 20 | 2. Configure the following environment variables: 21 | - `Arcus__EventGrid__TopicEndpoint` _- Custom topic endpoint for Azure Event Grid, for example `https://arcus.westeurope-1.eventgrid.azure.net/api/events`_ 22 | - `Arcus__EventGrid__EndpointKey` _- Authentication key for the custom Azure Event Grid topic_ 23 | - `Arcus__ServiceBus__ConnectionString` _- Connection string to use when connecting to Azure Service Bus`_ 24 | - `Arcus__ServiceBus__TopicName` _- Name of the Service Bus Topic that you want to use_ 25 | 26 | Once you have completed the above, you can run `dotnet test` from the `src\Arcus.EventGrid.Tests.Integration` directory. 27 | 28 | --------- 29 | 30 | :pencil: _**Notes**_ 31 | 32 | - _If you are using Visual Studio, you must restart Visual Studio in order to use new Environment Variables._ 33 | - _`src\Arcus.EventGrid.Tests.Integration\appsettings.json` can also be overriden but it brings the risk of commiting these changes. **This approach is not recommended.** This is also why we don't use `appsettings.{Environment}.json`_ 34 | 35 | --------- 36 | 37 | # License Information 38 | This is licensed under The MIT License (MIT). Which means that you can use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the web application. But you always need to state that Codit is the original author of this web application. 39 | -------------------------------------------------------------------------------- /build/variables/build.yml: -------------------------------------------------------------------------------- 1 | variables: 2 | DotNet.Sdk.Version: '8.0.x' 3 | DotNet.Sdk.VersionBC: '6.0.100' 4 | Project: 'Arcus.EventGrid' 5 | Vm.Image: 'ubuntu-latest' -------------------------------------------------------------------------------- /deploy/arm/testing-infrastructure/azuredeploy.parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "EventGrid.Topic.Name": { 6 | "value": "arcus-testing-event-topic" 7 | }, 8 | "EventGrid.Subscription.Name": { 9 | "value": "arcus-testing-runtime" 10 | }, 11 | "ServiceBus.Topic.Name": { 12 | "value": "received-events" 13 | }, 14 | "ServiceBus.Namespace.Name": { 15 | "value": "arcus-testing-infrastructure" 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator. 4 | 5 | ## Prerequisites 6 | This documentation assumes that you run all scripts within the docs folder. 7 | 8 | ```console 9 | cd docs 10 | ``` 11 | 12 | 13 | ## Installation 14 | 15 | 16 | ```console 17 | npm install 18 | ``` 19 | 20 | ## Local Development 21 | 22 | ```console 23 | npm start 24 | ``` 25 | 26 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. 27 | 28 | ## Versioning 29 | https://docusaurus.io/docs/versioning 30 | 31 | You can use the version script to create a new documentation version based on the latest content in the `./preview` directory. That specific set of documentation will then be preserved and accessible even as the documentation in the docs directory changes moving forward. 32 | 33 | ### Tagging a new version 34 | 35 | 1. First, make sure your content in the `./preview` directory is ready to be frozen as a version. A version always should be based from master. 36 | 2. Enter a new version number: 37 | 38 | `npm run docusaurus docs:version v1.1.0` 39 | 40 | --- 41 | When tagging a new version, the document versioning mechanism will: 42 | 43 | - Copy the full `./preview` folder contents into a new `versioned_docs/version-/` folder. 44 | - Create a versioned sidebars file based from your current sidebar configuration (if it exists) - saved as `versioned_sidebars/version--sidebars.json`. 45 | - Append the new version number to `versions.json`. 46 | 47 | 48 | ## Syntax highlighting 49 | 50 | To have syntax highlighting within the codeblocks you have to use one of the prism supported languages: 51 | 52 | https://github.com/FormidableLabs/prism-react-renderer/blob/master/src/vendor/prism/includeLangs.js 53 | ## Deploying to Netlify 54 | 55 | https://docusaurus.io/docs/deployment#deploying-to-netlify 56 | -------------------------------------------------------------------------------- /docs/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/docusaurus.build.config.js: -------------------------------------------------------------------------------- 1 | const buildConfig = require('./docusaurus.config'); 2 | 3 | module.exports = { 4 | ...buildConfig, 5 | themeConfig: { 6 | ...buildConfig.themeConfig, 7 | algolia: { 8 | appId: process.env.ALGOLIA_APP_ID, 9 | apiKey: process.env.ALGOLIA_API_KEY, 10 | indexName: 'arcus-azure', 11 | // Set `contextualSearch` to `true` when having multiple versions!!! 12 | contextualSearch: true, 13 | searchParameters: { 14 | facetFilters: ["tags:eventgrid"] 15 | }, 16 | }, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /docs/docusaurus.config.js: -------------------------------------------------------------------------------- 1 | const lightCodeTheme = require('./src/prism/light'); 2 | const darkCodeTheme = require('./src/prism/dark'); 3 | 4 | /** @type {import('@docusaurus/types').DocusaurusConfig} */ 5 | module.exports = { 6 | title: 'Arcus - Azure Event Grid', 7 | url: 'https://eventgrid.arcus-azure.net', 8 | baseUrl: '/', 9 | onBrokenLinks: 'throw', 10 | onBrokenMarkdownLinks: 'warn', 11 | favicon: 'img/favicon.ico', 12 | organizationName: 'arcus-azure', // Usually your GitHub org/user name. 13 | projectName: 'Arcus - Azure Event Grid', // Usually your repo name. 14 | themeConfig: { 15 | image: 'img/arcus.jpg', 16 | navbar: { 17 | title: 'Azure Event Grid', 18 | logo: { 19 | alt: 'Arcus', 20 | src: 'img/arcus.png', 21 | srcDark: 'img/arcus_for_dark.png', 22 | }, 23 | items: [ 24 | { 25 | type: 'docsVersionDropdown', 26 | 27 | //// Optional 28 | position: 'right', 29 | // Add additional dropdown items at the beginning/end of the dropdown. 30 | dropdownItemsBefore: [], 31 | // Do not add the link active class when browsing docs. 32 | dropdownActiveClassDisabled: true, 33 | docsPluginId: 'default', 34 | }, 35 | { 36 | type: 'search', 37 | position: 'right', 38 | }, 39 | { 40 | href: 'https://github.com/arcus-azure/arcus.eventgrid', 41 | label: 'GitHub', 42 | position: 'right', 43 | }, 44 | ], 45 | }, 46 | footer: { 47 | style: 'dark', 48 | links: [ 49 | { 50 | title: 'Community', 51 | items: [ 52 | { 53 | label: 'Arcus Azure Github', 54 | href: 'https://github.com/arcus-azure', 55 | }, 56 | ], 57 | }, 58 | ], 59 | copyright: `Copyright © ${new Date().getFullYear()}, Arcus - Azure Event Grid maintained by arcus-azure`, 60 | }, 61 | prism: { 62 | theme: lightCodeTheme, 63 | darkTheme: darkCodeTheme, 64 | additionalLanguages: ['csharp'], 65 | }, 66 | }, 67 | presets: [ 68 | [ 69 | '@docusaurus/preset-classic', 70 | { 71 | docs: { 72 | sidebarPath: require.resolve('./sidebars.js'), 73 | routeBasePath: "/", 74 | path: 'preview', 75 | sidebarCollapsible: false, 76 | // Please change this to your repo. 77 | editUrl: 78 | 'https://github.com/arcus-azure/arcus.eventgrid/edit/master/docs', 79 | includeCurrentVersion:process.env.CONTEXT !== 'production', 80 | }, 81 | theme: { 82 | customCss: require.resolve('./src/css/custom.css'), 83 | }, 84 | }, 85 | ], 86 | ], 87 | stylesheets: [ 88 | 'https://fonts.googleapis.com/css2?family=Bitter:wght@700&family=Inter:wght@400;500&display=swap', 89 | ], 90 | }; 91 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "arcus.eventgrid", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build --config ./docusaurus.build.config.js" , 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "clear": "docusaurus clear", 12 | "serve": "docusaurus serve", 13 | "write-translations": "docusaurus write-translations", 14 | "write-heading-ids": "docusaurus write-heading-ids" 15 | }, 16 | "dependencies": { 17 | "@docusaurus/core": "^2.0.0-beta.6", 18 | "@docusaurus/preset-classic": "^2.0.0-beta.6", 19 | "@docusaurus/theme-search-algolia": "^2.0.0-beta.6", 20 | "@mdx-js/react": "^1.6.21", 21 | "@svgr/webpack": "^5.5.0", 22 | "clsx": "^1.1.1", 23 | "file-loader": "^6.2.0", 24 | "prism-react-renderer": "^1.2.1", 25 | "react": "^17.0.1", 26 | "react-dom": "^17.0.1", 27 | "url-loader": "^4.1.1" 28 | }, 29 | "browserslist": { 30 | "production": [ 31 | ">0.5%", 32 | "not dead", 33 | "not op_mini all" 34 | ], 35 | "development": [ 36 | "last 1 chrome version", 37 | "last 1 firefox version", 38 | "last 1 safari version" 39 | ] 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /docs/preview/01-index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Arcus Event Grid" 3 | layout: default 4 | slug: / 5 | sidebar_label: Welcome 6 | --- 7 | 8 | # Introduction 9 | 10 | Arcus EventGrid builds on top of Microsoft technology to provide the user with transient publishing and safely registering event publishing to your application with the [Arcus secret store](https://security.arcus-azure.net/features/secret-store). EventGrid is often used in integration tests, so we made sure that retrieving events is easy, transient, and customizable. 11 | 12 | # Installation 13 | 14 | ```shell 15 | PM > Install-Package Arcus.EventGrid.Core 16 | ``` 17 | 18 | # License 19 | This is licensed under The MIT License (MIT). Which means that you can use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the web application. But you always need to state that Codit is the original author of this web application. 20 | 21 | *[Full license here](https://github.com/arcus-azure/arcus.eventgrid/blob/master/LICENSE)* 22 | -------------------------------------------------------------------------------- /docs/preview/02-Features/create-custom-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Create custom events" 3 | layout: default 4 | --- 5 | 6 | ## Create Custom Events 7 | 8 | > ❌ The `Arcus.EventGrid` package is deprecated and will be removed in v4. 9 | 10 | Starting from v3.3, we use fully the Azure SDK to send events to Azure Event Grid. See [their documentation](https://learn.microsoft.com/en-us/dotnet/api/overview/azure/messaging.eventgrid-readme?source=recommendations&view=azure-dotnet) to learn more about publishing custom events. -------------------------------------------------------------------------------- /docs/sidebars.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creating a sidebar enables you to: 3 | - create an ordered group of docs 4 | - render a sidebar for each doc of that group 5 | - provide next/previous navigation 6 | 7 | The sidebars can be generated from the filesystem, or explicitly defined here. 8 | 9 | Create as many sidebars as you want. 10 | */ 11 | 12 | module.exports = { 13 | // By default, Docusaurus generates a sidebar from the docs folder structure 14 | tutorialSidebar: [{type: 'autogenerated', dirName: '.'}], 15 | 16 | // But you can create a sidebar manually 17 | /* 18 | tutorialSidebar: [ 19 | { 20 | type: 'category', 21 | label: 'Tutorial', 22 | items: ['hello'], 23 | }, 24 | ], 25 | */ 26 | }; 27 | -------------------------------------------------------------------------------- /docs/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | /** 3 | * Any CSS included here will be global. The classic template 4 | * bundles Infima by default. Infima is a CSS framework designed to 5 | * work well for content-centric websites. 6 | */ 7 | 8 | /* You can override the default Infima variables here. */ 9 | :root { 10 | --ifm-color-primary: #248eff; 11 | --ifm-color-primary-dark: #078fff; 12 | --ifm-color-primary-darker: #0088f7; 13 | --ifm-color-primary-darkest: #006cc6; 14 | --ifm-color-primary-light: #47acff; 15 | --ifm-color-primary-lighter: #55b2ff; 16 | --ifm-color-primary-lightest: #81c6ff; 17 | 18 | --ifm-color-secondary: #cacad2; 19 | --ifm-color-secondary-dark: #9f9fac; 20 | --ifm-color-secondary-darker: #9f9fac; 21 | --ifm-color-secondary-darkest: #666675; 22 | --ifm-color-secondary-light: #e9e9f0; 23 | --ifm-color-secondary-lighter: #f4f4f7; 24 | --ifm-color-secondary-lightest: #f4f4f7; 25 | 26 | --ifm-color-warning: #ff970f; 27 | --ifm-color-warning-dark: #db770a; 28 | --ifm-color-warning-darker: #b75b07; 29 | --ifm-color-warning-darkest: #934304; 30 | --ifm-color-warning-light: #ffb84b; 31 | --ifm-color-warning-lighter: #ffcd6f; 32 | --ifm-color-warning-lightest: #ffe29f; 33 | --ifm-code-font-size: 95%; 34 | 35 | --ifm-color-gray-100: #e9edfa; 36 | --ifm-color-gray-200: #d5daec; 37 | --ifm-color-gray-300: #ccd1e3; 38 | --ifm-color-gray-400: #a6aecb; 39 | --ifm-color-gray-500: #8b95b8; 40 | --ifm-color-gray-600: #575f82; 41 | --ifm-color-gray-700: #444b6d; 42 | --ifm-color-gray-800: #242b47; 43 | --ifm-color-gray-900: #1d2338; 44 | 45 | --ifm-navbar-shadow: 0 1px 2px 0 var(--ifm-color-primary); 46 | --ifm-toc-border-color: var(--ifm-color-primary); 47 | --ifm-global-spacing: 1.5rem; 48 | } 49 | 50 | .docusaurus-highlight-code-line { 51 | background-color: rgba(0, 0, 0, 0.1); 52 | display: block; 53 | margin: 0 calc(-1 * var(--ifm-pre-padding)); 54 | padding: 0 var(--ifm-pre-padding); 55 | } 56 | 57 | .alert { 58 | background-color: var(--ifm-alert-background-color) !important; 59 | } 60 | 61 | html[data-theme='dark'] .docusaurus-highlight-code-line { 62 | background-color: var(--ifm-color-gray-800); 63 | } 64 | 65 | html[data-theme='dark'] code { 66 | background-color: var(--ifm-color-gray-800); 67 | } 68 | 69 | html[data-theme='dark'] main img[src$='.png'] { 70 | background-color: white; 71 | } 72 | 73 | html[data-theme='dark'] { 74 | --ifm-background-color: var(--ifm-color-gray-900); 75 | --ifm-color-primary: #249cff; 76 | 77 | --ifm-navbar-background-color: var(--ifm-color-gray-800); 78 | } 79 | 80 | .footer--dark { 81 | background-color: var(--ifm-color-gray-800); 82 | } 83 | 84 | html[data-theme='dark'] .footer--dark { 85 | background-color: var(--ifm-color-gray-800); 86 | border-top: 1px solid var(--ifm-color-primary); 87 | } 88 | 89 | .navbar__brand img { 90 | width: 110px; 91 | height: auto; 92 | margin-right: 10px; 93 | margin-bottom: 5px; 94 | } 95 | 96 | html { 97 | font-family: 'Inter'; 98 | font-weight: normal; 99 | } 100 | 101 | h1, 102 | h2, 103 | h3, 104 | h4, 105 | h5 { 106 | font-family: 'Bitter'; 107 | line-height: 110%; 108 | } 109 | 110 | h1 { 111 | margin-top: 0.25rem; 112 | } 113 | 114 | p, 115 | .theme-doc-markdown li { 116 | font-size: 1.1rem; 117 | line-height: 150%; 118 | } 119 | 120 | strong, 121 | .navbar__title { 122 | font-family: 'Bitter'; 123 | } 124 | 125 | .navbar__title { 126 | font-size: 1rem; 127 | align-self: baseline; 128 | margin-top: 8px; 129 | } 130 | 131 | nav.menu { 132 | padding: 1rem; 133 | } 134 | -------------------------------------------------------------------------------- /docs/src/pages/index.module.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/docs/src/pages/index.module.css -------------------------------------------------------------------------------- /docs/src/prism/dark.js: -------------------------------------------------------------------------------- 1 | ('use strict'); 2 | 3 | // Original: https://github.com/sdras/night-owl-vscode-theme 4 | 5 | var theme = { 6 | plain: { 7 | color: '#e9edfa', 8 | backgroundColor: '#19203d', 9 | }, 10 | styles: [ 11 | { 12 | types: ['changed'], 13 | style: { 14 | color: 'rgb(162, 191, 252)', 15 | fontStyle: 'italic', 16 | }, 17 | }, 18 | { 19 | types: ['deleted'], 20 | style: { 21 | color: 'hsl(5, 74%, 69%)', 22 | fontStyle: 'italic', 23 | }, 24 | }, 25 | { 26 | types: ['inserted', 'attr-name'], 27 | style: { 28 | color: 'hsl(119, 34%, 67%)', 29 | fontStyle: 'italic', 30 | }, 31 | }, 32 | { 33 | types: ['comment'], 34 | style: { 35 | color: 'hsl(230, 4%, 74%)', 36 | fontStyle: 'italic', 37 | }, 38 | }, 39 | { 40 | types: ['string', 'url'], 41 | style: { 42 | color: 'hsl(119, 34%, 67%)', 43 | }, 44 | }, 45 | { 46 | types: ['variable'], 47 | style: { 48 | color: '#47acff', 49 | }, 50 | }, 51 | { 52 | types: ['number'], 53 | style: { 54 | color: 'hsl(35, 99%, 66%)', 55 | }, 56 | }, 57 | { 58 | types: ['builtin', 'char', 'constant', 'function', 'operator'], 59 | style: { 60 | color: '#47acff', 61 | }, 62 | }, 63 | { 64 | // This was manually added after the auto-generation 65 | // so that punctuations are not italicised 66 | types: ['punctuation'], 67 | style: { 68 | color: '#e9edfa', 69 | }, 70 | }, 71 | { 72 | types: ['selector', 'doctype'], 73 | style: { 74 | color: '#e9edfa', 75 | fontStyle: 'italic', 76 | }, 77 | }, 78 | { 79 | types: ['class-name'], 80 | style: { 81 | color: 'hsl(35, 99%, 66%)', 82 | }, 83 | }, 84 | { 85 | types: ['tag', 'keyword'], 86 | style: { 87 | color: 'hsl(301, 63%, 80%)', 88 | }, 89 | }, 90 | { 91 | types: ['boolean'], 92 | style: { 93 | color: 'hsl(35, 99%, 66%)', 94 | }, 95 | }, 96 | { 97 | types: ['property'], 98 | style: { 99 | color: 'hsl(5, 74%, 69%)', 100 | }, 101 | }, 102 | { 103 | types: ['namespace'], 104 | style: { 105 | opacity: 0.8, 106 | }, 107 | }, 108 | ], 109 | }; 110 | 111 | module.exports = theme; 112 | -------------------------------------------------------------------------------- /docs/src/prism/light.js: -------------------------------------------------------------------------------- 1 | ('use strict'); 2 | 3 | // Original: https://github.com/sdras/night-owl-vscode-theme 4 | 5 | var theme = { 6 | plain: { 7 | color: '#19203d', 8 | backgroundColor: '#f6f8fa', 9 | }, 10 | styles: [ 11 | { 12 | types: ['changed'], 13 | style: { 14 | color: 'rgb(162, 191, 252)', 15 | fontStyle: 'italic', 16 | }, 17 | }, 18 | { 19 | types: ['deleted'], 20 | style: { 21 | color: 'hsl(5, 74%, 59%)', 22 | fontStyle: 'italic', 23 | }, 24 | }, 25 | { 26 | types: ['inserted', 'attr-name'], 27 | style: { 28 | color: 'hsl(119, 34%, 47%)', 29 | fontStyle: 'italic', 30 | }, 31 | }, 32 | { 33 | types: ['comment'], 34 | style: { 35 | color: 'hsl(230, 4%, 64%)', 36 | fontStyle: 'italic', 37 | }, 38 | }, 39 | { 40 | types: ['string', 'url'], 41 | style: { 42 | color: 'hsl(119, 34%, 47%)', 43 | }, 44 | }, 45 | { 46 | types: ['variable'], 47 | style: { 48 | color: '#249cff', 49 | }, 50 | }, 51 | { 52 | types: ['number'], 53 | style: { 54 | color: 'hsl(35, 99%, 36%)', 55 | }, 56 | }, 57 | { 58 | types: ['builtin', 'char', 'constant', 'function', 'operator'], 59 | style: { 60 | color: '#249cff', 61 | }, 62 | }, 63 | { 64 | // This was manually added after the auto-generation 65 | // so that punctuations are not italicised 66 | types: ['punctuation'], 67 | style: { 68 | color: '#19203d', 69 | }, 70 | }, 71 | { 72 | types: ['selector', 'doctype'], 73 | style: { 74 | color: '#19203d', 75 | fontStyle: 'italic', 76 | }, 77 | }, 78 | { 79 | types: ['class-name'], 80 | style: { 81 | color: 'hsl(35, 99%, 36%)', 82 | }, 83 | }, 84 | { 85 | types: ['tag', 'keyword'], 86 | style: { 87 | color: 'hsl(301, 63%, 40%)', 88 | }, 89 | }, 90 | { 91 | types: ['boolean'], 92 | style: { 93 | color: 'hsl(35, 99%, 36%)', 94 | }, 95 | }, 96 | { 97 | types: ['property'], 98 | style: { 99 | color: 'hsl(5, 74%, 59%)', 100 | }, 101 | }, 102 | { 103 | types: ['namespace'], 104 | style: { 105 | opacity: 0.8, 106 | }, 107 | }, 108 | ], 109 | }; 110 | 111 | module.exports = theme; 112 | -------------------------------------------------------------------------------- /docs/static/img/arcus.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/docs/static/img/arcus.jpg -------------------------------------------------------------------------------- /docs/static/img/arcus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/docs/static/img/arcus.png -------------------------------------------------------------------------------- /docs/static/img/arcus_for_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/docs/static/img/arcus_for_dark.png -------------------------------------------------------------------------------- /docs/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/docs/static/img/favicon.ico -------------------------------------------------------------------------------- /docs/static/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/docs/static/img/icon.png -------------------------------------------------------------------------------- /docs/static/media/event-grid-delivery-properties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/docs/static/media/event-grid-delivery-properties.png -------------------------------------------------------------------------------- /docs/static/media/event-grid-traceparent-delivery-properties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/docs/static/media/event-grid-traceparent-delivery-properties.png -------------------------------------------------------------------------------- /docs/static/media/integration-testing-infrastructure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/docs/static/media/integration-testing-infrastructure.png -------------------------------------------------------------------------------- /docs/static/media/logos/armviz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/docs/static/media/logos/armviz.png -------------------------------------------------------------------------------- /docs/static/media/schematics/schematics.drawio: -------------------------------------------------------------------------------- 1 | 5Vpbc5s4FP41fnRGXITtx9RO28xkO9mms033TQYB2mLECuFLf/1KIC4CfEli7Ow0yQM6kg7S+b7v6EJG1ny1/cRQEv5BPRyNTOBtR9ZiZJqGbZoj+Qe8XWGZWsoQMOKpRrXhifzCygiUNSMeTrWGnNKIk0Q3ujSOscs1G2KMbvRmPo30tyYowB3Dk4uirvU78XioZgFBbf+MSRCWbzaAqlmhsrEypCHy6KZhsu5G1pxRyoun1XaOIxm8Mi5Fv497aquBMRzzUzr86z9kcPzl8ev93z+/bP56/mjf/jlWXtYoytSE1WD5rowAo1nsYekEjKwPm5Bw/JQgV9ZuBObCFvJVJEqGeFTuMON4u3ecRjV7QRtMV5iznWiiOtgqXoowRhm/TR3+qk3YDP1MGZGCPKhc11ERDyowLwiS2QnSE0eMC9NnmvIDATOOB8ynMVesN2xZJlE0pxFluS/Lh/JX2FPO6E/cqHHyH+WhYS9+zgOF04LC6oEC9EABh0Jidpyu2BP6VUXKeEgDGqPorrZ+0Aldt3mgNFGo/IM53ylYUMbpYcxENNnuWfnLCz9k4QaWxcW2WbnYqVIxdjngw/iI+dGMufhAYCyVGhELMD/QzunHm+EIcbLWx3F29KwOevcxxwETr6axqPiGh1aT75uu26cmz1k60BlGNbNrq8buyV+C6r9b+qoCfDUg4GsEIObP9aDrwYxpjFuRVyYUkSAWxQj70oOMJRE7m1tlXhHPyxNiH8Z6kuzALMtqiMYZkGqv+eDENd8cCimng9TdWs7FBJ/kvtV0IhnRJRNPAc/ZWlg8sm6b0gTFpe0bTYhbVoiBNesaZs1Liw5iG5nIx5RjiVOCGRFTxkyZHuvyUe2SLS533IYGeZ+ySzK5Igy5905uxc6e3DqZLQE4j6QtB+pMmcAOU6odY5Mp06GYMukwRYHcljEjKA726q2By2k4KFEzyovsUQg1pIz8Ej1Q6QwxV/WGoCCjS+LgIe+8MEAPjlMX9+O4nEIbnglHOANHcZxeEsbyvPnbbS2Pbhknb9wyqq6PlOT5s8z409bibEDdRbHlVb2ax9qWI2umZwTBLd1RMcGOo5wl1XzeQJzuEfoxy7upFaNFIjdj60rcOPZu5SWFzKsRSlPiHqHDlvCKDeK5IMMEqmJNBlnYNZnxXL2x4tDkgueTyYlksw5mjTG4MYGlwT22Z53EAQ/s6d5KW521Vjsfncpaw2g5slqO9rBWsAXtGs0S2SA9MF6r9R6oXRKJh8Jjq3fpnvp+ioeRTfcwOGcYcSxsT9kydRlJil3xEPoxNP2cKJ9G1v2h6aVfPR5Kw2qgZ5SS+ba8XUvJgLata8l0LqklB7SWAPuVS4A5aTmyJjenLQIvlRM09Tc570VN3SP+Akf4f6Qm40pqss+lJvlpQ+OGbVxSTG0NGM4rxeS0ljgTDCOl9gbQBu9FS91bmlvmZmIq4IEsGVKHjVd/Innxwfqqd2iG3Q/T0QO3PdhJrXvi/opRNP5OWdRzM3Mf+wyJ0GUuzxi+MHQXuRNpS/8dQDTtQCSvNkkcCONVAbnI5YYN3h0g3Q9nRz62DKKGS3x9gdblgi+K9ff7Yv2p/wvCuvsP -------------------------------------------------------------------------------- /docs/versioned_docs/version-v1.0.0/01-index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Arcus Event Grid" 3 | layout: default 4 | slug: / 5 | sidebar_label: Welcome 6 | --- 7 | 8 | [![NuGet Badge](https://buildstats.info/nuget/Arcus.EventGrid.All?packageVersion=1.0.0)](https://www.nuget.org/packages/Arcus.EventGrid.All/) 9 | 10 | # Installation 11 | 12 | ```shell 13 | PM > Install-Package Arcus.EventGrid.All 14 | ``` 15 | 16 | # Features 17 | 18 | - Support for publishing events to an Event Grid Topic ([docs](./02-Features/publishing-events.md)) 19 | - Support for handling endpoint validation handshake ([docs](./02-Features/endpoint-validation.md)) 20 | - Provides event contracts for a subset of Azure services ([docs](./02-Features/azure-event-contracts.md)) 21 | 22 | # License 23 | This is licensed under The MIT License (MIT). Which means that you can use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the web application. But you always need to state that Codit is the original author of this web application. 24 | 25 | *[Full license here](https://github.com/arcus-azure/arcus.eventgrid/blob/master/LICENSE)* 26 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v1.0.0/02-Features/azure-event-contracts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Supported Azure Event Contracts" 3 | layout: default 4 | --- 5 | 6 | ## Supported Azure Event Contracts 7 | 8 | Currently we provide support for the following Azure events: 9 | - **Azure Storage** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-blob-storage)) 10 | - `Microsoft.Storage.BlobCreated` 11 | - **Azure Event Hubs** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-event-hubs)) 12 | - `Microsoft.EventHub.CaptureFileCreated` 13 | - **Azure IoT Hub** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-iot-hub)) 14 | - `Microsoft.Devices.DeviceCreated` 15 | - `Microsoft.Devices.DeviceDeleted` 16 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v1.0.0/02-Features/endpoint-validation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Endpoint validation" 3 | layout: default 4 | --- 5 | 6 | ## Endpoint validation 7 | 8 | We provide support for endpoint validation, when implementing your own custom web hook. This validation allows to secure your web hook with a secret key (taken from the query string or an HTTP header). This is required, because Azure Event Grid sends a validation request to a newly configured web hook, in order to prevent people leveraging Azure Event Grid to bring down a 3rd party API. The implementation we provide, is echoing back the validation key on your operation, in order to have the validation by Event Grid out of the box. 9 | 10 | Import the following namespace into your project: 11 | ```csharp 12 | using Arcus.EventGrid.Security; 13 | using Arcus.EventGrid.Security.Attributes; 14 | ``` 15 | 16 | Next, tag the Operation that will be handling the Event Grid events with the `EventGridSubscriptionValidator` and the `EventGridAuthorization` attributes, that will secure the endpoint and handle the handshake. 17 | ```csharp 18 | [EventGridSubscriptionValidator] 19 | [EventGridAuthorization("x-api-key", "event-grid")] 20 | public IHttpActionResult HandleEvents(HttpRequestMessage message) 21 | { 22 | return Ok(); 23 | } 24 | ``` 25 | 26 | ### Configuring Authorization with attributes 27 | There are 2 attributes available to secure operations: 28 | - The `EventGridAuthorization` has a hard-coded secret key and is only advised for demonstration or testing purposes. 29 | - The `DynamicEventGridAuthorizationAttribute` allows developer to specify a static `Func` with name `RetrieveAuthenticationSecret` to implement custom logic to retrieve the actual secret key (for example from Azure KeyVault, web.config or appsettings.json) 30 | 31 | These attributes will only allow an operation to be called, if the configured secret key value is found in the HTTP header or the Query String with the configured key name. 32 | 33 | #### The EventGridAuthorization attribute 34 | This attribute has the following public constructor. This constructor sets the header or query string name and the hard coded secret value. 35 | 36 | ```csharp 37 | [EventGridAuthorization("keyName", "keyValue")] 38 | ``` 39 | 40 | #### The DynamicEventGridAuthorization attribute 41 | This attribute has the following public constructors. This constructor sets the header or query string name to the provided value (or defaults to 'x-api-key' for the default constructor). 42 | 43 | ```csharp 44 | [DynamicEventGridAuthorizationAttribute()] 45 | [DynamicEventGridAuthorizationAttribute("custom-key-name")] 46 | ``` 47 | Important for this authorization method to work, is to set the static property `RetrieveAuthenticationSecret` to a `Func>`. This can be seen in the following example. 48 | 49 | ```csharp 50 | DynamicEventGridAuthorizationAttribute.RetrieveAuthenticationSecret = () => Task.FromResult("my-secret-key"); 51 | ``` 52 | 53 | [← back](/) -------------------------------------------------------------------------------- /docs/versioned_docs/version-v1.0.0/02-Features/publishing-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Publishing Events" 3 | layout: default 4 | --- 5 | 6 | ## Publishing Events 7 | 8 | We provide support for publishing custom events to a custom Azure Event Grid Topics. 9 | 10 | Import the following namespace into your project: 11 | 12 | ```csharp 13 | using Arcus.EventGrid.Publishing; 14 | ``` 15 | 16 | Next, create an `EventGridPublisher` instance via the `.Create()` method which requires the endpoint & authentication key of your custom topic endpoint. 17 | 18 | ```csharp 19 | var eventGridPublisher = EventGridPublisher.Create(topicEndpoint, endpointKey); 20 | ``` 21 | **Publishing EventGridEvent's** 22 | 23 | Create your event that you want to publish 24 | 25 | ```csharp 26 | string licensePlate = "1-TOM-337"; 27 | string eventSubject = $"/cars/{licensePlate}"; 28 | string eventId = Guid.NewGuid().ToString(); 29 | var @event = new NewCarRegistered(eventId, eventSubject, licensePlate); 30 | 31 | await eventGridPublisher.Publish(eventSubject, eventType: "NewCarRegistered", data: new [] { @event }, id: eventId); 32 | ``` 33 | 34 | [← back](/) 35 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v1.0.1/01-index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Arcus Event Grid" 3 | layout: default 4 | slug: / 5 | sidebar_label: Welcome 6 | --- 7 | 8 | [![NuGet Badge](https://buildstats.info/nuget/Arcus.EventGrid.All?packageVersion=1.0.1)](https://www.nuget.org/packages/Arcus.EventGrid.All/) 9 | 10 | # Installation 11 | 12 | ```shell 13 | PM > Install-Package Arcus.EventGrid.All 14 | ``` 15 | 16 | # Features 17 | 18 | - Support for publishing events to an Event Grid Topic ([docs](./02-Features/publishing-events.md)) 19 | - Support for handling endpoint validation handshake ([docs](./02-Features/endpoint-validation.md)) 20 | - Provides event contracts for a subset of Azure services ([docs](./02-Features/azure-event-contracts.md)) 21 | 22 | # License 23 | This is licensed under The MIT License (MIT). Which means that you can use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the web application. But you always need to state that Codit is the original author of this web application. 24 | 25 | *[Full license here](https://github.com/arcus-azure/arcus.eventgrid/blob/master/LICENSE)* 26 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v1.0.1/02-Features/azure-event-contracts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Supported Azure Event Contracts" 3 | layout: default 4 | --- 5 | 6 | ## Supported Azure Event Contracts 7 | 8 | Currently we provide support for the following Azure events: 9 | - **Azure Storage** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-blob-storage)) 10 | - `Microsoft.Storage.BlobCreated` 11 | - **Azure Event Hubs** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-event-hubs)) 12 | - `Microsoft.EventHub.CaptureFileCreated` 13 | - **Azure IoT Hub** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-iot-hub)) 14 | - `Microsoft.Devices.DeviceCreated` 15 | - `Microsoft.Devices.DeviceDeleted` 16 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v1.0.1/02-Features/endpoint-validation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Endpoint validation" 3 | layout: default 4 | --- 5 | 6 | ## Endpoint validation 7 | 8 | We provide support for endpoint validation, when implementing your own custom web hook. This validation allows to secure your web hook with a secret key (taken from the query string or an HTTP header). This is required, because Azure Event Grid sends a validation request to a newly configured web hook, in order to prevent people leveraging Azure Event Grid to bring down a 3rd party API. The implementation we provide, is echoing back the validation key on your operation, in order to have the validation by Event Grid out of the box. 9 | 10 | Import the following namespace into your project: 11 | ```csharp 12 | using Arcus.EventGrid.Security; 13 | using Arcus.EventGrid.Security.Attributes; 14 | ``` 15 | 16 | Next, tag the Operation that will be handling the Event Grid events with the `EventGridSubscriptionValidator` and the `EventGridAuthorization` attributes, that will secure the endpoint and handle the handshake. 17 | ```csharp 18 | [EventGridSubscriptionValidator] 19 | [EventGridAuthorization("x-api-key", "event-grid")] 20 | public IHttpActionResult HandleEvents(HttpRequestMessage message) 21 | { 22 | return Ok(); 23 | } 24 | ``` 25 | 26 | ### Configuring Authorization with attributes 27 | There are 2 attributes available to secure operations: 28 | - The `EventGridAuthorization` has a hard-coded secret key and is only advised for demonstration or testing purposes. 29 | - The `DynamicEventGridAuthorizationAttribute` allows developer to specify a static `Func` with name `RetrieveAuthenticationSecret` to implement custom logic to retrieve the actual secret key (for example from Azure KeyVault, web.config or appsettings.json) 30 | 31 | These attributes will only allow an operation to be called, if the configured secret key value is found in the HTTP header or the Query String with the configured key name. 32 | 33 | #### The EventGridAuthorization attribute 34 | This attribute has the following public constructor. This constructor sets the header or query string name and the hard coded secret value. 35 | 36 | ```csharp 37 | [EventGridAuthorization("keyName", "keyValue")] 38 | ``` 39 | 40 | #### The DynamicEventGridAuthorization attribute 41 | This attribute has the following public constructors. This constructor sets the header or query string name to the provided value (or defaults to 'x-api-key' for the default constructor). 42 | 43 | ```csharp 44 | [DynamicEventGridAuthorizationAttribute()] 45 | [DynamicEventGridAuthorizationAttribute("custom-key-name")] 46 | ``` 47 | Important for this authorization method to work, is to set the static property `RetrieveAuthenticationSecret` to a `Func>`. This can be seen in the following example. 48 | 49 | ```csharp 50 | DynamicEventGridAuthorizationAttribute.RetrieveAuthenticationSecret = () => Task.FromResult("my-secret-key"); 51 | ``` 52 | 53 | [← back](/) -------------------------------------------------------------------------------- /docs/versioned_docs/version-v1.0.1/02-Features/publishing-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Publishing Events" 3 | layout: default 4 | --- 5 | 6 | ## Publishing Events 7 | 8 | We provide support for publishing custom events to a custom Azure Event Grid Topics. 9 | 10 | Import the following namespace into your project: 11 | 12 | ```csharp 13 | using Arcus.EventGrid.Publishing; 14 | ``` 15 | 16 | Next, create an `EventGridPublisher` instance via the `.Create()` method which requires the endpoint & authentication key of your custom topic endpoint. 17 | 18 | ```csharp 19 | var eventGridPublisher = EventGridPublisher.Create(topicEndpoint, endpointKey); 20 | ``` 21 | **Publishing EventGridEvent's** 22 | 23 | Create your event that you want to publish 24 | 25 | ```csharp 26 | string licensePlate = "1-TOM-337"; 27 | string eventSubject = $"/cars/{licensePlate}"; 28 | string eventId = Guid.NewGuid().ToString(); 29 | var @event = new NewCarRegistered(eventId, eventSubject, licensePlate); 30 | 31 | await eventGridPublisher.Publish(eventSubject, eventType: "NewCarRegistered", data: new [] { @event }, id: eventId); 32 | ``` 33 | 34 | [← back](/) 35 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v1.0.2/01-index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Arcus Event Grid" 3 | layout: default 4 | slug: / 5 | sidebar_label: Welcome 6 | --- 7 | 8 | [![NuGet Badge](https://buildstats.info/nuget/Arcus.EventGrid.All?packageVersion=1.0.2)](https://www.nuget.org/packages/Arcus.EventGrid.All/) 9 | 10 | # Installation 11 | 12 | ```shell 13 | PM > Install-Package Arcus.EventGrid.All 14 | ``` 15 | 16 | # Features 17 | 18 | - Support for publishing events to an Event Grid Topic ([docs](./02-Features/publishing-events.md)) 19 | - Support for handling endpoint validation handshake ([docs](./02-Features/endpoint-validation.md)) 20 | - Provides event contracts for a subset of Azure services ([docs](./02-Features/azure-event-contracts.md)) 21 | 22 | # License 23 | This is licensed under The MIT License (MIT). Which means that you can use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the web application. But you always need to state that Codit is the original author of this web application. 24 | 25 | *[Full license here](https://github.com/arcus-azure/arcus.eventgrid/blob/master/LICENSE)* 26 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v1.0.2/02-Features/azure-event-contracts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Supported Azure Event Contracts" 3 | layout: default 4 | --- 5 | 6 | ## Supported Azure Event Contracts 7 | 8 | Currently we provide support for the following Azure events: 9 | - **Azure Storage** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-blob-storage)) 10 | - `Microsoft.Storage.BlobCreated` 11 | - **Azure Event Hubs** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-event-hubs)) 12 | - `Microsoft.EventHub.CaptureFileCreated` 13 | - **Azure IoT Hub** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-iot-hub)) 14 | - `Microsoft.Devices.DeviceCreated` 15 | - `Microsoft.Devices.DeviceDeleted` 16 | 17 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v1.0.2/02-Features/endpoint-validation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Endpoint validation" 3 | layout: default 4 | --- 5 | 6 | ## Endpoint validation 7 | 8 | We provide support for endpoint validation, when implementing your own custom web hook. This validation allows to secure your web hook with a secret key (taken from the query string or an HTTP header). This is required, because Azure Event Grid sends a validation request to a newly configured web hook, in order to prevent people leveraging Azure Event Grid to bring down a 3rd party API. The implementation we provide, is echoing back the validation key on your operation, in order to have the validation by Event Grid out of the box. 9 | 10 | Import the following namespace into your project: 11 | ```csharp 12 | using Arcus.EventGrid.Security; 13 | using Arcus.EventGrid.Security.Attributes; 14 | ``` 15 | 16 | Next, tag the Operation that will be handling the Event Grid events with the `EventGridSubscriptionValidator` and the `EventGridAuthorization` attributes, that will secure the endpoint and handle the handshake. 17 | ```csharp 18 | [EventGridSubscriptionValidator] 19 | [EventGridAuthorization("x-api-key", "event-grid")] 20 | public IHttpActionResult HandleEvents(HttpRequestMessage message) 21 | { 22 | return Ok(); 23 | } 24 | ``` 25 | 26 | ### Configuring Authorization with attributes 27 | There are 2 attributes available to secure operations: 28 | - The `EventGridAuthorization` has a hard-coded secret key and is only advised for demonstration or testing purposes. 29 | - The `DynamicEventGridAuthorizationAttribute` allows developer to specify a static `Func` with name `RetrieveAuthenticationSecret` to implement custom logic to retrieve the actual secret key (for example from Azure KeyVault, web.config or appsettings.json) 30 | 31 | These attributes will only allow an operation to be called, if the configured secret key value is found in the HTTP header or the Query String with the configured key name. 32 | 33 | #### The EventGridAuthorization attribute 34 | This attribute has the following public constructor. This constructor sets the header or query string name and the hard coded secret value. 35 | 36 | ```csharp 37 | [EventGridAuthorization("keyName", "keyValue")] 38 | ``` 39 | 40 | #### The DynamicEventGridAuthorization attribute 41 | This attribute has the following public constructors. This constructor sets the header or query string name to the provided value (or defaults to 'x-api-key' for the default constructor). 42 | 43 | ```csharp 44 | [DynamicEventGridAuthorizationAttribute()] 45 | [DynamicEventGridAuthorizationAttribute("custom-key-name")] 46 | ``` 47 | Important for this authorization method to work, is to set the static property `RetrieveAuthenticationSecret` to a `Func>`. This can be seen in the following example. 48 | 49 | ```csharp 50 | DynamicEventGridAuthorizationAttribute.RetrieveAuthenticationSecret = () => Task.FromResult("my-secret-key"); 51 | ``` 52 | 53 | [← back](/) -------------------------------------------------------------------------------- /docs/versioned_docs/version-v1.0.2/02-Features/publishing-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Publishing Events" 3 | layout: default 4 | --- 5 | 6 | ## Publishing Events 7 | 8 | We provide support for publishing custom events to a custom Azure Event Grid Topics. 9 | 10 | Import the following namespace into your project: 11 | 12 | ```csharp 13 | using Arcus.EventGrid.Publishing; 14 | ``` 15 | 16 | Next, create an `EventGridPublisher` instance via the `.Create()` method which requires the endpoint & authentication key of your custom topic endpoint. 17 | 18 | ```csharp 19 | var eventGridPublisher = EventGridPublisher.Create(topicEndpoint, endpointKey); 20 | ``` 21 | **Publishing EventGridEvent's** 22 | 23 | Create your event that you want to publish 24 | 25 | ```csharp 26 | string licensePlate = "1-TOM-337"; 27 | string eventSubject = $"/cars/{licensePlate}"; 28 | string eventId = Guid.NewGuid().ToString(); 29 | var @event = new NewCarRegistered(eventId, eventSubject, licensePlate); 30 | 31 | await eventGridPublisher.Publish(eventSubject, eventType: "NewCarRegistered", data: new [] { @event }, id: eventId); 32 | ``` 33 | 34 | [← back](/) 35 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v1.1.0/01-index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Arcus Event Grid" 3 | layout: default 4 | slug: / 5 | sidebar_label: Welcome 6 | --- 7 | 8 | [![NuGet Badge](https://buildstats.info/nuget/Arcus.EventGrid.All?packageVersion=1.1.0)](https://www.nuget.org/packages/Arcus.EventGrid.All/) 9 | 10 | # Installation 11 | 12 | ```shell 13 | PM > Install-Package Arcus.EventGrid.All 14 | ``` 15 | 16 | # Features 17 | 18 | - Support for publishing events to an Event Grid Topic ([docs](./02-Features/publishing-events.md)) 19 | - Support for handling endpoint validation handshake ([docs](./02-Features/endpoint-validation.md)) 20 | - Provides event contracts for a subset of Azure services ([docs](./02-Features/azure-event-contracts.md)) 21 | 22 | # License 23 | This is licensed under The MIT License (MIT). Which means that you can use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the web application. But you always need to state that Codit is the original author of this web application. 24 | 25 | *[Full license here](https://github.com/arcus-azure/arcus.eventgrid/blob/master/LICENSE)* 26 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v1.1.0/02-Features/azure-event-contracts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Supported Azure Event Contracts" 3 | layout: default 4 | --- 5 | 6 | ## Supported Azure Event Contracts 7 | 8 | Currently we provide support for the following Azure events: 9 | - **Azure Storage** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-blob-storage)) 10 | - `Microsoft.Storage.BlobCreated` 11 | - **Azure Event Hubs** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-event-hubs)) 12 | - `Microsoft.EventHub.CaptureFileCreated` 13 | - **Azure IoT Hub** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-iot-hub)) 14 | - `Microsoft.Devices.DeviceCreated` 15 | - `Microsoft.Devices.DeviceDeleted` 16 | 17 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v1.1.0/02-Features/endpoint-validation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Endpoint validation" 3 | layout: default 4 | --- 5 | 6 | ## Endpoint validation 7 | 8 | We provide support for endpoint validation, when implementing your own custom web hook. This validation allows to secure your web hook with a secret key (taken from the query string or an HTTP header). This is required, because Azure Event Grid sends a validation request to a newly configured web hook, in order to prevent people leveraging Azure Event Grid to bring down a 3rd party API. The implementation we provide, is echoing back the validation key on your operation, in order to have the validation by Event Grid out of the box. 9 | 10 | Import the following namespace into your project: 11 | ```csharp 12 | using Arcus.EventGrid.Security; 13 | using Arcus.EventGrid.Security.Attributes; 14 | ``` 15 | 16 | Next, tag the Operation that will be handling the Event Grid events with the `EventGridSubscriptionValidator` and the `EventGridAuthorization` attributes, that will secure the endpoint and handle the handshake. 17 | ```csharp 18 | [EventGridSubscriptionValidator] 19 | [EventGridAuthorization("x-api-key", "event-grid")] 20 | public IHttpActionResult HandleEvents(HttpRequestMessage message) 21 | { 22 | return Ok(); 23 | } 24 | ``` 25 | 26 | ### Configuring Authorization with attributes 27 | There are 2 attributes available to secure operations: 28 | - The `EventGridAuthorization` has a hard-coded secret key and is only advised for demonstration or testing purposes. 29 | - The `DynamicEventGridAuthorizationAttribute` allows developer to specify a static `Func` with name `RetrieveAuthenticationSecret` to implement custom logic to retrieve the actual secret key (for example from Azure KeyVault, web.config or appsettings.json) 30 | 31 | These attributes will only allow an operation to be called, if the configured secret key value is found in the HTTP header or the Query String with the configured key name. 32 | 33 | #### The EventGridAuthorization attribute 34 | This attribute has the following public constructor. This constructor sets the header or query string name and the hard coded secret value. 35 | 36 | ```csharp 37 | [EventGridAuthorization("keyName", "keyValue")] 38 | ``` 39 | 40 | #### The DynamicEventGridAuthorization attribute 41 | This attribute has the following public constructors. This constructor sets the header or query string name to the provided value (or defaults to 'x-api-key' for the default constructor). 42 | 43 | ```csharp 44 | [DynamicEventGridAuthorizationAttribute()] 45 | [DynamicEventGridAuthorizationAttribute("custom-key-name")] 46 | ``` 47 | Important for this authorization method to work, is to set the static property `RetrieveAuthenticationSecret` to a `Func>`. This can be seen in the following example. 48 | 49 | ```csharp 50 | DynamicEventGridAuthorizationAttribute.RetrieveAuthenticationSecret = () => Task.FromResult("my-secret-key"); 51 | ``` 52 | 53 | [← back](/) -------------------------------------------------------------------------------- /docs/versioned_docs/version-v1.1.0/02-Features/publishing-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Publishing Events" 3 | layout: default 4 | --- 5 | 6 | ## Publishing Events 7 | 8 | We provide support for publishing custom events to a custom Azure Event Grid Topics. 9 | 10 | Import the following namespace into your project: 11 | 12 | ```csharp 13 | using Arcus.EventGrid.Publishing; 14 | ``` 15 | 16 | Next, create an `EventGridPublisher` instance via the `EventGridPublisherBuilder` which requires the endpoint & authentication key of your custom topic endpoint. 17 | 18 | ```csharp 19 | var eventGridPublisher = EventGridPublisherBuilder 20 | .ForTopic(topicEndpoint) 21 | .UsingAuthenticationKey(endpointKey) 22 | .Build(); 23 | ``` 24 | **Publishing EventGridEvent's** 25 | 26 | Create your event that you want to publish 27 | 28 | ```csharp 29 | string licensePlate = "1-TOM-337"; 30 | string eventSubject = $"/cars/{licensePlate}"; 31 | string eventId = Guid.NewGuid().ToString(); 32 | var @event = new NewCarRegistered(eventId, eventSubject, licensePlate); 33 | 34 | await eventGridPublisher.Publish(eventSubject, eventType: "NewCarRegistered", data: new [] { @event }, id: eventId); 35 | ``` 36 | 37 | [← back](/) 38 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.0.0/01-index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Arcus Event Grid" 3 | layout: default 4 | slug: / 5 | sidebar_label: Welcome 6 | --- 7 | 8 | [![NuGet Badge](https://buildstats.info/nuget/Arcus.EventGrid.All?packageVersion=2.0.0)](https://www.nuget.org/packages/Arcus.EventGrid.All/) 9 | 10 | # Installation 11 | 12 | ```shell 13 | PM > Install-Package Arcus.EventGrid.All 14 | ``` 15 | 16 | # Features 17 | 18 | - Support for publishing events to an Event Grid Topic ([docs](./02-Features/publishing-events.md)) 19 | - Support for handling endpoint validation handshake ([docs](./02-Features/endpoint-validation.md)) 20 | - Provides event contracts for a subset of Azure services ([docs](./02-Features/azure-event-contracts.md)) 21 | - Support for creating your own events 22 | 23 | # License 24 | This is licensed under The MIT License (MIT). Which means that you can use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the web application. But you always need to state that Codit is the original author of this web application. 25 | 26 | *[Full license here](https://github.com/arcus-azure/arcus.eventgrid/blob/master/LICENSE)* 27 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.0.0/02-Features/azure-event-contracts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Supported Azure Event Contracts" 3 | layout: default 4 | --- 5 | 6 | ## Supported Azure Event Contracts 7 | 8 | Currently we provide support for the following Azure events: 9 | - **Azure Storage** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-blob-storage)) 10 | - `Microsoft.Storage.BlobCreated` 11 | - **Azure Event Hubs** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-event-hubs)) 12 | - `Microsoft.EventHub.CaptureFileCreated` 13 | - **Azure IoT Hub** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-iot-hub)) 14 | - `Microsoft.Devices.DeviceCreated` 15 | - `Microsoft.Devices.DeviceDeleted` 16 | 17 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.0.0/02-Features/deserializing-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Deserializing Events" 3 | layout: default 4 | --- 5 | 6 | ## Deserializing Events 7 | 8 | The `Arcus.EventGrid` package provides several ways to deserializing events. 9 | 10 | Following paragraphs describe each supported way to deserialize an event. 11 | 12 | - [Deserializing Events](#deserializing-events) 13 | - [Deserializing Custom Events](#deserializing-custom-events) 14 | 15 | ### Deserializing Custom Events 16 | 17 | We provide support for deserializing events to typed event objects where the custom event payload is available via the `.GetPayload()` method. 18 | 19 | If you want to have the original raw JSON event payload, you can get it via the `.Data` property. 20 | 21 | ```csharp 22 | using Arcus.EventGrid; 23 | using Arcus.EventGrid.Parsers; 24 | 25 | // Parse from your custom event implementation with the `.Parse<>` function. 26 | EventGridMessage eventGridBatch = EventGridParser.Parse(rawEvent); 27 | 28 | // The event data type will be wrapped inside an `EventGridMessage<>` instance. 29 | NewCarRegistered eventGridMessage = eventGridBatch.Events.First(); 30 | 31 | // The original event payload can now be accessed. 32 | CarEventData eventPayload = eventGridMessage.Data; 33 | ``` 34 | 35 | [← back](/) 36 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.0.0/02-Features/endpoint-validation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Endpoint validation" 3 | layout: default 4 | --- 5 | 6 | ## Endpoint validation 7 | 8 | We provide support for endpoint validation, when implementing your own custom web hook. This validation allows to secure your web hook with a secret key (taken from the query string or an HTTP header). This is required, because Azure Event Grid sends a validation request to a newly configured web hook, in order to prevent people leveraging Azure Event Grid to bring down a 3rd party API. The implementation we provide, is echoing back the validation key on your operation, in order to have the validation by Event Grid out of the box. 9 | 10 | Import the following namespace into your project: 11 | ```csharp 12 | using Arcus.EventGrid.Security; 13 | using Arcus.EventGrid.Security.Attributes; 14 | ``` 15 | 16 | Next, tag the Operation that will be handling the Event Grid events with the `EventGridSubscriptionValidator` and the `EventGridAuthorization` attributes, that will secure the endpoint and handle the handshake. 17 | ```csharp 18 | [EventGridSubscriptionValidator] 19 | [EventGridAuthorization("x-api-key", "event-grid")] 20 | public IHttpActionResult HandleEvents(HttpRequestMessage message) 21 | { 22 | return Ok(); 23 | } 24 | ``` 25 | 26 | ### Configuring Authorization with attributes 27 | There are 2 attributes available to secure operations: 28 | - The `EventGridAuthorization` has a hard-coded secret key and is only advised for demonstration or testing purposes. 29 | - The `DynamicEventGridAuthorizationAttribute` allows developer to specify a static `Func` with name `RetrieveAuthenticationSecret` to implement custom logic to retrieve the actual secret key (for example from Azure KeyVault, web.config or appsettings.json) 30 | 31 | These attributes will only allow an operation to be called, if the configured secret key value is found in the HTTP header or the Query String with the configured key name. 32 | 33 | #### The EventGridAuthorization attribute 34 | This attribute has the following public constructor. This constructor sets the header or query string name and the hard coded secret value. 35 | 36 | ```csharp 37 | [EventGridAuthorization("keyName", "keyValue")] 38 | ``` 39 | 40 | #### The DynamicEventGridAuthorization attribute 41 | This attribute has the following public constructors. This constructor sets the header or query string name to the provided value (or defaults to 'x-api-key' for the default constructor). 42 | 43 | ```csharp 44 | [DynamicEventGridAuthorizationAttribute()] 45 | [DynamicEventGridAuthorizationAttribute("custom-key-name")] 46 | ``` 47 | Important for this authorization method to work, is to set the static property `RetrieveAuthenticationSecret` to a `Func>`. This can be seen in the following example. 48 | 49 | ```csharp 50 | DynamicEventGridAuthorizationAttribute.RetrieveAuthenticationSecret = () => Task.FromResult("my-secret-key"); 51 | ``` 52 | 53 | [← back](/) -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.0.0/02-Features/publishing-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Publishing Events" 3 | layout: default 4 | --- 5 | 6 | ## Publishing Events 7 | 8 | We provide support for publishing custom events to a custom Azure Event Grid Topics. 9 | 10 | Import the following namespace into your project: 11 | 12 | ```csharp 13 | using Arcus.EventGrid.Publishing; 14 | ``` 15 | 16 | Next, create an `EventGridPublisher` instance via the `EventGridPublisherBuilder` which requires the endpoint & authentication key of your custom topic endpoint. 17 | 18 | ```csharp 19 | var eventGridPublisher = EventGridPublisherBuilder 20 | .ForTopic(topicEndpoint) 21 | .UsingAuthenticationKey(endpointKey) 22 | .Build(); 23 | ``` 24 | **Publishing EventGridEvent's** 25 | 26 | Create your event that you want to publish 27 | 28 | ```csharp 29 | string licensePlate = "1-TOM-337"; 30 | string eventSubject = $"/cars/{licensePlate}"; 31 | string eventId = Guid.NewGuid().ToString(); 32 | var @event = new NewCarRegistered(eventId, eventSubject, licensePlate); 33 | 34 | await eventGridPublisher.Publish(eventSubject, eventType: "NewCarRegistered", data: new [] { @event }, id: eventId); 35 | ``` 36 | 37 | Alternatively you can publish a list of events by using 38 | 39 | ```csharp 40 | await eventGridPublisher.PublishMany(events); 41 | ``` 42 | 43 | ### Resilient Publishing 44 | 45 | The `EventGridPublisherBuilder` also provides several ways to publish events in a resilient manner. Resilient meaning we support three ways to add resilience to your event publishing: 46 | 47 | - **Exponential retry**: makes the publishing resilient by retrying a specified number of times with exponential back off. 48 | 49 | ```csharp 50 | EventGridPublisherBuilder.ForTopic(topicEndpoint) 51 | .UsingAuthenticationKey(endpointKey) 52 | .WithExponentialRetry(retryCount) 53 | .Build(); 54 | ``` 55 | 56 | - **Circuit breaker**: makes the publishing resilient by breaking the circuit if the maximum specified number of exceptions are handled by the policy. The circuit will stay broken for a specified duration. Any attempt to execute the function while the circuit is broken will result in a `BrokenCircuitException`. 57 | 58 | ```csharp 59 | EventGridPublisherBuilder.ForTopic(topicEndpoint) 60 | .UsingAuthenticationKey(endpointKey) 61 | .WithCircuitBreaker(exceptionsBeforeBreaking, durationOfBreak) 62 | .Build(); 63 | ``` 64 | 65 | - Combination of the two: **Circuit breaker with/after exponential retry**. 66 | 67 | ```csharp 68 | EventGridPublisherBuilder.ForTopic(topicEndpoint) 69 | .UsingAuthenticationKey(endpointKey) 70 | .WithExponentialRetry(retryCount) 71 | .WithCircuitBreaker(exceptionsBeforeBreaking, durationOfBreak) 72 | .Build(); 73 | ``` 74 | 75 | [← back](/) 76 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.1.0/01-index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Arcus Event Grid" 3 | layout: default 4 | slug: / 5 | sidebar_label: Welcome 6 | --- 7 | 8 | [![NuGet Badge](https://buildstats.info/nuget/Arcus.EventGrid.All?packageVersion=2.1.0)](https://www.nuget.org/packages/Arcus.EventGrid.All/) 9 | 10 | # Installation 11 | 12 | ```shell 13 | PM > Install-Package Arcus.EventGrid.All 14 | ``` 15 | 16 | # Features 17 | 18 | - Support for publishing events to an Event Grid Topic ([docs](./02-Features/publishing-events.md)) 19 | - Support for handling endpoint validation handshake ([docs](./02-Features/endpoint-validation.md)) 20 | - Provides event contracts for a subset of Azure services ([docs](./02-Features/azure-event-contracts.md)) 21 | - Provide tooling for writing integration tests ([docs](./02-Features/running-integration-tests.md)) 22 | - Support for deserializing events ([docs](./02-Features/deserializing-events.md)) 23 | - Support for creating your own events 24 | 25 | # License 26 | This is licensed under The MIT License (MIT). Which means that you can use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the web application. But you always need to state that Codit is the original author of this web application. 27 | 28 | *[Full license here](https://github.com/arcus-azure/arcus.eventgrid/blob/master/LICENSE)* 29 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.1.0/02-Features/azure-event-contracts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Supported Azure Event Contracts" 3 | layout: default 4 | --- 5 | 6 | ## Supported Azure Event Contracts 7 | 8 | Currently we provide support for the following Azure events: 9 | - **Azure Storage** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-blob-storage)) 10 | - `Microsoft.Storage.BlobCreated` 11 | - **Azure Event Hubs** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-event-hubs)) 12 | - `Microsoft.EventHub.CaptureFileCreated` 13 | - **Azure IoT Hub** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-iot-hub)) 14 | - `Microsoft.Devices.DeviceCreated` 15 | - `Microsoft.Devices.DeviceDeleted` 16 | 17 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.1.0/02-Features/deserializing-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Deserializing Events" 3 | layout: default 4 | --- 5 | 6 | ## Deserializing Events 7 | 8 | The `Arcus.EventGrid` package provides several ways to deserializing events. 9 | 10 | Following paragraphs describe each supported way to deserialize an event. 11 | 12 | - [Deserializing Events](#deserializing-events) 13 | - [Deserializing Custom Events](#deserializing-custom-events) 14 | 15 | ### Deserializing Custom Events 16 | 17 | We provide support for deserializing events to typed event objects where the custom event payload is available via the `.GetPayload()` method. 18 | 19 | If you want to have the original raw JSON event payload, you can get it via the `.Data` property. 20 | 21 | ```csharp 22 | using Arcus.EventGrid; 23 | using Arcus.EventGrid.Parsers; 24 | 25 | // Parse from your custom event implementation with the `.Parse<>` function. 26 | EventGridMessage eventGridBatch = EventGridParser.Parse(rawEvent); 27 | 28 | // The event data type will be wrapped inside an `EventGridMessage<>` instance. 29 | NewCarRegistered eventGridMessage = eventGridBatch.Events.First(); 30 | 31 | // The original event payload can now be accessed. 32 | CarEventData eventPayload = eventGridMessage.Data; 33 | ``` 34 | 35 | [← back](/) 36 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.1.0/02-Features/endpoint-validation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Endpoint validation" 3 | layout: default 4 | --- 5 | 6 | ## Endpoint validation 7 | 8 | We provide support for endpoint validation, when implementing your own custom web hook. This validation allows to secure your web hook with a secret key (taken from the query string or an HTTP header). This is required, because Azure Event Grid sends a validation request to a newly configured web hook, in order to prevent people leveraging Azure Event Grid to bring down a 3rd party API. The implementation we provide, is echoing back the validation key on your operation, in order to have the validation by Event Grid out of the box. 9 | 10 | Import the following namespace into your project: 11 | ```csharp 12 | using Arcus.EventGrid.Security; 13 | using Arcus.EventGrid.Security.Attributes; 14 | ``` 15 | 16 | Next, tag the Operation that will be handling the Event Grid events with the `EventGridSubscriptionValidator` and the `EventGridAuthorization` attributes, that will secure the endpoint and handle the handshake. 17 | ```csharp 18 | [EventGridSubscriptionValidator] 19 | [EventGridAuthorization("x-api-key", "event-grid")] 20 | public IHttpActionResult HandleEvents(HttpRequestMessage message) 21 | { 22 | return Ok(); 23 | } 24 | ``` 25 | 26 | ### Configuring Authorization with attributes 27 | There are 2 attributes available to secure operations: 28 | - The `EventGridAuthorization` has a hard-coded secret key and is only advised for demonstration or testing purposes. 29 | - The `DynamicEventGridAuthorizationAttribute` allows developer to specify a static `Func` with name `RetrieveAuthenticationSecret` to implement custom logic to retrieve the actual secret key (for example from Azure KeyVault, web.config or appsettings.json) 30 | 31 | These attributes will only allow an operation to be called, if the configured secret key value is found in the HTTP header or the Query String with the configured key name. 32 | 33 | #### The EventGridAuthorization attribute 34 | This attribute has the following public constructor. This constructor sets the header or query string name and the hard coded secret value. 35 | 36 | ```csharp 37 | [EventGridAuthorization("keyName", "keyValue")] 38 | ``` 39 | 40 | #### The DynamicEventGridAuthorization attribute 41 | This attribute has the following public constructors. This constructor sets the header or query string name to the provided value (or defaults to 'x-api-key' for the default constructor). 42 | 43 | ```csharp 44 | [DynamicEventGridAuthorizationAttribute()] 45 | [DynamicEventGridAuthorizationAttribute("custom-key-name")] 46 | ``` 47 | Important for this authorization method to work, is to set the static property `RetrieveAuthenticationSecret` to a `Func>`. This can be seen in the following example. 48 | 49 | ```csharp 50 | DynamicEventGridAuthorizationAttribute.RetrieveAuthenticationSecret = () => Task.FromResult("my-secret-key"); 51 | ``` 52 | 53 | [← back](/) -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.1.0/02-Features/publishing-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Publishing Events" 3 | layout: default 4 | --- 5 | 6 | ## Publishing Events 7 | 8 | We provide support for publishing custom events to a custom Azure Event Grid Topics. 9 | 10 | Import the following namespace into your project: 11 | 12 | ```csharp 13 | using Arcus.EventGrid.Publishing; 14 | ``` 15 | 16 | Next, create an `EventGridPublisher` instance via the `EventGridPublisherBuilder` which requires the endpoint & authentication key of your custom topic endpoint. 17 | 18 | ```csharp 19 | var eventGridPublisher = EventGridPublisherBuilder 20 | .ForTopic(topicEndpoint) 21 | .UsingAuthenticationKey(endpointKey) 22 | .Build(); 23 | ``` 24 | **Publishing EventGridEvent's** 25 | 26 | 27 | 28 | Create your event that you want to publish 29 | 30 | ```csharp 31 | string licensePlate = "1-TOM-337"; 32 | string eventSubject = $"/cars/{licensePlate}"; 33 | string eventId = Guid.NewGuid().ToString(); 34 | var @event = new NewCarRegistered(eventId, eventSubject, licensePlate); 35 | 36 | await eventGridPublisher.Publish(@event); 37 | ``` 38 | 39 | Alternatively you can publish a list of events by using 40 | 41 | ```csharp 42 | await eventGridPublisher.PublishMany(events); 43 | ``` 44 | 45 | ### Resilient Publishing 46 | 47 | The `EventGridPublisherBuilder` also provides several ways to publish events in a resilient manner. Resilient meaning we support three ways to add resilience to your event publishing: 48 | 49 | - **Exponential retry**: makes the publishing resilient by retrying a specified number of times with exponential back off. 50 | 51 | ```csharp 52 | EventGridPublisherBuilder.ForTopic(topicEndpoint) 53 | .UsingAuthenticationKey(endpointKey) 54 | .WithExponentialRetry(retryCount) 55 | .Build(); 56 | ``` 57 | 58 | - **Circuit breaker**: makes the publishing resilient by breaking the circuit if the maximum specified number of exceptions are handled by the policy. The circuit will stay broken for a specified duration. Any attempt to execute the function while the circuit is broken will result in a `BrokenCircuitException`. 59 | 60 | ```csharp 61 | EventGridPublisherBuilder.ForTopic(topicEndpoint) 62 | .UsingAuthenticationKey(endpointKey) 63 | .WithCircuitBreaker(exceptionsBeforeBreaking, durationOfBreak) 64 | .Build(); 65 | ``` 66 | 67 | - Combination of the two: **Circuit breaker with/after exponential retry**. 68 | 69 | ```csharp 70 | EventGridPublisherBuilder.ForTopic(topicEndpoint) 71 | .UsingAuthenticationKey(endpointKey) 72 | .WithExponentialRetry(retryCount) 73 | .WithCircuitBreaker(exceptionsBeforeBreaking, durationOfBreak) 74 | .Build(); 75 | ``` 76 | 77 | [← back](/) 78 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.2.0/01-index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Arcus Event Grid" 3 | layout: default 4 | slug: / 5 | sidebar_label: Welcome 6 | --- 7 | 8 | [![NuGet Badge](https://buildstats.info/nuget/Arcus.EventGrid.All?packageVersion=2.2.0)](https://www.nuget.org/packages/Arcus.EventGrid.All/) 9 | 10 | # Installation 11 | 12 | ```shell 13 | PM > Install-Package Arcus.EventGrid.All 14 | ``` 15 | 16 | # Features 17 | 18 | - Support for publishing events to an Event Grid Topic ([docs](./02-Features/publishing-events.md)) 19 | - Support for handling endpoint validation handshake ([docs](./02-Features/endpoint-validation.md)) 20 | - Provides event contracts for a subset of Azure services ([docs](./02-Features/azure-event-contracts.md)) 21 | - Provide tooling for writing integration tests ([docs](./02-Features/running-integration-tests.md)) 22 | - Support for deserializing events ([docs](./02-Features/deserializing-events.md)) 23 | - Support for creating your own events 24 | 25 | # License 26 | This is licensed under The MIT License (MIT). Which means that you can use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the web application. But you always need to state that Codit is the original author of this web application. 27 | 28 | *[Full license here](https://github.com/arcus-azure/arcus.eventgrid/blob/master/LICENSE)* 29 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.2.0/02-Features/azure-event-contracts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Supported Azure Event Contracts" 3 | layout: default 4 | --- 5 | 6 | ## Supported Azure Event Contracts 7 | 8 | Currently we provide support for the following Azure events: 9 | - **Azure Storage** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-blob-storage)) 10 | - `Microsoft.Storage.BlobCreated` 11 | - **Azure Event Hubs** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-event-hubs)) 12 | - `Microsoft.EventHub.CaptureFileCreated` 13 | - **Azure IoT Hub** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-iot-hub)) 14 | - `Microsoft.Devices.DeviceCreated` 15 | - `Microsoft.Devices.DeviceDeleted` 16 | 17 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.2.0/02-Features/deserializing-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Deserializing Events" 3 | layout: default 4 | --- 5 | 6 | ## Deserializing Events 7 | 8 | The `Arcus.EventGrid` package provides several ways to deserializing events. 9 | 10 | Following paragraphs describe each supported way to deserialize an event. 11 | 12 | - [Deserializing Events](#deserializing-events) 13 | - [Deserializing Custom Events](#deserializing-custom-events) 14 | 15 | ### Deserializing Custom Events 16 | 17 | We provide support for deserializing events to typed event objects where the custom event payload is available via the `.GetPayload()` method. 18 | 19 | If you want to have the original raw JSON event payload, you can get it via the `.Data` property. 20 | 21 | ```csharp 22 | using Arcus.EventGrid; 23 | using Arcus.EventGrid.Parsers; 24 | 25 | // Parse from your custom event implementation with the `.Parse<>` function. 26 | EventGridMessage eventGridBatch = EventGridParser.Parse(rawEvent); 27 | 28 | // The event data type will be wrapped inside an `EventGridMessage<>` instance. 29 | NewCarRegistered eventGridMessage = eventGridBatch.Events.First(); 30 | 31 | // The original event payload can now be accessed. 32 | CarEventData eventPayload = eventGridMessage.Data; 33 | ``` 34 | 35 | [← back](/) 36 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.2.0/02-Features/endpoint-validation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Endpoint validation" 3 | layout: default 4 | --- 5 | 6 | ## Endpoint validation 7 | 8 | We provide support for endpoint validation, when implementing your own custom web hook. This validation allows to secure your web hook with a secret key (taken from the query string or an HTTP header). This is required, because Azure Event Grid sends a validation request to a newly configured web hook, in order to prevent people leveraging Azure Event Grid to bring down a 3rd party API. The implementation we provide, is echoing back the validation key on your operation, in order to have the validation by Event Grid out of the box. 9 | 10 | Import the following namespace into your project: 11 | ```csharp 12 | using Arcus.EventGrid.Security; 13 | using Arcus.EventGrid.Security.Attributes; 14 | ``` 15 | 16 | Next, tag the Operation that will be handling the Event Grid events with the `EventGridSubscriptionValidator` and the `EventGridAuthorization` attributes, that will secure the endpoint and handle the handshake. 17 | ```csharp 18 | [EventGridSubscriptionValidator] 19 | [EventGridAuthorization("x-api-key", "event-grid")] 20 | public IHttpActionResult HandleEvents(HttpRequestMessage message) 21 | { 22 | return Ok(); 23 | } 24 | ``` 25 | 26 | ### Configuring Authorization with attributes 27 | There are 2 attributes available to secure operations: 28 | - The `EventGridAuthorization` has a hard-coded secret key and is only advised for demonstration or testing purposes. 29 | - The `DynamicEventGridAuthorizationAttribute` allows developer to specify a static `Func` with name `RetrieveAuthenticationSecret` to implement custom logic to retrieve the actual secret key (for example from Azure KeyVault, web.config or appsettings.json) 30 | 31 | These attributes will only allow an operation to be called, if the configured secret key value is found in the HTTP header or the Query String with the configured key name. 32 | 33 | #### The EventGridAuthorization attribute 34 | This attribute has the following public constructor. This constructor sets the header or querystring name and the hard coded secret value. 35 | 36 | ```csharp 37 | [EventGridAuthorization("keyName", "keyValue")] 38 | ``` 39 | 40 | #### The DynamicEventGridAuthorization attribute 41 | This attribute has the following public constructors. This constructor sets the header or querystring name to the provided value (or defaults to 'x-api-key' for the default constructor). 42 | 43 | ```csharp 44 | [DynamicEventGridAuthorizationAttribute()] 45 | [DynamicEventGridAuthorizationAttribute("custom-key-name")] 46 | ``` 47 | Important for this authorization method to work, is to set the static property `RetrieveAuthenticationSecret` to a `Func>`. This can be seen in the following example. 48 | 49 | ```csharp 50 | DynamicEventGridAuthorizationAttribute.RetrieveAuthenticationSecret = () => Task.FromResult("my-secret-key"); 51 | ``` 52 | 53 | [← back](/) -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.2.0/02-Features/publishing-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Publishing Events" 3 | layout: default 4 | --- 5 | 6 | ## Publishing Events 7 | 8 | We provide support for publishing custom events to a custom Azure Event Grid Topics. 9 | 10 | Import the following namespace into your project: 11 | 12 | ```csharp 13 | using Arcus.EventGrid.Publishing; 14 | ``` 15 | 16 | Next, create an `EventGridPublisher` instance via the `EventGridPublisherBuilder` which requires the endpoint & authentication key of your custom topic endpoint. 17 | 18 | ```csharp 19 | var eventGridPublisher = EventGridPublisherBuilder 20 | .ForTopic(topicEndpoint) 21 | .UsingAuthenticationKey(endpointKey) 22 | .Build(); 23 | ``` 24 | **Publishing EventGridEvent's** 25 | 26 | Create your event that you want to publish 27 | 28 | ```csharp 29 | string licensePlate = "1-TOM-337"; 30 | string eventSubject = $"/cars/{licensePlate}"; 31 | string eventId = Guid.NewGuid().ToString(); 32 | var @event = new NewCarRegistered(eventId, eventSubject, licensePlate); 33 | 34 | await eventGridPublisher.Publish(@event); 35 | ``` 36 | 37 | Alternatively you can publish a list of events by using 38 | 39 | ```csharp 40 | await eventGridPublisher.PublishMany(events); 41 | ``` 42 | 43 | ### Resilient Publishing 44 | 45 | The `EventGridPublisherBuilder` also provides several ways to publish events in a resilient manner. Resilient meaning we support three ways to add resilience to your event publishing: 46 | 47 | - **Exponential retry**: makes the publishing resilient by retrying a specified number of times with exponential back off. 48 | 49 | ```csharp 50 | EventGridPublisherBuilder.ForTopic(topicEndpoint) 51 | .UsingAuthenticationKey(endpointKey) 52 | .WithExponentialRetry(retryCount) 53 | .Build(); 54 | ``` 55 | 56 | - **Circuit breaker**: makes the publishing resilient by breaking the circuit if the maximum specified number of exceptions are handled by the policy. The circuit will stay broken for a specified duration. Any attempt to execute the function while the circuit is broken will result in a `BrokenCircuitException`. 57 | 58 | ```csharp 59 | EventGridPublisherBuilder.ForTopic(topicEndpoint) 60 | .UsingAuthenticationKey(endpointKey) 61 | .WithCircuitBreaker(exceptionsBeforeBreaking, durationOfBreak) 62 | .Build(); 63 | ``` 64 | 65 | - Combination of the two: **Circuit breaker with/after exponential retry**. 66 | 67 | ```csharp 68 | EventGridPublisherBuilder.ForTopic(topicEndpoint) 69 | .UsingAuthenticationKey(endpointKey) 70 | .WithExponentialRetry(retryCount) 71 | .WithCircuitBreaker(exceptionsBeforeBreaking, durationOfBreak) 72 | .Build(); 73 | ``` 74 | 75 | [← back](/) 76 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.3.0/01-index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Arcus Event Grid" 3 | layout: default 4 | slug: / 5 | sidebar_label: Welcome 6 | --- 7 | 8 | [![NuGet Badge](https://buildstats.info/nuget/Arcus.EventGrid.All?packageVersion=2.3.0)](https://www.nuget.org/packages/Arcus.EventGrid.All/) 9 | 10 | # Installation 11 | 12 | ```shell 13 | PM > Install-Package Arcus.EventGrid.All 14 | ``` 15 | 16 | # Features 17 | 18 | - Support for publishing events to an Event Grid Topic ([docs](./02-Features/publishing-events.md)) 19 | - Support for handling endpoint validation handshake ([docs](./02-Features/endpoint-validation.md)) 20 | - Provides event contracts for a subset of Azure services ([docs](./02-Features/azure-event-contracts.md)) 21 | - Provide tooling for writing integration tests ([docs](./02-Features/running-integration-tests.md)) 22 | - Support for deserializing events ([docs](./02-Features/deserializing-events.md)) 23 | - Support for creating your own events 24 | 25 | # License 26 | This is licensed under The MIT License (MIT). Which means that you can use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the web application. But you always need to state that Codit is the original author of this web application. 27 | 28 | *[Full license here](https://github.com/arcus-azure/arcus.eventgrid/blob/master/LICENSE)* 29 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.3.0/02-Features/azure-event-contracts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Supported Azure Event Contracts" 3 | layout: default 4 | --- 5 | 6 | ## Supported Azure Event Contracts 7 | 8 | Currently we provide support for the following Azure events: 9 | - **Azure Storage** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-blob-storage)) 10 | - `Microsoft.Storage.BlobCreated` 11 | - **Azure Event Hubs** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-event-hubs)) 12 | - `Microsoft.EventHub.CaptureFileCreated` 13 | - **Azure IoT Hub** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-iot-hub)) 14 | - `Microsoft.Devices.DeviceCreated` 15 | - `Microsoft.Devices.DeviceDeleted` 16 | 17 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.3.0/02-Features/deserializing-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Deserializing Events" 3 | layout: default 4 | --- 5 | 6 | ## Deserializing Events 7 | 8 | The `Arcus.EventGrid` package provides several ways to deserializing events. 9 | 10 | Following paragraphs describe each supported way to deserialize an event. 11 | 12 | - [Deserializing Events](#deserializing-events) 13 | - [Deserializing Custom Events](#deserializing-custom-events) 14 | 15 | ### Deserializing Custom Events 16 | 17 | We provide support for deserializing events to typed event objects where the custom event payload is available via the `.GetPayload()` method. 18 | 19 | If you want to have the original raw JSON event payload, you can get it via the `.Data` property. 20 | 21 | ```csharp 22 | using Arcus.EventGrid; 23 | using Arcus.EventGrid.Parsers; 24 | 25 | // Parse from your custom event implementation with the `.Parse<>` function. 26 | EventGridMessage eventGridBatch = EventGridParser.Parse(rawEvent); 27 | 28 | // The event data type will be wrapped inside an `EventGridMessage<>` instance. 29 | NewCarRegistered eventGridMessage = eventGridBatch.Events.First(); 30 | 31 | // The original event payload can now be accessed. 32 | CarEventData eventPayload = eventGridMessage.Data; 33 | ``` 34 | 35 | [← back](/) 36 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.3.0/02-Features/endpoint-validation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Endpoint validation" 3 | layout: default 4 | --- 5 | 6 | ## Endpoint validation 7 | 8 | We provide support for endpoint validation, when implementing your own custom web hook. This validation allows to secure your web hook with a secret key (taken from the query string or an HTTP header). This is required, because Azure Event Grid sends a validation request to a newly configured web hook, in order to prevent people leveraging Azure Event Grid to bring down a 3rd party API. The implementation we provide, is echoing back the validation key on your operation, in order to have the validation by Event Grid out of the box. 9 | 10 | Import the following namespace into your project: 11 | ```csharp 12 | using Arcus.EventGrid.Security; 13 | using Arcus.EventGrid.Security.Attributes; 14 | ``` 15 | 16 | Next, tag the Operation that will be handling the Event Grid events with the `EventGridSubscriptionValidator` and the `EventGridAuthorization` attributes, that will secure the endpoint and handle the handshake. 17 | ```csharp 18 | [EventGridSubscriptionValidator] 19 | [EventGridAuthorization("x-api-key", "event-grid")] 20 | public IHttpActionResult HandleEvents(HttpRequestMessage message) 21 | { 22 | return Ok(); 23 | } 24 | ``` 25 | 26 | ### Configuring Authorization with attributes 27 | There are 2 attributes available to secure operations: 28 | - The `EventGridAuthorization` has a hard-coded secret key and is only advised for demonstration or testing purposes. 29 | - The `DynamicEventGridAuthorizationAttribute` allows developer to specify a static `Func` with name `RetrieveAuthenticationSecret` to implement custom logic to retrieve the actual secret key (for example from Azure KeyVault, web.config or appsettings.json) 30 | 31 | These attributes will only allow an operation to be called, if the configured secret key value is found in the HTTP header or the Query String with the configured key name. 32 | 33 | #### The EventGridAuthorization attribute 34 | This attribute has the following public constructor. This constructor sets the header or query string name and the hard coded secret value. 35 | 36 | ```csharp 37 | [EventGridAuthorization("keyName", "keyValue")] 38 | ``` 39 | 40 | #### The DynamicEventGridAuthorization attribute 41 | This attribute has the following public constructors. This constructor sets the header or query string name to the provided value (or defaults to 'x-api-key' for the default constructor). 42 | 43 | ```csharp 44 | [DynamicEventGridAuthorizationAttribute()] 45 | [DynamicEventGridAuthorizationAttribute("custom-key-name")] 46 | ``` 47 | Important for this authorization method to work, is to set the static property `RetrieveAuthenticationSecret` to a `Func>`. This can be seen in the following example. 48 | 49 | ```csharp 50 | DynamicEventGridAuthorizationAttribute.RetrieveAuthenticationSecret = () => Task.FromResult("my-secret-key"); 51 | ``` 52 | 53 | [← back](/) -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.3.0/02-Features/publishing-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Publishing Events" 3 | layout: default 4 | --- 5 | 6 | ## Publishing Events 7 | 8 | We provide support for publishing custom events to a custom Azure Event Grid Topics. 9 | 10 | Import the following namespace into your project: 11 | 12 | ```csharp 13 | using Arcus.EventGrid.Publishing; 14 | ``` 15 | 16 | Next, create an `EventGridPublisher` instance via the `EventGridPublisherBuilder` which requires the endpoint & authentication key of your custom topic endpoint. 17 | 18 | ```csharp 19 | var eventGridPublisher = EventGridPublisherBuilder 20 | .ForTopic(topicEndpoint) 21 | .UsingAuthenticationKey(endpointKey) 22 | .Build(); 23 | ``` 24 | **Publishing EventGridEvent's** 25 | 26 | Create your event that you want to publish 27 | 28 | ```csharp 29 | string licensePlate = "1-TOM-337"; 30 | string eventSubject = $"/cars/{licensePlate}"; 31 | string eventId = Guid.NewGuid().ToString(); 32 | var @event = new NewCarRegistered(eventId, eventSubject, licensePlate); 33 | 34 | await eventGridPublisher.Publish(@event); 35 | ``` 36 | 37 | Alternatively you can publish a list of events by using 38 | 39 | ```csharp 40 | await eventGridPublisher.PublishMany(events); 41 | ``` 42 | 43 | ### Resilient Publishing 44 | 45 | The `EventGridPublisherBuilder` also provides several ways to publish events in a resilient manner. Resilient meaning we support three ways to add resilience to your event publishing: 46 | 47 | - **Exponential retry**: makes the publishing resilient by retrying a specified number of times with exponential back off. 48 | 49 | ```csharp 50 | EventGridPublisherBuilder.ForTopic(topicEndpoint) 51 | .UsingAuthenticationKey(endpointKey) 52 | .WithExponentialRetry(retryCount) 53 | .Build(); 54 | ``` 55 | 56 | - **Circuit breaker**: makes the publishing resilient by breaking the circuit if the maximum specified number of exceptions are handled by the policy. The circuit will stay broken for a specified duration. Any attempt to execute the function while the circuit is broken will result in a `BrokenCircuitException`. 57 | 58 | ```csharp 59 | EventGridPublisherBuilder.ForTopic(topicEndpoint) 60 | .UsingAuthenticationKey(endpointKey) 61 | .WithCircuitBreaker(exceptionsBeforeBreaking, durationOfBreak) 62 | .Build(); 63 | ``` 64 | 65 | - Combination of the two: **Circuit breaker with/after exponential retry**. 66 | 67 | ```csharp 68 | EventGridPublisherBuilder.ForTopic(topicEndpoint) 69 | .UsingAuthenticationKey(endpointKey) 70 | .WithExponentialRetry(retryCount) 71 | .WithCircuitBreaker(exceptionsBeforeBreaking, durationOfBreak) 72 | .Build(); 73 | ``` 74 | 75 | [← back](/) 76 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.4.0/01-index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Arcus Event Grid" 3 | layout: default 4 | slug: / 5 | sidebar_label: Welcome 6 | --- 7 | 8 | [![NuGet Badge](https://buildstats.info/nuget/Arcus.EventGrid.All?packageVersion=2.4.0)](https://www.nuget.org/packages/Arcus.EventGrid.All/) 9 | 10 | # Installation 11 | 12 | ```shell 13 | PM > Install-Package Arcus.EventGrid.All 14 | ``` 15 | 16 | # Features 17 | 18 | - Support for publishing events to an Event Grid Topic ([docs](./02-Features/publishing-events.md)) 19 | - Support for handling endpoint validation handshake ([docs](./02-Features/endpoint-validation.md)) 20 | - Provides event contracts for a subset of Azure services ([docs](./02-Features/azure-event-contracts.md)) 21 | - Provide tooling for writing integration tests ([docs](./02-Features/running-integration-tests.md)) 22 | - Support for deserializing events ([docs](./02-Features/deserializing-events.md)) 23 | - Support for creating your own events 24 | 25 | # License 26 | This is licensed under The MIT License (MIT). Which means that you can use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the web application. But you always need to state that Codit is the original author of this web application. 27 | 28 | *[Full license here](https://github.com/arcus-azure/arcus.eventgrid/blob/master/LICENSE)* 29 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.4.0/02-Features/azure-event-contracts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Supported Azure Event Contracts" 3 | layout: default 4 | --- 5 | 6 | ## Supported Azure Event Contracts 7 | 8 | Currently we provide support for the following Azure events: 9 | - **Azure Storage** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-blob-storage)) 10 | - `Microsoft.Storage.BlobCreated` 11 | - **Azure Event Hubs** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-event-hubs)) 12 | - `Microsoft.EventHub.CaptureFileCreated` 13 | - **Azure IoT Hub** ([docs](https://docs.microsoft.com/en-us/azure/event-grid/event-schema-iot-hub)) 14 | - `Microsoft.Devices.DeviceCreated` 15 | - `Microsoft.Devices.DeviceDeleted` 16 | 17 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.4.0/02-Features/deserializing-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Deserializing Events" 3 | layout: default 4 | --- 5 | 6 | ## Deserializing Events 7 | 8 | The `Arcus.EventGrid` package provides several ways to deserializing events. 9 | 10 | Following paragraphs describe each supported way to deserialize an event. 11 | 12 | - [Deserializing Events](#deserializing-events) 13 | - [Deserializing Custom Events](#deserializing-custom-events) 14 | 15 | ### Deserializing Custom Events 16 | 17 | We provide support for deserializing events to typed event objects where the custom event payload is available via the `.GetPayload()` method. 18 | 19 | If you want to have the original raw JSON event payload, you can get it via the `.Data` property. 20 | 21 | ```csharp 22 | using Arcus.EventGrid; 23 | using Arcus.EventGrid.Parsers; 24 | 25 | // Parse from your custom event implementation with the `.Parse<>` function. 26 | EventGridMessage eventGridBatch = EventGridParser.Parse(rawEvent); 27 | 28 | // The event data type will be wrapped inside an `EventGridMessage<>` instance. 29 | NewCarRegistered eventGridMessage = eventGridBatch.Events.First(); 30 | 31 | // The original event payload can now be accessed. 32 | CarEventData eventPayload = eventGridMessage.Data; 33 | ``` 34 | 35 | [← back](/) 36 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.4.0/02-Features/endpoint-validation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Endpoint validation" 3 | layout: default 4 | --- 5 | 6 | ## Endpoint validation 7 | 8 | We provide support for endpoint validation, when implementing your own custom web hook. This validation allows to secure your web hook with a secret key (taken from the query string or an HTTP header). This is required, because Azure Event Grid sends a validation request to a newly configured web hook, in order to prevent people leveraging Azure Event Grid to bring down a 3rd party API. The implementation we provide, is echoing back the validation key on your operation, in order to have the validation by Event Grid out of the box. 9 | 10 | Import the following namespace into your project: 11 | ```csharp 12 | using Arcus.EventGrid.Security; 13 | using Arcus.EventGrid.Security.Attributes; 14 | ``` 15 | 16 | Next, tag the Operation that will be handling the Event Grid events with the `EventGridSubscriptionValidator` and the `EventGridAuthorization` attributes, that will secure the endpoint and handle the handshake. 17 | ```csharp 18 | [EventGridSubscriptionValidator] 19 | [EventGridAuthorization("x-api-key", "event-grid")] 20 | public IHttpActionResult HandleEvents(HttpRequestMessage message) 21 | { 22 | return Ok(); 23 | } 24 | ``` 25 | 26 | ### Configuring Authorization with attributes 27 | There are 2 attributes available to secure operations: 28 | - The `EventGridAuthorization` has a hard-coded secret key and is only advised for demonstration or testing purposes. 29 | - The `DynamicEventGridAuthorizationAttribute` allows developer to specify a static `Func` with name `RetrieveAuthenticationSecret` to implement custom logic to retrieve the actual secret key (for example from Azure KeyVault, web.config or appsettings.json) 30 | 31 | These attributes will only allow an operation to be called, if the configured secret key value is found in the HTTP header or the Query String with the configured key name. 32 | 33 | #### The EventGridAuthorization attribute 34 | This attribute has the following public constructor. This constructor sets the header or query string name and the hard coded secret value. 35 | 36 | ```csharp 37 | [EventGridAuthorization("keyName", "keyValue")] 38 | ``` 39 | 40 | #### The DynamicEventGridAuthorization attribute 41 | This attribute has the following public constructors. This constructor sets the header or query string name to the provided value (or defaults to 'x-api-key' for the default constructor). 42 | 43 | ```csharp 44 | [DynamicEventGridAuthorizationAttribute()] 45 | [DynamicEventGridAuthorizationAttribute("custom-key-name")] 46 | ``` 47 | Important for this authorization method to work, is to set the static property `RetrieveAuthenticationSecret` to a `Func>`. This can be seen in the following example. 48 | 49 | ```csharp 50 | DynamicEventGridAuthorizationAttribute.RetrieveAuthenticationSecret = () => Task.FromResult("my-secret-key"); 51 | ``` 52 | 53 | [← back](/) -------------------------------------------------------------------------------- /docs/versioned_docs/version-v2.4.0/02-Features/publishing-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Publishing Events" 3 | layout: default 4 | --- 5 | 6 | ## Publishing Events 7 | 8 | We provide support for publishing custom events to a custom Azure Event Grid Topics. 9 | 10 | Import the following namespace into your project: 11 | 12 | ```csharp 13 | using Arcus.EventGrid.Publishing; 14 | ``` 15 | 16 | Next, create an `EventGridPublisher` instance via the `EventGridPublisherBuilder` which requires the endpoint & authentication key of your custom topic endpoint. 17 | 18 | ```csharp 19 | var eventGridPublisher = EventGridPublisherBuilder 20 | .ForTopic(topicEndpoint) 21 | .UsingAuthenticationKey(endpointKey) 22 | .Build(); 23 | ``` 24 | **Publishing EventGridEvent's** 25 | 26 | Create your event that you want to publish 27 | 28 | ```csharp 29 | string licensePlate = "1-TOM-337"; 30 | string eventSubject = $"/cars/{licensePlate}"; 31 | string eventId = Guid.NewGuid().ToString(); 32 | var @event = new NewCarRegistered(eventId, eventSubject, licensePlate); 33 | 34 | await eventGridPublisher.Publish(@event); 35 | ``` 36 | 37 | Alternatively you can publish a list of events by using 38 | 39 | ```csharp 40 | await eventGridPublisher.PublishMany(events); 41 | ``` 42 | 43 | ### Resilient Publishing 44 | 45 | The `EventGridPublisherBuilder` also provides several ways to publish events in a resilient manner. Resilient meaning we support three ways to add resilience to your event publishing: 46 | 47 | - **Exponential retry**: makes the publishing resilient by retrying a specified number of times with exponential backoff. 48 | 49 | ```csharp 50 | EventGridPublisherBuilder.ForTopic(topicEndpoint) 51 | .UsingAuthenticationKey(endpointKey) 52 | .WithExponentialRetry(retryCount) 53 | .Build(); 54 | ``` 55 | 56 | - **Circuit breaker**: makes the publishing resilient by breaking the circuit if the maximum specified number of exceptions are handled by the policy. The circuit will stay broken for a specified duration. Any attempt to execute the function while the circuit is broken will result in a `BrokenCircuitException`. 57 | 58 | ```csharp 59 | EventGridPublisherBuilder.ForTopic(topicEndpoint) 60 | .UsingAuthenticationKey(endpointKey) 61 | .WithCircuitBreaker(exceptionsBeforeBreaking, durationOfBreak) 62 | .Build(); 63 | ``` 64 | 65 | - Combination of the two: **Circuit breaker with/after exponential retry**. 66 | 67 | ```csharp 68 | EventGridPublisherBuilder.ForTopic(topicEndpoint) 69 | .UsingAuthenticationKey(endpointKey) 70 | .WithExponentialRetry(retryCount) 71 | .WithCircuitBreaker(exceptionsBeforeBreaking, durationOfBreak) 72 | .Build(); 73 | ``` 74 | 75 | [← back](/) 76 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v3.0.0/01-index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Arcus Event Grid" 3 | layout: default 4 | slug: / 5 | sidebar_label: Welcome 6 | --- 7 | 8 | [![NuGet Badge](https://buildstats.info/nuget/Arcus.EventGrid.All?packageVersion=3.0.0)](https://www.nuget.org/packages/Arcus.EventGrid.All/) 9 | 10 | # Installation 11 | 12 | ```shell 13 | PM > Install-Package Arcus.EventGrid.All 14 | ``` 15 | 16 | # Features 17 | 18 | - Support for publishing events to an Event Grid Topic ([docs](./02-Features/publishing-events.md)) 19 | - Support for handling endpoint validation handshake ([docs](./02-Features/endpoint-validation.md)) 20 | - Provide tooling for writing integration tests ([docs](./02-Features/running-integration-tests.md)) 21 | - Support for deserializing official Azure or custom events according to Event Grid & CloudEvent schema ([docs](./02-Features/deserializing-events.md)) 22 | - Support for creating your own events ([docs](./02-Features/create-custom-events.md)) 23 | 24 | # License 25 | This is licensed under The MIT License (MIT). Which means that you can use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the web application. But you always need to state that Codit is the original author of this web application. 26 | 27 | *[Full license here](https://github.com/arcus-azure/arcus.eventgrid/blob/master/LICENSE)* 28 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v3.0.0/02-Features/create-custom-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Create custom events" 3 | layout: default 4 | --- 5 | 6 | ## Create Custom Events 7 | 8 | We allow you to create custom events next to the [official Azure SDK event schemas](https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.eventgrid.models?view=azure-dotnet). 9 | 10 | The official SDK provides a class called `EventGridEvent` which provides your event data as an ordinary .NET `object`. 11 | We provide a variation of the official `EventGridEvent` which provides your data as a typed instance instead. 12 | 13 | This makes sure that your new custom events are both type-safe and are supported by any official functions that use the official `EventGridEvent`. 14 | 15 | ```csharp 16 | using Arcus.EventGrid.Contracts; 17 | using Newtonsoft.Json; 18 | 19 | public class CarEventData 20 | { 21 | public CarEventData(string licensePlate) 22 | { 23 | LicensePlate = licensePlate; 24 | } 25 | 26 | public string LicensePlate { get; } 27 | } 28 | 29 | public class NewCarRegistered : EventGridEvent 30 | { 31 | private const string DefaultDataVersion = "1", 32 | DefaultEventType = "Arcus.Samples.Cars.NewCarRegistered"; 33 | 34 | // `JsonConstructor` attribute is not necessary but can help as documentation for the event. 35 | [JsonConstructor] 36 | private NewCarRegistered() 37 | { 38 | } 39 | 40 | public NewCarRegistered(string id, string licensePlate) : this(id, "New registered car", licensePlate) 41 | { 42 | } 43 | 44 | public NewCarRegistered(string id, string subject, string licensePlate) 45 | : base(id, subject, new CarEventData(licensePlate), DefaultDataVersion, DefaultEventType) 46 | { 47 | } 48 | } 49 | ``` 50 | 51 | Read ["Deserializing Events"](./deserializing-events.md) for information on how custom events are deserialized. 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v3.0.0/02-Features/endpoint-validation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Endpoint validation" 3 | layout: default 4 | --- 5 | 6 | ## Endpoint validation 7 | 8 | We provide support for endpoint validation, when implementing your own custom web hook. This validation allows to secure your web hook with a secret key (taken from the query string or an HTTP header). This is required, because Azure Event Grid sends a validation request to a newly configured web hook, in order to prevent people leveraging Azure Event Grid to bring down a 3rd party API. The implementation we provide, is echoing back the validation key on your operation, in order to have the validation by Event Grid out of the box. 9 | 10 | Import the following namespace into your project: 11 | ```csharp 12 | using Arcus.EventGrid.Security; 13 | using Arcus.EventGrid.Security.Attributes; 14 | ``` 15 | 16 | Next, tag the Operation that will be handling the Event Grid events with the `EventGridSubscriptionValidator` and the `EventGridAuthorization` attributes, that will secure the endpoint and handle the handshake. 17 | ```csharp 18 | [EventGridSubscriptionValidator] 19 | [EventGridAuthorization("x-api-key", "event-grid")] 20 | public IHttpActionResult HandleEvents(HttpRequestMessage message) 21 | { 22 | return Ok(); 23 | } 24 | ``` 25 | 26 | ### Configuring Authorization with attributes 27 | There are 2 attributes available to secure operations: 28 | - The `EventGridAuthorization` has a hard-coded secret key and is only advised for demonstration or testing purposes. 29 | - The `DynamicEventGridAuthorizationAttribute` allows developer to specify a static `Func` with name `RetrieveAuthenticationSecret` to implement custom logic to retrieve the actual secret key (for example from Azure KeyVault, web.config or appsettings.json) 30 | 31 | These attributes will only allow an operation to be called, if the configured secret key value is found in the HTTP header or the Query String with the configured key name. 32 | 33 | #### The EventGridAuthorization attribute 34 | This attribute has the following public constructor. This constructor sets the header or query string name and the hard coded secret value. 35 | 36 | ```csharp 37 | [EventGridAuthorization("keyName", "keyValue")] 38 | ``` 39 | 40 | #### The DynamicEventGridAuthorization attribute 41 | This attribute has the following public constructors. This constructor sets the header or query string name to the provided value (or defaults to 'x-api-key' for the default constructor). 42 | 43 | ```csharp 44 | [DynamicEventGridAuthorizationAttribute()] 45 | [DynamicEventGridAuthorizationAttribute("custom-key-name")] 46 | ``` 47 | Important for this authorization method to work, is to set the static property `RetrieveAuthenticationSecret` to a `Func>`. This can be seen in the following example. 48 | 49 | ```csharp 50 | DynamicEventGridAuthorizationAttribute.RetrieveAuthenticationSecret = () => Task.FromResult("my-secret-key"); 51 | ``` 52 | 53 | [← back](/) -------------------------------------------------------------------------------- /docs/versioned_docs/version-v3.2.0/01-index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Arcus Event Grid" 3 | layout: default 4 | slug: / 5 | sidebar_label: Welcome 6 | --- 7 | 8 | # Installation 9 | 10 | ```shell 11 | PM > Install-Package Arcus.EventGrid.All 12 | ``` 13 | 14 | # Features 15 | 16 | - Support for publishing events to an Event Grid Topic ([docs](./02-Features/publishing-events.md)) 17 | - Support for handling endpoint validation handshake ([docs](./02-Features/endpoint-validation.md)) 18 | - Provide tooling for writing integration tests ([docs](./02-Features/running-integration-tests.md)) 19 | - Support for deserializing official Azure or custom events according to Event Grid & CloudEvent schema ([docs](./02-Features/deserializing-events.md)) 20 | - Support for creating your own events ([docs](./02-Features/create-custom-events.md)) 21 | 22 | # License 23 | This is licensed under The MIT License (MIT). Which means that you can use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the web application. But you always need to state that Codit is the original author of this web application. 24 | 25 | *[Full license here](https://github.com/arcus-azure/arcus.eventgrid/blob/master/LICENSE)* 26 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v3.2.0/02-Features/create-custom-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Create custom events" 3 | layout: default 4 | --- 5 | 6 | ## Create Custom Events 7 | 8 | We allow you to create custom events next to the [official Azure SDK event schemas](https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.eventgrid.models?view=azure-dotnet). 9 | 10 | The official SDK provides a class called `EventGridEvent` which provides your event data as an ordinary .NET `object`. 11 | We provide a variation of the official `EventGridEvent` which provides your data as a typed instance instead. 12 | 13 | This makes sure that your new custom events are both type-safe and are supported by any official functions that use the official `EventGridEvent`. 14 | 15 | ```csharp 16 | using Arcus.EventGrid.Contracts; 17 | using Newtonsoft.Json; 18 | 19 | public class CarEventData 20 | { 21 | public CarEventData(string licensePlate) 22 | { 23 | LicensePlate = licensePlate; 24 | } 25 | 26 | public string LicensePlate { get; } 27 | } 28 | 29 | public class NewCarRegistered : EventGridEvent 30 | { 31 | private const string DefaultDataVersion = "1", 32 | DefaultEventType = "Arcus.Samples.Cars.NewCarRegistered"; 33 | 34 | // `JsonConstructor` attribute is not necessary but can help as documentation for the event. 35 | [JsonConstructor] 36 | private NewCarRegistered() 37 | { 38 | } 39 | 40 | public NewCarRegistered(string id, string licensePlate) : this(id, "New registered car", licensePlate) 41 | { 42 | } 43 | 44 | public NewCarRegistered(string id, string subject, string licensePlate) 45 | : base(id, subject, new CarEventData(licensePlate), DefaultDataVersion, DefaultEventType) 46 | { 47 | } 48 | } 49 | ``` 50 | 51 | Read ["Deserializing Events"](./deserializing-events.md) for information on how custom events are deserialized. 52 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v3.2.0/02-Features/deserializing-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Deserializing Events" 3 | layout: default 4 | --- 5 | 6 | ## Deserializing Events 7 | 8 | The `Arcus.EventGrid` package provides several ways to deserializing events. 9 | 10 | Following paragraphs describe each supported way to deserialize an event. 11 | 12 | - [Deserializing Events](#deserializing-events) 13 | - [Deserializing Built-In Azure Events](#deserializing-built-in-azure-events) 14 | - [Deserializing CloudEvent Events](#deserializing-cloudevent-events) 15 | - [Deserializing Event Grid Events](#deserializing-event-grid-events) 16 | - [Deserializing Custom Events](#deserializing-custom-events) 17 | 18 | ### Deserializing Built-In Azure Events 19 | 20 | When using official Azure events, you can use `.ParseFromData<>` to deserialize then those based on the built-in types as shown in the example: 21 | 22 | ```csharp 23 | using Arcus.EventGrid; 24 | using Arcus.EventGrid.Parsers; 25 | using Microsoft.Azure.EventGrid.Models; 26 | 27 | // Parse directly from an event data type with the `.Parse` function. 28 | byte[] rawEvent = ... 29 | EventBatch eventBatch = EventParser.Parse(rawEvent); 30 | 31 | // The type `EventGridEvent` comes directly from the official SDK package 32 | // and can be cast implicitly like so, 33 | EventGridEvent eventGridEvent = eventBatch.Events.Single(); 34 | 35 | // Or explicitly. 36 | EventGridEvent eventGridEvent = eventBatch.Events.Single().AsEventGridEvent(); 37 | 38 | // The actual EventGrid payload can be retrieved by passing along the Azure SDK model type. 39 | var storageEventData = eventGridEvent.GetPayload(); 40 | ``` 41 | 42 | You can find a list of supported built-in Azure events [in the official documentation](https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.eventgrid.models?view=azure-dotnet). 43 | 44 | ### Deserializing CloudEvent Events 45 | 46 | We provide support for deserializing CloudEvents using the [official SDK for C#](https://github.com/cloudevents/sdk-csharp). 47 | 48 | Upon receiving of CloudEvent events: 49 | 50 | ```csharp 51 | using Arcus.EventGrid; 52 | using Arcus.EventGrid.Parsers; 53 | using CloudNative.CloudEvents; 54 | 55 | string cloudEventJson = ... 56 | EventBatch eventBatch = EventParser.Parse(cloudEventJson); 57 | var events = eventBatch.Events; 58 | 59 | // The type `CloudEvent` comes directly from the official SDK package 60 | // and can be cast implicitly like so, 61 | CloudEvent cloudEvent = events.First(); 62 | 63 | // Or explicitly. 64 | CloudEvent cloudEvent = events.First().AsCloudEvent(); 65 | ``` 66 | 67 | ### Deserializing Event Grid Events 68 | 69 | We provide support for deserializing [EventGrid events](https://docs.microsoft.com/en-us/azure/event-grid/event-schema). 70 | 71 | ```csharp 72 | using Arcus.EventGrid; 73 | using Arcus.EventGrid.Parsers; 74 | using Microsoft.Azure.EventGrid.Models; 75 | 76 | string eventGridEventJson = ... 77 | EventBatch eventBatch = EventParser.Parse(eventGridEventJson); 78 | var events = eventBatch.Events; 79 | 80 | // The `EventGridEvent` can be cast implicitly like so, 81 | EventGridEvent eventGridEvent = events.First(); 82 | 83 | // Or explicitly. 84 | EventGridEvent eventGridEvent = events.First().AsEventGridEvent(); 85 | ``` 86 | 87 | ### Deserializing Custom Events 88 | 89 | We provide support for deserializing events to typed event objects where the custom event payload is available via the `.GetPayload()` method. 90 | 91 | If you want to have the original raw JSON event payload, you can get it via the `.Data` property. 92 | 93 | ```csharp 94 | using Arcus.EventGrid; 95 | using Arcus.EventGrid.Parsers; 96 | 97 | // Parse from your custom event implementation with the `.Parse<>` function. 98 | EventGridBatch eventGridBatch = EventGridParser.Parse(rawEvent); 99 | 100 | // The event data type will be wrapped inside an `EventGridEvent<>` instance. 101 | NewCarRegistered eventGridMessage = eventGridBatch.Events.First(); 102 | 103 | // The original event payload can now be accessed. 104 | CarEventData typedEventPayload = eventGridMessage.GetPayload(); 105 | object untypedEventPayload = eventGridMessage.Data; 106 | ``` 107 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v3.3.0/01-index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Arcus Event Grid" 3 | layout: default 4 | slug: / 5 | sidebar_label: Welcome 6 | --- 7 | 8 | # Introduction 9 | 10 | Arcus EventGrid builds on top of Microsoft technology to provide the user with transient publishing and safely registering event publishing to your application with the [Arcus secret store](https://security.arcus-azure.net/features/secret-store). EventGrid is often used in integration tests, so we made sure that retrieving events is easy, transient, and customizable. 11 | 12 | # Installation 13 | 14 | ```shell 15 | PM > Install-Package Arcus.EventGrid.Core 16 | ``` 17 | 18 | # License 19 | This is licensed under The MIT License (MIT). Which means that you can use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the web application. But you always need to state that Codit is the original author of this web application. 20 | 21 | *[Full license here](https://github.com/arcus-azure/arcus.eventgrid/blob/master/LICENSE)* 22 | -------------------------------------------------------------------------------- /docs/versioned_docs/version-v3.3.0/02-Features/create-custom-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Create custom events" 3 | layout: default 4 | --- 5 | 6 | ## Create Custom Events 7 | 8 | > ❌ The `Arcus.EventGrid` package is deprecated and will be removed in v4. 9 | 10 | Starting from v3.3, we use fully the Azure SDK to send events to Azure Event Grid. See [their documentation](https://learn.microsoft.com/en-us/dotnet/api/overview/azure/messaging.eventgrid-readme?source=recommendations&view=azure-dotnet) to learn more about publishing custom events. -------------------------------------------------------------------------------- /docs/versioned_sidebars/version-v1.0.0-sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "version-v1.0.0/tutorialSidebar": [ 3 | { 4 | "type": "autogenerated", 5 | "dirName": "." 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /docs/versioned_sidebars/version-v1.0.1-sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "version-v1.0.1/tutorialSidebar": [ 3 | { 4 | "type": "autogenerated", 5 | "dirName": "." 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /docs/versioned_sidebars/version-v1.0.2-sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "version-v1.0.2/tutorialSidebar": [ 3 | { 4 | "type": "autogenerated", 5 | "dirName": "." 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /docs/versioned_sidebars/version-v1.1.0-sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "version-v1.1.0/tutorialSidebar": [ 3 | { 4 | "type": "autogenerated", 5 | "dirName": "." 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /docs/versioned_sidebars/version-v2.0.0-sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "version-v2.0.0/tutorialSidebar": [ 3 | { 4 | "type": "autogenerated", 5 | "dirName": "." 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /docs/versioned_sidebars/version-v2.1.0-sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "version-v2.1.0/tutorialSidebar": [ 3 | { 4 | "type": "autogenerated", 5 | "dirName": "." 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /docs/versioned_sidebars/version-v2.2.0-sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "version-v2.2.0/tutorialSidebar": [ 3 | { 4 | "type": "autogenerated", 5 | "dirName": "." 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /docs/versioned_sidebars/version-v2.3.0-sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "version-v2.3.0/tutorialSidebar": [ 3 | { 4 | "type": "autogenerated", 5 | "dirName": "." 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /docs/versioned_sidebars/version-v2.4.0-sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "version-v2.4.0/tutorialSidebar": [ 3 | { 4 | "type": "autogenerated", 5 | "dirName": "." 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /docs/versioned_sidebars/version-v3.0.0-sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "version-v3.0.0/tutorialSidebar": [ 3 | { 4 | "type": "autogenerated", 5 | "dirName": "." 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /docs/versioned_sidebars/version-v3.2.0-sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "version-v3.2.0/tutorialSidebar": [ 3 | { 4 | "type": "autogenerated", 5 | "dirName": "." 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /docs/versioned_sidebars/version-v3.3.0-sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "version-v3.3.0/tutorialSidebar": [ 3 | { 4 | "type": "autogenerated", 5 | "dirName": "." 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /docs/versions.json: -------------------------------------------------------------------------------- 1 | [ 2 | "v3.3.0", 3 | "v3.2.0", 4 | "v3.0.0", 5 | "v2.4.0", 6 | "v2.3.0", 7 | "v2.2.0", 8 | "v2.1.0", 9 | "v2.0.0", 10 | "v1.1.0", 11 | "v1.0.2", 12 | "v1.0.1", 13 | "v1.0.0" 14 | ] 15 | -------------------------------------------------------------------------------- /media/fonts/Exo2-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/media/fonts/Exo2-Black.ttf -------------------------------------------------------------------------------- /media/fonts/Exo2-BlackItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/media/fonts/Exo2-BlackItalic.ttf -------------------------------------------------------------------------------- /media/fonts/Exo2-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/media/fonts/Exo2-Bold.ttf -------------------------------------------------------------------------------- /media/fonts/Exo2-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/media/fonts/Exo2-BoldItalic.ttf -------------------------------------------------------------------------------- /media/fonts/Exo2-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/media/fonts/Exo2-ExtraBold.ttf -------------------------------------------------------------------------------- /media/fonts/Exo2-ExtraBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/media/fonts/Exo2-ExtraBoldItalic.ttf -------------------------------------------------------------------------------- /media/fonts/Exo2-ExtraLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/media/fonts/Exo2-ExtraLight.ttf -------------------------------------------------------------------------------- /media/fonts/Exo2-ExtraLightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/media/fonts/Exo2-ExtraLightItalic.ttf -------------------------------------------------------------------------------- /media/fonts/Exo2-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/media/fonts/Exo2-Italic.ttf -------------------------------------------------------------------------------- /media/fonts/Exo2-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/media/fonts/Exo2-Light.ttf -------------------------------------------------------------------------------- /media/fonts/Exo2-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/media/fonts/Exo2-LightItalic.ttf -------------------------------------------------------------------------------- /media/fonts/Exo2-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/media/fonts/Exo2-Medium.ttf -------------------------------------------------------------------------------- /media/fonts/Exo2-MediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/media/fonts/Exo2-MediumItalic.ttf -------------------------------------------------------------------------------- /media/fonts/Exo2-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/media/fonts/Exo2-Regular.ttf -------------------------------------------------------------------------------- /media/fonts/Exo2-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/media/fonts/Exo2-SemiBold.ttf -------------------------------------------------------------------------------- /media/fonts/Exo2-SemiBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/media/fonts/Exo2-SemiBoldItalic.ttf -------------------------------------------------------------------------------- /media/fonts/Exo2-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/media/fonts/Exo2-Thin.ttf -------------------------------------------------------------------------------- /media/fonts/Exo2-ThinItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/media/fonts/Exo2-ThinItalic.ttf -------------------------------------------------------------------------------- /media/logo/arcus-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/media/logo/arcus-logo.png -------------------------------------------------------------------------------- /media/logo/arcus-logo.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/media/logo/arcus-logo.pub -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [Settings] 2 | # Added automatically by the Netlify CLI. It has no effect during normal 3 | # Git-backed deploys. 4 | ID = "c1ddb1e6-972b-4368-aea8-0eee9c959996" 5 | 6 | # Settings in the [build] context are global and are applied to all contexts 7 | # unless otherwise overridden by more specific contexts. 8 | [build] 9 | # Directory to change to before starting a build. 10 | # This is where we will look for package.json/.nvmrc/etc. 11 | base = "docs" 12 | 13 | # Directory (relative to root of your repo) that contains the deploy-ready 14 | # HTML files and assets generated by the build. 15 | publish = "build" 16 | 17 | # Default build command. 18 | command = "npm run build" 19 | 20 | # Directory with the lambda functions to deploy to AWS. 21 | # functions = "project/functions/" 22 | 23 | [build.environment] 24 | NODE_VERSION = "16.2.0" 25 | 26 | # Production context: all deploys from the Production branch set in your site's 27 | # deploy settings will inherit these settings. 28 | # [context.production] 29 | # publish = "output/" 30 | # command = "make publish" 31 | # environment = { ACCESS_TOKEN = "super secret", NODE_ENV = "8.0.1" } 32 | 33 | # Deploy Preview context: all deploys resulting from a pull/merge request will 34 | # inherit these settings. 35 | # [context.deploy-preview] 36 | # publish = "dist/" 37 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Core/Arcus.EventGrid.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0;net6.0;netstandard2.1 5 | Arcus 6 | Arcus 7 | https://eventgrid.arcus-azure.net/ 8 | https://github.com/arcus-azure/arcus.eventgrid 9 | LICENSE 10 | icon.png 11 | README.md 12 | Azure;Event Grid 13 | Copyright (c) Arcus 14 | Provides core capabilities for using Event Grid with Arcus 15 | true 16 | true 17 | true 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Core/EventCorrelationFormat.cs: -------------------------------------------------------------------------------- 1 | namespace Arcus.EventGrid.Core 2 | { 3 | /// 4 | /// Represents the event correlation format of the send-out events. 5 | /// 6 | public enum EventCorrelationFormat 7 | { 8 | /// 9 | /// Uses the W3C event correlation system with traceparent and tracestate to represent parent-child relationship. 10 | /// 11 | W3C, 12 | 13 | /// 14 | /// Uses the hierarchical event correlation system with Root-Id and Request-Id to represent parent-child relationship. 15 | /// 16 | Hierarchical 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Security.AzureFunctions/Arcus.EventGrid.Security.AzureFunctions.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0;net6.0 5 | Copyright (c) Arcus 6 | https://eventgrid.arcus-azure.net/ 7 | https://github.com/arcus-azure/arcus.eventgrid 8 | README.md 9 | LICENSE 10 | icon.png 11 | Azure;Event Grid 12 | Arcus 13 | Provides security capabilities to simplify the authentication and endpoint handshake for Azure Event Grid in Azure Functions 14 | true 15 | true 16 | true 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Security.AzureFunctions/Extensions/IFunctionsHostBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Arcus.EventGrid.Security.Core.Validation; 3 | using GuardNet; 4 | using Microsoft.Extensions.DependencyInjection; 5 | 6 | // ReSharper disable once CheckNamespace 7 | namespace Microsoft.Azure.Functions.Extensions.DependencyInjection 8 | { 9 | /// 10 | /// Extensions on the Azure Functions to add Azure EventGrid security related methods. 11 | /// 12 | // ReSharper disable once InconsistentNaming 13 | public static class IFunctionsHostBuilderExtensions 14 | { 15 | /// 16 | /// Adds an to the Azure Functions application services. 17 | /// 18 | /// The Azure Functions builder instance to add the Azure EventGrid subscription validation. 19 | /// Thrown when the is null. 20 | public static IFunctionsHostBuilder AddEventGridSubscriptionValidation(this IFunctionsHostBuilder builder) 21 | { 22 | Guard.NotNull(builder, nameof(builder), "Requires an Azure Functions host builder to add the Azure EventGrid subscription validation"); 23 | 24 | builder.Services.AddEventGridSubscriptionValidation(); 25 | return builder; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Security.Core/Arcus.EventGrid.Security.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0;net6.0 5 | Copyright (c) Arcus 6 | https://eventgrid.arcus-azure.net/ 7 | https://github.com/arcus-azure/arcus.eventgrid 8 | README.md 9 | LICENSE 10 | icon.png 11 | Azure;Event Grid 12 | Arcus 13 | Provides comon security capabilities to simplify the authentication and endpoint handshake for Azure Event Grid 14 | true 15 | true 16 | true 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Security.Core/Extensions/IServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Arcus.EventGrid.Security.Core.Validation; 3 | using GuardNet; 4 | 5 | // ReSharper disable once CheckNamespace 6 | namespace Microsoft.Extensions.DependencyInjection 7 | { 8 | /// 9 | /// Extensions on the application services related to Azure EventGrid security. 10 | /// 11 | // ReSharper disable once InconsistentNaming 12 | public static class IServiceCollectionExtensions 13 | { 14 | /// 15 | /// Add validation to the application services. 16 | /// 17 | /// The available registered services. 18 | /// Thrown when the is null. 19 | public static IServiceCollection AddEventGridSubscriptionValidation(this IServiceCollection services) 20 | { 21 | Guard.NotNull(services, nameof(services), "Requires a set of registered services to add the Azure EventGrid subscription validation"); 22 | 23 | services.AddSingleton(); 24 | return services; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Security.Core/Validation/IEventGridSubscriptionValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Microsoft.AspNetCore.Http; 4 | using Microsoft.AspNetCore.Mvc; 5 | 6 | namespace Arcus.EventGrid.Security.Core.Validation 7 | { 8 | /// 9 | /// Represents a validation on events on Azure EventGrid, wrapped as HTTP requests. 10 | /// 11 | public interface IEventGridSubscriptionValidator 12 | { 13 | /// 14 | /// CloudEvents validation handshake of the incoming HTTP . 15 | /// 16 | /// The incoming HTTP request that needs to be validated. 17 | /// 18 | /// An [OK] HTTP response that represents a successful result of the validation; [BadRequest] otherwise. 19 | /// 20 | /// Thrown when the is null. 21 | IActionResult ValidateCloudEventsHandshakeRequest(HttpRequest request); 22 | 23 | /// 24 | /// Azure EventGrid subscription event validation of the incoming HTTP . 25 | /// 26 | /// The incoming HTTP request that needs to be validated. 27 | /// 28 | /// An [OK] HTTP response that represents a successful result of the validation; [BadRequest] otherwise. 29 | /// 30 | /// Thrown when the is null. 31 | Task ValidateEventGridSubscriptionEventRequestAsync(HttpRequest request); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Security.WebApi/Arcus.EventGrid.Security.WebApi.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0;net6.0 5 | Copyright (c) Arcus 6 | https://eventgrid.arcus-azure.net/ 7 | https://github.com/arcus-azure/arcus.eventgrid 8 | README.md 9 | LICENSE 10 | icon.png 11 | Azure;Event Grid 12 | Arcus 13 | Provides capability to simplify the authentication and endpoint handshake for Azure Event Grid 14 | true 15 | true 16 | true 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Security.WebApi/EventGridAuthorizationAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GuardNet; 3 | using Microsoft.AspNetCore.Mvc; 4 | 5 | namespace Arcus.EventGrid.Security.WebApi 6 | { 7 | /// 8 | /// Represents an attribute to authorize HTTP requests using Azure Event Grid. 9 | /// 10 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] 11 | public class EventGridAuthorizationAttribute : TypeFilterAttribute 12 | { 13 | private readonly EventGridAuthorizationOptions _options; 14 | 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// 18 | /// The value indicating where the authorization secret should come from. 19 | /// The name of the that holds the authorization secret. 20 | /// The name of the stored secret which value should match the request header or query parameter. 21 | /// Thrown when the is blank. 22 | public EventGridAuthorizationAttribute(HttpRequestProperty property, string propertyName, string secretName) : base(typeof(EventGridAuthorizationFilter)) 23 | { 24 | Guard.NotNullOrWhitespace(propertyName, nameof(propertyName), "Requires a non-blank name for the request input"); 25 | Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank name for the secret"); 26 | Guard.For(() => !Enum.IsDefined(typeof(HttpRequestProperty), property), new ArgumentException("Requires the request input to be within the bounds of the enumeration", nameof(property))); 27 | 28 | _options = new EventGridAuthorizationOptions(); 29 | Arguments = new object[] {property, propertyName, secretName, _options}; 30 | } 31 | 32 | /// 33 | /// Gets or sets the flag indicating whether or not the Azure Event Grid authorization should emit security events during the authorization process. 34 | /// 35 | public bool EmitSecurityEvents 36 | { 37 | get => _options.EmitSecurityEvents; 38 | set => _options.EmitSecurityEvents = value; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Security.WebApi/EventGridAuthorizationOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Arcus.EventGrid.Security.WebApi 2 | { 3 | /// 4 | /// Represents the additional consumer-configurable options to influence the behavior of the Azure Event Grid authorization (). 5 | /// 6 | public class EventGridAuthorizationOptions 7 | { 8 | /// 9 | /// Gets or sets the flag indicating whether or not the Azure Event Grid authorization should emit security events during the authorization of the request. 10 | /// 11 | public bool EmitSecurityEvents { get; set; } = false; 12 | } 13 | } -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Security.WebApi/EventGridSubscriptionValidationAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace Arcus.EventGrid.Security.WebApi 5 | { 6 | /// 7 | /// Represents an attribute to validate Azure Event Grid subscription events. 8 | /// 9 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] 10 | public class EventGridSubscriptionValidationAttribute : TypeFilterAttribute 11 | { 12 | /// 13 | /// Initializes a new instance of the class. 14 | /// 15 | public EventGridSubscriptionValidationAttribute() : base(typeof(EventGridSubscriptionValidationActionFilter)) 16 | { 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Security.WebApi/HttpRequestProperty.cs: -------------------------------------------------------------------------------- 1 | namespace Arcus.EventGrid.Security.WebApi 2 | { 3 | /// 4 | /// Represents the available inputs for the to authorize the HTTP request using Azure Event Grid. 5 | /// 6 | public enum HttpRequestProperty 7 | { 8 | /// 9 | /// Uses the HTTP request header to find the authorization secret. 10 | /// 11 | Header = 1, 12 | 13 | /// 14 | /// Uses the HTTP request query parameter to find the authorization secret. 15 | /// 16 | Query = 2 17 | } 18 | } -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Security/Arcus.EventGrid.Security.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0;netstandard2.1;netcoreapp3.1 5 | true 6 | Arcus.EventGrid.snk 7 | Copyright (c) Arcus 8 | https://github.com/arcus-azure/arcus.eventgrid/blob/master/LICENSE 9 | https://github.com/arcus-azure/arcus.eventgrid 10 | https://raw.githubusercontent.com/arcus-azure/arcus/master/media/arcus.png 11 | Azure;Event Grid 12 | Arcus 13 | Provides capability to simplify the authentication and endpoint handshake for Azure Event Grid 14 | true 15 | true 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Security/Arcus.EventGrid.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcus-azure/arcus.eventgrid/a8315a437806f1e51d68abc13ae6948ec90b07b3/src/Arcus.EventGrid.Security/Arcus.EventGrid.snk -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Security/Attributes/DynamicEventGridAuthorizationAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace Arcus.EventGrid.Security.Attributes 5 | { 6 | [Obsolete("Use the 'Arcus.EventGrid.WebApi.Security' package instead where the secret store is used to set the secret")] 7 | public class DynamicEventGridAuthorizationAttribute : EventGridAuthorizationAttribute 8 | { 9 | public static Func> RetrieveAuthenticationSecret { private get; set; } 10 | 11 | /// 12 | /// Attribute that leverages authentication validation for api operations via query string or HTTP headers 13 | /// 14 | public DynamicEventGridAuthorizationAttribute(string authenticationKeyName = "x-api-key") : base(authenticationKeyName) 15 | { 16 | } 17 | 18 | protected override async Task GetAuthenticationSecret() 19 | { 20 | // TODO: Add validation that the func is there 21 | 22 | var authenticationKey = await RetrieveAuthenticationSecret(); 23 | return authenticationKey; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Security/EventGridSubscriptionValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Net; 4 | using System.Net.Http; 5 | using System.Net.Http.Formatting; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | using System.Web.Http.Controllers; 9 | using System.Web.Http.Filters; 10 | using Arcus.EventGrid.Parsers; 11 | using Microsoft.Azure.EventGrid.Models; 12 | 13 | namespace Arcus.EventGrid.Security 14 | { 15 | /// 16 | /// 17 | /// Event grid web hook validation attribute 18 | /// 19 | [Obsolete("Use the 'Arcus.EventGrid.WebApi.Security' package instead where Azure EventGrid subscription validation happens via an attribute on class and/or operation level")] 20 | public class EventGridSubscriptionValidator : ActionFilterAttribute 21 | { 22 | /// 23 | /// Occurs before the action method is invoked. 24 | /// 25 | public override async Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken) 26 | { 27 | try 28 | { 29 | // This action only has to be executed, when the incoming contains a Header Aeg-Event-Type with value SubscriptionValidation 30 | if (actionContext.Request.Headers.TryGetValues(name: "Aeg-Event-Type", values: out var headerValues)) 31 | { 32 | //TODO : add logging 33 | //Log.Logger.Information("Subscription validation message received by Action Filter"); 34 | if (headerValues.Contains(value: "SubscriptionValidation")) 35 | { 36 | var subscriptionValidationResponse = await HandleSubscriptionValidationEventAsync(actionContext); 37 | if (subscriptionValidationResponse != null) 38 | { 39 | actionContext.Response = subscriptionValidationResponse; 40 | return; 41 | } 42 | } 43 | } 44 | 45 | // When arriving here, the message was not a validation message, so let it handle by the pipeline 46 | await base.OnActionExecutingAsync(actionContext, cancellationToken); 47 | } 48 | catch (Exception) 49 | { 50 | //TODO : add logging 51 | //Log.Logger.Error(e, "error in filter"); 52 | await base.OnActionExecutingAsync(actionContext, cancellationToken); 53 | } 54 | } 55 | 56 | private async Task HandleSubscriptionValidationEventAsync(HttpActionContext actionContext) 57 | { 58 | // Parsing the incoming message to a typed EventGrid message 59 | var rawRequest = await actionContext.Request.Content.ReadAsStringAsync(); 60 | var gridMessage = EventGridParser.ParseFromData(rawRequest); 61 | 62 | if (gridMessage.Events == null || gridMessage.Events.Any() == false) 63 | { 64 | throw new Exception(message: "No subscription events were found"); 65 | } 66 | 67 | if (gridMessage.Events.Count > 1) 68 | { 69 | throw new Exception(message: "More than one subscription event was found"); 70 | } 71 | 72 | var subscriptionEvent = gridMessage.Events.Single(); 73 | 74 | var validationCode = subscriptionEvent.GetPayload()?.ValidationCode; 75 | if (validationCode == null) 76 | { 77 | return null; 78 | } 79 | 80 | // This is a subscription validation message, echo the validationCode 81 | var responseMessage = actionContext.Request.CreateResponse( 82 | HttpStatusCode.OK, 83 | new {validationResponse = validationCode}, 84 | new JsonMediaTypeFormatter() 85 | ); 86 | 87 | //TODO : add logging 88 | //Log.Logger.Information("Echoing back the validation code {validationCode}", validationCode.ToString()); 89 | 90 | return responseMessage; 91 | } 92 | } 93 | } -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Security/ResultWithChallenge.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Net.Http; 4 | using System.Net.Http.Headers; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using System.Web.Http; 8 | 9 | namespace Arcus.EventGrid.Security 10 | { 11 | [Obsolete("Use the 'Arcus.EventGrid.WebApi.Security' package instead where Azure EventGrid authorization and subscription validation is now located")] 12 | public class ResultWithChallenge : IHttpActionResult 13 | { 14 | private const string AuthenticationScheme = "secretkey"; 15 | private readonly IHttpActionResult _next; 16 | 17 | public ResultWithChallenge(IHttpActionResult next) 18 | { 19 | _next = next; 20 | } 21 | 22 | public async Task ExecuteAsync(CancellationToken cancellationToken) 23 | { 24 | var response = await _next.ExecuteAsync(cancellationToken); 25 | 26 | if (response.StatusCode == HttpStatusCode.Unauthorized) 27 | { 28 | var authenticationHeader = new AuthenticationHeaderValue(AuthenticationScheme); 29 | response.Headers.WwwAuthenticate.Add(authenticationHeader); 30 | } 31 | 32 | return response; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Testing/Arcus.EventGrid.Testing.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0;net6.0 5 | Arcus 6 | Copyright (c) Arcus 7 | https://eventgrid.arcus-azure.net/ 8 | https://github.com/arcus-azure/arcus.eventgrid 9 | README.md 10 | LICENSE 11 | icon.png 12 | Azure;Event Grid;Testing 13 | Provides infrastructure to build automated testing with Azure Event Grid. 14 | true 15 | true 16 | true 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Testing/Infrastructure/Hosts/ServiceBus/ServiceBusEventConsumerHostOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GuardNet; 3 | 4 | namespace Arcus.EventGrid.Testing.Infrastructure.Hosts.ServiceBus 5 | { 6 | /// 7 | /// Represents the configuration options for the . 8 | /// 9 | public class ServiceBusEventConsumerHostOptions 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// The path of the Azure Service Bus topic relative to the Azure Service Bus namespace base address. 15 | /// The connection string, scoped to the Azure Service Bus namespace to authenticate with the Azure Service Bus topic. 16 | /// Thrown when the or the is blank. 17 | public ServiceBusEventConsumerHostOptions(string topicPath, string connectionString) 18 | { 19 | Guard.NotNullOrWhitespace(topicPath, nameof(topicPath), "Requires a non-blank Azure Service Bus topic name to consume events"); 20 | Guard.NotNullOrWhitespace(connectionString, nameof(connectionString), "Requires a non-blank Azure Service Bus connection string, scoped to the Azure Service Bus namespace to authenticate with the topic"); 21 | 22 | TopicPath = topicPath; 23 | ConnectionString = connectionString; 24 | SubscriptionName = $"Test-{Guid.NewGuid()}"; 25 | } 26 | 27 | /// 28 | /// Gets the Azure Service Bus topic name, relative to the namespace base address. 29 | /// 30 | public string TopicPath { get; } 31 | 32 | /// 33 | /// Gets the Azure Service Bus topic subscription name, where the to-be-consumed events will be placed. 34 | /// 35 | public string SubscriptionName { get; } 36 | 37 | /// 38 | /// Gets the connection string, scoped to the Azure Service Bus namespace to authenticate with the Azure Service Bus topic. 39 | /// 40 | public string ConnectionString { get; } 41 | 42 | /// 43 | /// Gets the the behavior of the Azure Service Bus topic subscription on closure. (Defaults to ) 44 | /// 45 | public SubscriptionBehavior SubscriptionBehavior { get; set; } = SubscriptionBehavior.DeleteOnClosure; 46 | } 47 | } -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Testing/Infrastructure/Hosts/ServiceBus/SubscriptionBehavior.cs: -------------------------------------------------------------------------------- 1 | namespace Arcus.EventGrid.Testing.Infrastructure.Hosts.ServiceBus 2 | { 3 | /// 4 | /// Represents the available options in behavior when Azure Service Bus topic subscriptions are managed during the lifetime of the . 5 | /// 6 | public enum SubscriptionBehavior 7 | { 8 | /// 9 | /// Keeps all the Azure Service Bus topic subscriptions that were created during the lifetime of the 10 | /// when the consumer host stops receiving traffic. 11 | /// 12 | KeepOnClosure, 13 | 14 | /// 15 | /// Deletes all the Azure Service Bus topic subscriptions that were created during the lifetime of the 16 | /// when the consumer host stops receiving traffic. 17 | /// 18 | DeleteOnClosure 19 | } 20 | } -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Testing/Logging/ConsoleLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Extensions.Logging; 3 | 4 | namespace Arcus.EventGrid.Testing.Logging 5 | { 6 | /// 7 | /// Represents an model that writes log messages towards the standard console output. 8 | /// 9 | [Obsolete("Use our xUnit test logger 'XunitTestLogger' in the 'Arcus.Testing.Logging' package to delegate diagnostic information to the test output")] 10 | public class ConsoleLogger : ILogger 11 | { 12 | /// 13 | /// Writes a log entry. 14 | /// 15 | /// The entry will be written on this level. 16 | /// The ID of the event. 17 | /// The entry to be written. Can be also an object. 18 | /// The exception related to this entry. 19 | /// The function to create a string message of the and . 20 | public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) 21 | { 22 | var message = formatter(state, exception); 23 | Console.WriteLine($"{DateTimeOffset.UtcNow:s} {logLevel} > {message}"); 24 | } 25 | 26 | /// 27 | /// Checks if the given is enabled. 28 | /// 29 | /// level to be checked. 30 | /// true if enabled. 31 | public bool IsEnabled(LogLevel logLevel) 32 | { 33 | return true; 34 | } 35 | 36 | /// 37 | /// Begins a logical operation scope. 38 | /// 39 | /// The identifier for the scope. 40 | /// An IDisposable that ends the logical operation scope on dispose. 41 | public IDisposable BeginScope(TState state) 42 | { 43 | return null; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Core/Arcus.EventGrid.Tests.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Core/ArcusAssert.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Arcus.EventGrid.Tests.Core.Events.Data; 3 | using Azure.Messaging; 4 | using Azure.Messaging.EventGrid; 5 | using Xunit; 6 | 7 | namespace Arcus.EventGrid.Tests.Core 8 | { 9 | /// 10 | /// Custom additional assertions. 11 | /// 12 | public static class ArcusAssert 13 | { 14 | public static void ReceivedNewCarRegisteredEvent(CloudEvent expected, string receivedEvent) 15 | { 16 | Assert.NotNull(expected); 17 | CloudEvent actual = CloudEvent.Parse(BinaryData.FromString(receivedEvent)); 18 | Assert.NotNull(actual); 19 | Assert.Equal(expected.Id, actual.Id); 20 | Assert.Equal(expected.Subject, actual.Subject); 21 | Assert.Equal(expected.Type, actual.Type); 22 | 23 | Assert.NotNull(expected.Data); 24 | var expectedData = expected.Data.ToObjectFromJson(); 25 | Assert.NotNull(actual.Data); 26 | var actualData = actual.Data.ToObjectFromJson(); 27 | Assert.Equal(expectedData.LicensePlate, actualData.LicensePlate); 28 | } 29 | 30 | public static void ReceivedNewCarRegisteredEvent(EventGridEvent expected, string receivedEvent) 31 | { 32 | Assert.NotNull(expected); 33 | EventGridEvent actual = EventGridEvent.Parse(BinaryData.FromString(receivedEvent)); 34 | Assert.NotNull(actual); 35 | Assert.Equal(expected.Id, actual.Id); 36 | Assert.Equal(expected.Subject, actual.Subject); 37 | Assert.Equal(expected.EventType, actual.EventType); 38 | 39 | Assert.NotNull(expected.Data); 40 | var expectedData = expected.Data.ToObjectFromJson(); 41 | Assert.NotNull(actual.Data); 42 | var actualData = actual.Data.ToObjectFromJson(); 43 | Assert.Equal(expectedData.LicensePlate, actualData.LicensePlate); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Core/Events/Data/CarEventData.cs: -------------------------------------------------------------------------------- 1 | using GuardNet; 2 | using System; 3 | 4 | namespace Arcus.EventGrid.Tests.Core.Events.Data 5 | { 6 | /// 7 | /// Event data representing a Collection of information about a car. 8 | /// 9 | public class CarEventData : IEquatable 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// The license plate of the car. 15 | public CarEventData(string licensePlate) 16 | { 17 | Guard.NotNullOrWhitespace(licensePlate, nameof(licensePlate)); 18 | 19 | LicensePlate = licensePlate; 20 | } 21 | 22 | /// 23 | /// Gets the license plate of the car. 24 | /// 25 | public string LicensePlate { get; } 26 | 27 | /// 28 | /// Indicates whether the current object is equal to another object of the same type. 29 | /// 30 | /// An object to compare with this object. 31 | /// true if the current object is equal to the other parameter; otherwise, false. 32 | public bool Equals(CarEventData other) 33 | { 34 | if (other is null) 35 | { 36 | return false; 37 | } 38 | 39 | if (ReferenceEquals(this, other)) 40 | { 41 | return true; 42 | } 43 | 44 | return LicensePlate.Equals(other.LicensePlate); 45 | } 46 | 47 | /// 48 | /// Indicates whether the current object is equal to another object of the same type. 49 | /// 50 | /// An object to compare with this object. 51 | /// true if the current object is equal to the other parameter; otherwise, false. 52 | public override bool Equals(object obj) 53 | { 54 | if (obj is null) 55 | { 56 | return false; 57 | } 58 | 59 | if (ReferenceEquals(this, obj)) 60 | { 61 | return true; 62 | } 63 | 64 | return obj is CarEventData other && Equals(other); 65 | } 66 | 67 | /// 68 | /// Serves as the default hash function. 69 | /// 70 | public override int GetHashCode() 71 | { 72 | return LicensePlate.GetHashCode(); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Core/Events/EventSchema.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Arcus.EventGrid.Tests.Core.Events 8 | { 9 | public enum EventSchema 10 | { 11 | CloudEvent, 12 | EventGrid 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.InMemoryApi/Arcus.EventGrid.Tests.InMemoryApi.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1;net6.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.InMemoryApi/Controllers/AuthorizationController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.Http; 3 | using System.Web.Http; 4 | using Arcus.EventGrid.Security.Attributes; 5 | 6 | namespace Arcus.EventGrid.Tests.InMemoryApi.Controllers 7 | { 8 | public class AuthorizationController : ApiController 9 | { 10 | [HttpPost] 11 | [Route("authz/hardcoded")] 12 | [EventGridAuthorization("x-auth", "auth-key")] 13 | public IHttpActionResult TestConfiguredKeyWithHardcodedKey(HttpRequestMessage message) 14 | { 15 | try 16 | { 17 | return Ok(); 18 | } 19 | catch (Exception ex) 20 | { 21 | return InternalServerError(ex); 22 | } 23 | } 24 | 25 | [HttpPost] 26 | [Route("authz/dynamic")] 27 | [DynamicEventGridAuthorization("x-auth")] 28 | public IHttpActionResult TestConfiguredKeyWithDynamicKey(HttpRequestMessage message) 29 | { 30 | try 31 | { 32 | return Ok(); 33 | } 34 | catch (Exception ex) 35 | { 36 | return InternalServerError(ex); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.InMemoryApi/Controllers/WebhookController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.Http; 3 | using System.Web.Http; 4 | using Arcus.EventGrid.Security; 5 | using Arcus.EventGrid.Security.Attributes; 6 | 7 | namespace Arcus.EventGrid.Tests.InMemoryApi.Controllers 8 | { 9 | public class WebhookController : ApiController 10 | { 11 | [HttpPost] 12 | [Route("events/test")] 13 | [EventGridSubscriptionValidator] 14 | [EventGridAuthorization("x-api-key", "event-grid")] 15 | public IHttpActionResult TestHandshake(HttpRequestMessage message) 16 | { 17 | try 18 | { 19 | return Ok(); 20 | } 21 | catch (Exception ex) 22 | { 23 | return InternalServerError(ex); 24 | } 25 | } 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.InMemoryApi/InMemoryTestApiStartup.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using System.Web.Http; 3 | using Arcus.EventGrid.Security.Attributes; 4 | using Owin; 5 | 6 | namespace Arcus.EventGrid.Tests.InMemoryApi 7 | { 8 | public class InMemoryTestApiStartup 9 | { 10 | public static string SecretKey { private get; set; } = null; 11 | 12 | public void Configuration(IAppBuilder app) 13 | { 14 | var config = new HttpConfiguration 15 | { 16 | IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always 17 | }; 18 | 19 | config.MapHttpAttributeRoutes(); 20 | config.Routes.MapHttpRoute( 21 | name: "DefaultApi", 22 | routeTemplate: "api/{controller}/{id}", 23 | defaults: new { id = RouteParameter.Optional } 24 | ); 25 | 26 | app.UseWebApi(config); 27 | 28 | if (!string.IsNullOrEmpty(SecretKey)) 29 | { 30 | DynamicEventGridAuthorizationAttribute.RetrieveAuthenticationSecret = () => Task.FromResult(SecretKey); 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Integration/Arcus.EventGrid.Tests.Integration.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Always 29 | 30 | 31 | Always 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Integration/Fixture/MockServiceBusEventConsumerHostOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using Arcus.EventGrid.Testing.Infrastructure.Hosts.ServiceBus; 5 | using Azure.Messaging.ServiceBus; 6 | 7 | namespace Arcus.EventGrid.Tests.Integration.Fixture 8 | { 9 | public class MockServiceBusEventConsumerHostOptions : ServiceBusEventConsumerHostOptions 10 | { 11 | private readonly ICollection> _assertions = new Collection>(); 12 | 13 | /// 14 | /// Initializes a new instance of the class. 15 | /// 16 | /// The path of the Azure Service Bus topic relative to the Azure Service Bus namespace base address. 17 | /// The connection string, scoped to the Azure Service Bus namespace to authenticate with the Azure Service Bus topic. 18 | /// Thrown when the or the is blank. 19 | public MockServiceBusEventConsumerHostOptions(string topicPath, string connectionString) : base(topicPath, connectionString) 20 | { 21 | } 22 | 23 | public void AddMessageAssertion(Action assertion) 24 | { 25 | _assertions.Add(assertion); 26 | } 27 | 28 | public void AssertMessage(ProcessMessageEventArgs message) 29 | { 30 | var exceptions = new Collection(); 31 | foreach (Action assertion in _assertions) 32 | { 33 | try 34 | { 35 | assertion(message); 36 | } 37 | catch (Exception exception) 38 | { 39 | exceptions.Add(exception); 40 | } 41 | } 42 | 43 | if (exceptions.Count is 1) 44 | { 45 | throw exceptions[0]; 46 | } 47 | 48 | if (exceptions.Count > 1) 49 | { 50 | throw new AggregateException("Received message failed to be asserted by all the registered message assertions", exceptions); 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Integration/Fixture/TemporaryManagedIdentityConnection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GuardNet; 3 | using Microsoft.Extensions.Configuration; 4 | 5 | namespace Arcus.EventGrid.Tests.Integration.Fixture 6 | { 7 | /// 8 | /// Represents a temporary active Azure Managed Identity connection. 9 | /// 10 | public class TemporaryManagedIdentityConnection : IDisposable 11 | { 12 | private const string AzureTenantIdEnvironmentVariable = "AZURE_TENANT_ID", 13 | AzureServicePrincipalClientIdVariable = "AZURE_CLIENT_ID", 14 | AzureServicePrincipalClientSecretVariable = "AZURE_CLIENT_SECRET"; 15 | 16 | private TemporaryManagedIdentityConnection() 17 | { 18 | } 19 | 20 | /// 21 | /// Start a temporary active Azure Managed Identity connection. 22 | /// 23 | /// The test configuration to retrieve the secrets from to represent the Azure Managed Identity. 24 | /// Thrown when the is null. 25 | public static TemporaryManagedIdentityConnection Create(TestConfig config) 26 | { 27 | Guard.NotNull(config, nameof(config), "Requires a test configuration instance to retrieve any secrets to represent the Azure Managed Identity"); 28 | 29 | Environment.SetEnvironmentVariable(AzureTenantIdEnvironmentVariable, config.GetValue("Arcus:TenantId")); 30 | Environment.SetEnvironmentVariable(AzureServicePrincipalClientIdVariable, config.GetValue("Arcus:ServicePrincipal:ClientId")); 31 | Environment.SetEnvironmentVariable(AzureServicePrincipalClientSecretVariable, config.GetValue("Arcus:ServicePrincipal:ClientKey")); 32 | 33 | return new TemporaryManagedIdentityConnection(); 34 | } 35 | 36 | /// 37 | /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. 38 | /// 39 | public void Dispose() 40 | { 41 | Environment.SetEnvironmentVariable(AzureTenantIdEnvironmentVariable, null); 42 | Environment.SetEnvironmentVariable(AzureServicePrincipalClientIdVariable, null); 43 | Environment.SetEnvironmentVariable(AzureServicePrincipalClientSecretVariable, null); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Integration/Publishing/Fixture/CustomEventGridPublisherClientWithTracking.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Arcus.Observability.Correlation; 7 | using Arcus.Security.Core; 8 | using Azure.Messaging; 9 | using Azure.Messaging.EventGrid; 10 | using Microsoft.Extensions.Logging; 11 | using Microsoft.Extensions.Logging.Abstractions; 12 | 13 | namespace Arcus.EventGrid.Tests.Integration.Publishing.Fixture 14 | { 15 | public class CustomEventGridPublisherClientWithTracking : EventGridPublisherClientWithTracking 16 | { 17 | public CustomEventGridPublisherClientWithTracking( 18 | string topicEndpoint, 19 | string authenticationKeySecretName, 20 | ISecretProvider secretProvider, 21 | ICorrelationInfoAccessor correlationAccessor, 22 | EventGridPublisherClientWithTrackingOptions options, 23 | ILogger logger) 24 | : base(topicEndpoint, authenticationKeySecretName, secretProvider, correlationAccessor, options, logger) 25 | { 26 | } 27 | 28 | protected override CloudEvent SetCorrelationPropertyInCloudEvent(CloudEvent cloudEvent, string propertyName, string propertyValue) 29 | { 30 | propertyName = DetermineCustomPropertyName(propertyName); 31 | return base.SetCorrelationPropertyInCloudEvent(cloudEvent, propertyName, propertyValue); 32 | } 33 | 34 | protected override EventGridEvent SetCorrelationPropertyInEventGridEvent(EventGridEvent eventGridEvent, string propertyName, string propertyValue) 35 | { 36 | propertyName = DetermineCustomPropertyName(propertyName); 37 | return base.SetCorrelationPropertyInEventGridEvent(eventGridEvent, propertyName, propertyValue); 38 | } 39 | 40 | protected override BinaryData SetCorrelationPropertyInCustomEvent(BinaryData data, string propertyName, string propertyValue) 41 | { 42 | propertyName = DetermineCustomPropertyName(propertyName); 43 | return base.SetCorrelationPropertyInCustomEvent(data, propertyName, propertyValue); 44 | } 45 | 46 | private static string DetermineCustomPropertyName(string propertyName) 47 | { 48 | if (propertyName == "transactionId") 49 | { 50 | return "customTransactionId"; 51 | } 52 | 53 | if (propertyName == "operationParentId") 54 | { 55 | return "customOperationParentId"; 56 | } 57 | 58 | if (propertyName == "traceparent") 59 | { 60 | return "customTraceparent"; 61 | } 62 | 63 | throw new InvalidOperationException($"Unknown property name: '{propertyName}'"); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Integration/Publishing/Fixture/EndpointCallCount.cs: -------------------------------------------------------------------------------- 1 | namespace Arcus.EventGrid.Tests.Integration.Publishing.Fixture 2 | { 3 | /// 4 | /// Represents a data model to count the calls to the . 5 | /// 6 | public class EndpointCallCount 7 | { 8 | /// 9 | /// Gets or sets the amount of calls to the . 10 | /// 11 | public int Count { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Integration/Publishing/Fixture/EventOptionsFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Azure.Messaging.EventGrid; 4 | using Xunit; 5 | using GuardNet; 6 | 7 | namespace Arcus.EventGrid.Tests.Integration.Publishing.Fixture 8 | { 9 | /// 10 | /// Represents a test fixture to verify whether event options are being passed correctly. 11 | /// 12 | public class EventOptionsFixture 13 | { 14 | private readonly string _key1 = $"key-{Guid.NewGuid()}", _value1 = $"value-{Guid.NewGuid()}"; 15 | private readonly string _key2 = $"key-{Guid.NewGuid()}", _value2 = $"value-{Guid.NewGuid()}"; 16 | 17 | /// 18 | /// Gets the custom dependency ID used during the event publishing options. 19 | /// 20 | public string DependencyId { get; } = $"parent-{Guid.NewGuid()}"; 21 | 22 | /// 23 | /// Applies additional values to the to verify the changed behavior later. 24 | /// 25 | /// The user options to influence the correlation during event publishing. 26 | /// Thrown when the is null. 27 | public void ApplyOptions(EventGridPublisherClientWithTrackingOptions options) 28 | { 29 | Guard.NotNull(options, nameof(options), "Requires a set of user options that influence the correlation during event publishing"); 30 | 31 | options.GenerateDependencyId = () => DependencyId; 32 | options.AddTelemetryContext(new Dictionary { [_key1] = _value1 }); 33 | options.AddTelemetryContext(new Dictionary { [_key2] = _value2, [_key1] = _value2 }); 34 | } 35 | 36 | /// 37 | /// Asserts on the influenced correlation during event publishing. 38 | /// 39 | /// The log message that should contain the influenced correlation during event publishing. 40 | public void AssertTelemetry(string logMessage) 41 | { 42 | Assert.NotNull(logMessage); 43 | Assert.Contains(_key1, logMessage); 44 | Assert.DoesNotContain(_value1, logMessage); 45 | Assert.Contains(_key2, logMessage); 46 | Assert.Contains(_value2, logMessage); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Integration/Publishing/Fixture/SabotageMockTopicEndpoint.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Bogus; 4 | using Microsoft.AspNetCore.Builder; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.AspNetCore.Http; 7 | using Microsoft.Extensions.DependencyInjection; 8 | using Microsoft.Extensions.Hosting; 9 | 10 | namespace Arcus.EventGrid.Tests.Integration.Publishing.Fixture 11 | { 12 | /// 13 | /// Represents an Azure Event Grid topic endpoint that sabotages requests to the endpoint. 14 | /// 15 | public class SabotageMockTopicEndpoint : IAsyncDisposable 16 | { 17 | private readonly IHost _host; 18 | 19 | private static readonly Faker BogusGenerator = new Faker(); 20 | 21 | private SabotageMockTopicEndpoint(IHost host, string hostingUrl) 22 | { 23 | _host = host; 24 | HostingUrl = hostingUrl; 25 | } 26 | 27 | /// 28 | /// Gets the URL where this topic endpoint is hosted. 29 | /// 30 | public string HostingUrl { get; } 31 | 32 | /// 33 | /// Gets the amount that where send to this topic endpoint. 34 | /// 35 | public int EndpointCallCount => _host.Services.GetRequiredService().Count; 36 | 37 | /// 38 | /// Starts an on a generated hosting URL. 39 | /// 40 | public static async Task StartAsync() 41 | { 42 | string url = $"http://localhost:{BogusGenerator.Random.Int(5000, 5500)}/"; 43 | 44 | var builder = WebApplication.CreateBuilder(); 45 | builder.Services.AddSingleton(); 46 | builder.WebHost.UseKestrel() 47 | .UseUrls(url); 48 | 49 | WebApplication app = builder.Build(); 50 | app.Use(async (HttpContext ctx, Func next) => 51 | { 52 | ctx.RequestServices.GetRequiredService().Count++; 53 | 54 | ctx.Response.StatusCode = StatusCodes.Status500InternalServerError; 55 | await ctx.Response.WriteAsync("Sabotage this endpoint!"); 56 | }); 57 | 58 | await app.StartAsync(); 59 | return new SabotageMockTopicEndpoint(app, url); 60 | } 61 | 62 | /// 63 | /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources asynchronously. 64 | /// 65 | /// A task that represents the asynchronous dispose operation. 66 | public async ValueTask DisposeAsync() 67 | { 68 | await _host.StopAsync(); 69 | _host.Dispose(); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Integration/TestCollections.cs: -------------------------------------------------------------------------------- 1 | namespace Arcus.EventGrid.Tests.Integration 2 | { 3 | /// 4 | /// Represents the different test collections in this test suite. 5 | /// 6 | public class TestCollections 7 | { 8 | /// 9 | /// Gets the default integration test collection. 10 | /// 11 | public const string Integration = "Integration"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Integration/WebApi/Fixture/HealthController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace Arcus.EventGrid.Tests.Integration.WebApi.Fixture 4 | { 5 | [Route(GetRoute)] 6 | [ApiController] 7 | public class HealthController : ControllerBase 8 | { 9 | public const string GetRoute = "api/v1/health"; 10 | 11 | [HttpGet] 12 | public IActionResult Get() 13 | { 14 | return Ok(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Integration/WebApi/Security/Controllers/EventGridAuthorizationController.cs: -------------------------------------------------------------------------------- 1 | using Arcus.EventGrid.Security.WebApi; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace Arcus.EventGrid.Tests.Integration.WebApi.Security.Controllers 5 | { 6 | [ApiController] 7 | public class EventGridAuthorizationController : ControllerBase 8 | { 9 | public const string GetAuthorizedWithHeaderRoute = "authz/event-grid/header", 10 | GetAuthorizedWithHeaderEmitsSecurityEventsRoute = "authz/event-grid/header/security-events", 11 | GetAuthorizedWithQueryRoute = "authz/event-grid/query", 12 | GetAuthorizedWithQueryEmitsSecurityEventsRoute = "authz/event-grid/query/security-events", 13 | HttpRequestHeaderName = "X-Auth-Header", 14 | HttpRequestQueryParameterName = "x-auth-param", 15 | SecretName = "auth-key"; 16 | 17 | [HttpGet] 18 | [Route(GetAuthorizedWithHeaderRoute)] 19 | [EventGridAuthorization(HttpRequestProperty.Header, HttpRequestHeaderName, SecretName)] 20 | public IActionResult GetAuthorizedWithHeader() 21 | { 22 | return Ok(); 23 | } 24 | 25 | [HttpGet] 26 | [Route(GetAuthorizedWithHeaderEmitsSecurityEventsRoute)] 27 | [EventGridAuthorization(HttpRequestProperty.Header, HttpRequestHeaderName, SecretName, EmitSecurityEvents = true)] 28 | public IActionResult GetAuthorizedWithHeaderEmitsSecurityEvents() 29 | { 30 | return Ok(); 31 | } 32 | 33 | [HttpGet] 34 | [Route(GetAuthorizedWithQueryRoute)] 35 | [EventGridAuthorization(HttpRequestProperty.Query, HttpRequestQueryParameterName, SecretName)] 36 | public IActionResult GetAuthorizedWithQuery() 37 | { 38 | return Ok(); 39 | } 40 | 41 | [HttpGet] 42 | [Route(GetAuthorizedWithQueryEmitsSecurityEventsRoute)] 43 | [EventGridAuthorization(HttpRequestProperty.Query, HttpRequestQueryParameterName, SecretName, EmitSecurityEvents = true)] 44 | public IActionResult GetAuthorizedWithQueryEmitsSecurityEvents() 45 | { 46 | return Ok(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Integration/WebApi/Security/Controllers/EventGridSubscriptionValidationController.cs: -------------------------------------------------------------------------------- 1 | using Arcus.EventGrid.Security.WebApi; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace Arcus.EventGrid.Tests.Integration.WebApi.Security.Controllers 5 | { 6 | [ApiController] 7 | public class EventGridSubscriptionValidationController : ControllerBase 8 | { 9 | public const string GetSubscriptionValidationRoute = "subscr-val/event-grid"; 10 | 11 | [HttpGet, HttpOptions] 12 | [Route(GetSubscriptionValidationRoute)] 13 | [EventGridSubscriptionValidation] 14 | public IActionResult Get() 15 | { 16 | return Accepted(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Integration/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Arcus": { 3 | "TenantId": "#{Arcus.TenantId}#", 4 | "ServicePrincipal": { 5 | "ClientId": "#{Arcus.ServicePrincipal.ClientId}#", 6 | "ClientKey": "#{Arcus.ServicePrincipal.ClientKey}#" 7 | }, 8 | "ServiceBus": { 9 | "ConnectionString": "#{ServiceBus.ConnectionString}#" 10 | }, 11 | "EventGridEvent": { 12 | "EventGrid": { 13 | "TopicEndpoint": "#{EventGridEvent.EventGrid.TopicEndpoint}#", 14 | "EndpointKey": "#{EventGridEvent.EventGrid.EndpointKey}#" 15 | }, 16 | "ServiceBus": { 17 | "TopicName": "#{ServiceBus.EventGridEvent.TopicName}#" 18 | } 19 | }, 20 | "CloudEvent": { 21 | "EventGrid": { 22 | "TopicEndpoint": "#{CloudEvent.EventGrid.TopicEndpoint}#", 23 | "EndpointKey": "#{CloudEvent.EventGrid.EndpointKey}#" 24 | }, 25 | "ServiceBus": { 26 | "TopicName": "#{ServiceBus.CloudEvent.TopicName}#" 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Unit/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Unit/Arcus.EventGrid.Tests.Unit.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | all 16 | 17 | 18 | runtime; build; native; contentfiles; analyzers; buildtransitive 19 | all 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | True 39 | True 40 | EventSamples.resx 41 | 42 | 43 | 44 | 45 | 46 | ResXFileCodeGenerator 47 | EventSamples.Designer.cs 48 | 49 | 50 | 51 | 52 | 53 | PreserveNewest 54 | 55 | 56 | PreserveNewest 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Unit/Blanks.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | 4 | namespace Arcus.EventGrid.Tests.Unit 5 | { 6 | /// 7 | /// Represents a series of blank test inputs, used for data-driven tests. 8 | /// 9 | public class Blanks : IEnumerable 10 | { 11 | /// 12 | /// Returns an enumerator that iterates through the collection. 13 | /// 14 | /// An enumerator that can be used to iterate through the collection. 15 | public IEnumerator GetEnumerator() 16 | { 17 | yield return new object[] {null}; 18 | yield return new object[] {""}; 19 | yield return new object[] {" "}; 20 | yield return new object[] {" "}; 21 | } 22 | 23 | /// 24 | /// Returns an enumerator that iterates through a collection. 25 | /// 26 | /// An object that can be used to iterate through the collection. 27 | IEnumerator IEnumerable.GetEnumerator() 28 | { 29 | return GetEnumerator(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Unit/Publishing/Fixtures/StubEventGridPublisherClientWithTracking.cs: -------------------------------------------------------------------------------- 1 | using Arcus.Observability.Correlation; 2 | using Azure.Messaging.EventGrid; 3 | using Microsoft.Extensions.Logging; 4 | using Microsoft.Extensions.Logging.Abstractions; 5 | using Moq; 6 | 7 | namespace Arcus.EventGrid.Tests.Unit.Publishing.Fixtures 8 | { 9 | public class StubEventGridPublisherClientWithTracking : EventGridPublisherClientWithTracking 10 | { 11 | public StubEventGridPublisherClientWithTracking( 12 | EventGridPublisherClientWithTrackingOptions options = null, 13 | ILogger logger = null) 14 | : base("https://savanh-grid-lab.westcentralus-1.eventgrid.azure.net/api/events", 15 | new InMemoryEventGridPublisherClient(), 16 | Mock.Of(), 17 | options ?? new EventGridPublisherClientWithTrackingOptions(), 18 | logger ?? NullLogger.Instance) 19 | { 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Unit/Security/EventGridAuthorizationAttributeTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Arcus.EventGrid.Security.WebApi; 3 | using Bogus; 4 | using Xunit; 5 | 6 | namespace Arcus.EventGrid.Tests.Unit.Security 7 | { 8 | public class EventGridAuthorizationAttributeTests 9 | { 10 | private readonly Faker _bogusGenerator = new Faker(); 11 | 12 | [Theory] 13 | [ClassData(typeof(Blanks))] 14 | public void CreateAttribute_WithoutSecretName_Fails(string secretName) 15 | { 16 | // Arrange 17 | var property = _bogusGenerator.Random.Enum(); 18 | string inputName = _bogusGenerator.Name.FirstName(); 19 | 20 | // Act / Assert 21 | Assert.ThrowsAny(() => new EventGridAuthorizationAttribute(property, inputName, secretName)); 22 | } 23 | 24 | [Theory] 25 | [ClassData(typeof(Blanks))] 26 | public void CreateAttribute_WithoutInputName_Fails(string inputName) 27 | { 28 | // Arrange 29 | var property = _bogusGenerator.Random.Enum(); 30 | string secretName = _bogusGenerator.Name.FirstName(); 31 | 32 | // Act / Assert 33 | Assert.ThrowsAny(() => new EventGridAuthorizationAttribute(property, inputName, secretName)); 34 | } 35 | 36 | [Theory] 37 | [InlineData(HttpRequestProperty.Header)] 38 | [InlineData(HttpRequestProperty.Query)] 39 | public void CreateAttribute_WithRequestFlags_Succeeds(HttpRequestProperty requestInput) 40 | { 41 | // Arrange 42 | string property = _bogusGenerator.Name.FirstName(); 43 | string secretName = _bogusGenerator.Name.FirstName(); 44 | 45 | // Act / Assert 46 | var attribute = new EventGridAuthorizationAttribute(requestInput, property, secretName); 47 | } 48 | 49 | [Theory] 50 | [InlineData((HttpRequestProperty) 4)] 51 | [InlineData((HttpRequestProperty) 5)] 52 | [InlineData((HttpRequestProperty) 15)] 53 | [InlineData(HttpRequestProperty.Query | HttpRequestProperty.Header)] 54 | public void CreateAttribute_WithInvalidRequestFlags_Succeeds(HttpRequestProperty requestInput) 55 | { 56 | // Arrange 57 | string property = _bogusGenerator.Name.FirstName(); 58 | string secretName = _bogusGenerator.Name.FirstName(); 59 | 60 | // Act / Assert 61 | Assert.ThrowsAny(() => new EventGridAuthorizationAttribute(requestInput, property, secretName)); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Unit/Security/EventGridSubscriptionValidationActionFilterTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Arcus.EventGrid.Security.Core.Validation; 7 | using Arcus.EventGrid.Security.WebApi; 8 | using Microsoft.AspNetCore.Http; 9 | using Microsoft.AspNetCore.Mvc; 10 | using Microsoft.AspNetCore.Mvc.Abstractions; 11 | using Microsoft.AspNetCore.Mvc.Filters; 12 | using Microsoft.AspNetCore.Mvc.ModelBinding; 13 | using Microsoft.AspNetCore.Routing; 14 | using Microsoft.Extensions.DependencyInjection; 15 | using Moq; 16 | using Xunit; 17 | 18 | namespace Arcus.EventGrid.Tests.Unit.Security 19 | { 20 | public class EventGridSubscriptionValidationActionFilterTests 21 | { 22 | [Fact] 23 | public async Task ValidateSubscription_WithDefault_Succeeds() 24 | { 25 | // Arrange 26 | var attribute = new EventGridSubscriptionValidationAttribute(); 27 | var services = new ServiceCollection(); 28 | services.AddLogging(); 29 | 30 | ServiceProvider serviceProvider = services.BuildServiceProvider(); 31 | var filter = (IAsyncActionFilter) attribute.CreateInstance(serviceProvider); 32 | 33 | var httpContext = new DefaultHttpContext(); 34 | httpContext.RequestServices = serviceProvider; 35 | 36 | var actionExecutingContext = new ActionExecutingContext( 37 | new ActionContext(httpContext, new RouteData(), new ActionDescriptor(), new ModelStateDictionary()), 38 | new List(), 39 | new Dictionary(), 40 | controller: null); 41 | 42 | var actionExecutedContext = new ActionExecutedContext( 43 | new ActionContext(httpContext, new RouteData(), new ActionDescriptor(), new ModelStateDictionary()), 44 | new List(), 45 | controller: null); 46 | 47 | // Act / Assert 48 | await filter.OnActionExecutionAsync(actionExecutingContext, () => Task.FromResult(actionExecutedContext)); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Unit/Security/Extensions/IServiceCollectionExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Arcus.EventGrid.Security.Core.Validation; 3 | using Arcus.EventGrid.Tests.Unit.Security.Fixture; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Azure.Functions.Extensions.DependencyInjection; 6 | using Xunit; 7 | 8 | namespace Arcus.EventGrid.Tests.Unit.Security.Extensions 9 | { 10 | public class IServiceCollectionExtensionsTests 11 | { 12 | [Fact] 13 | public void AddEventGridSubscriptionValidation_WithServices_RegistersInstance() 14 | { 15 | // Arrange 16 | var services = new ServiceCollection(); 17 | services.AddLogging(); 18 | 19 | // Act 20 | services.AddEventGridSubscriptionValidation(); 21 | 22 | // Assert 23 | IServiceProvider provider = services.BuildServiceProvider(); 24 | Assert.NotNull(provider.GetService()); 25 | } 26 | 27 | [Fact] 28 | public void AddEventGridSubscriptionValidation_WithFuntionHostServices_RegisteresInstance() 29 | { 30 | // Arrange 31 | var services = new ServiceCollection(); 32 | var builder = new StubFunctionsHostBuilder(services); 33 | services.AddLogging(); 34 | 35 | // Act 36 | builder.AddEventGridSubscriptionValidation(); 37 | 38 | // Assert 39 | IServiceProvider provider = builder.Services.BuildServiceProvider(); 40 | Assert.NotNull(provider.GetService()); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Unit/Security/Fixture/StubFunctionsHostBuilder.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Azure.Functions.Extensions.DependencyInjection; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Arcus.EventGrid.Tests.Unit.Security.Fixture 5 | { 6 | /// 7 | /// Represents a stubbed-out Azure Functions host builder instance. 8 | /// 9 | public class StubFunctionsHostBuilder : IFunctionsHostBuilder 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// The stubbed-out registered application services for the Azure Functions application. 15 | public StubFunctionsHostBuilder(IServiceCollection services) 16 | { 17 | Services = services; 18 | } 19 | 20 | /// 21 | /// Gets the available registered services collection for the Azure Functions application. 22 | /// 23 | public IServiceCollection Services { get; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Unit/TestCollections.cs: -------------------------------------------------------------------------------- 1 | namespace Arcus.EventGrid.Tests.Unit 2 | { 3 | internal class TestCollections 4 | { 5 | public const string ApiTests = "ApiTests"; 6 | } 7 | } -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Unit/Testing/Fixture/InMemoryEventConsumerHost.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Text.Json; 6 | using System.Threading.Tasks; 7 | using Arcus.EventGrid.Testing.Infrastructure.Hosts; 8 | using Azure.Messaging; 9 | using Azure.Messaging.EventGrid; 10 | using Microsoft.Extensions.Logging; 11 | 12 | namespace Arcus.EventGrid.Tests.Unit.Testing.Fixture 13 | { 14 | public class InMemoryEventConsumerHost : EventConsumerHost 15 | { 16 | public InMemoryEventConsumerHost(ILogger logger) : base(logger) 17 | { 18 | } 19 | 20 | public void ReceiveEvent(CloudEvent cloudEvent) 21 | { 22 | string rawReceivedEvents = JsonSerializer.Serialize(cloudEvent); 23 | EventsReceived(rawReceivedEvents); 24 | } 25 | 26 | public void ReceiveEvent(EventGridEvent eventGridEvent) 27 | { 28 | string rawReceivedEvents = JsonSerializer.Serialize(eventGridEvent); 29 | EventsReceived(rawReceivedEvents); 30 | } 31 | 32 | public void ReceiveEvents(IEnumerable cloudEvents) 33 | { 34 | EventsReceived(JsonSerializer.Serialize(cloudEvents)); 35 | } 36 | 37 | public void ReceiveEvents(IEnumerable eventGridEvents) 38 | { 39 | EventsReceived(JsonSerializer.Serialize(eventGridEvents)); 40 | } 41 | 42 | public void ReceiveEvent(string raw) 43 | { 44 | EventsReceived(raw); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Unit/Testing/ServiceBusEventConsumerHostOptionsTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Arcus.EventGrid.Testing.Infrastructure.Hosts.ServiceBus; 3 | using Bogus; 4 | using Xunit; 5 | 6 | namespace Arcus.EventGrid.Tests.Unit.Testing 7 | { 8 | public class ServiceBusEventConsumerHostOptionsTests 9 | { 10 | private static readonly Faker BogusGenerator = new Faker(); 11 | 12 | [Fact] 13 | public void Create_WithDefault_Succeeds() 14 | { 15 | // Arrange 16 | string topicPath = BogusGenerator.Internet.UrlWithPath(); 17 | string connectionString = BogusGenerator.Lorem.Sentence(); 18 | 19 | // Act 20 | var options = new ServiceBusEventConsumerHostOptions(topicPath, connectionString); 21 | 22 | // Assert 23 | Assert.NotNull(options.SubscriptionName); 24 | } 25 | 26 | [Theory] 27 | [ClassData(typeof(Blanks))] 28 | public void Create_WithoutTopicPath_Fails(string topicPath) 29 | { 30 | // Arrange 31 | string connectionString = BogusGenerator.Lorem.Sentence(); 32 | 33 | // Act / Assert 34 | Assert.ThrowsAny( 35 | () => new ServiceBusEventConsumerHostOptions(topicPath, connectionString)); 36 | } 37 | 38 | [Theory] 39 | [ClassData(typeof(Blanks))] 40 | public void Create_WithoutConnectionString_Fails(string connectionString) 41 | { 42 | // Arrange 43 | string topicPath = BogusGenerator.Internet.UrlWithPath(); 44 | 45 | // Act / Assert 46 | Assert.ThrowsAny( 47 | () => new ServiceBusEventConsumerHostOptions(topicPath, connectionString)); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Unit/Testing/ServiceBusEventConsumerHostTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Arcus.EventGrid.Testing.Infrastructure.Hosts.ServiceBus; 7 | using Arcus.Testing.Logging; 8 | using Microsoft.Extensions.Logging; 9 | using Xunit; 10 | using Xunit.Abstractions; 11 | 12 | namespace Arcus.EventGrid.Tests.Unit.Testing 13 | { 14 | public class ServiceBusEventConsumerHostTests 15 | { 16 | private readonly ILogger _logger; 17 | 18 | /// 19 | /// Initializes a new instance of the class. 20 | /// 21 | public ServiceBusEventConsumerHostTests(ITestOutputHelper outputWriter) 22 | { 23 | _logger = new XunitTestLogger(outputWriter); 24 | } 25 | 26 | [Fact] 27 | public async Task Test() 28 | { 29 | var options = new ServiceBusEventConsumerHostOptions("topic-path", "Endpoint=sb://something-valid.servicebus.windows.net/;SharedAccessKeyName=SomeAccessKeyName;SharedAccessKey=1A00aAaaAaa00aaa00AaaAa0a0AAaAA0a0AAaaaAaAA="); 30 | await Assert.ThrowsAsync(() => ServiceBusEventConsumerHost.StartAsync(options, _logger)); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Arcus.EventGrid.Tests.Unit/xunit.runner.json: -------------------------------------------------------------------------------- 1 | { 2 | "appDomain": "required" 3 | } -------------------------------------------------------------------------------- /src/Arcus.EventGrid.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> --------------------------------------------------------------------------------