Skip to content
This repository has been archived by the owner on Aug 27, 2024. It is now read-only.

docs: publish v4.0 feature docs #314

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions docs/versioned_docs/version-v4.0.0/01-index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: "Arcus Event Grid"
layout: default
slug: /
sidebar_label: Welcome
---

# Introduction

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.

# Installation

```shell
PM > Install-Package Arcus.EventGrid.Core
```

# License
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.

*[Full license here](https://github.com/arcus-azure/arcus.eventgrid/blob/master/LICENSE)*
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: "Create custom events"
layout: default
---

## Create Custom Events

> ❌ The `Arcus.EventGrid` package is deprecated and will be removed in v4.

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.
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
---
title: "Deserializing Events"
layout: default
---

## Deserializing Events

> ❌ The `Arcus.EventGrid` package is deprecated and will be removed in v4. Use the `EventGridEvent.Parse` and `CloudEvent.Parse` from the `Azure.Messaging.EventGrid` to parse events.

Starting from v3.3, we use fully the Azure SDK to deserialize events from and 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 parsing custom events.

The `Arcus.EventGrid` package provides several ways to deserializing events.

Following paragraphs describe each supported way to deserialize an event.

### Deserializing Built-In Azure Events

When using official Azure events, you can use `.ParseFromData<>` to deserialize then those based on the built-in types as shown in the example:

```csharp
using Arcus.EventGrid;
using Arcus.EventGrid.Parsers;
using Microsoft.Azure.EventGrid.Models;

// Parse directly from an event data type with the `.Parse` function.
byte[] rawEvent = ...
EventBatch<Event> eventBatch = EventParser.Parse(rawEvent);

// The type `EventGridEvent` comes directly from the official SDK package
// and can be cast implicitly like so,
EventGridEvent eventGridEvent = eventBatch.Events.Single();

// Or explicitly.
EventGridEvent eventGridEvent = eventBatch.Events.Single().AsEventGridEvent();

// The actual EventGrid payload can be retrieved by passing along the Azure SDK model type.
var storageEventData = eventGridEvent.GetPayload<StorageBlobCreatedEventData>();
```

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).

### Deserializing CloudEvent Events

We provide support for deserializing CloudEvents using the [official SDK for C#](https://github.com/cloudevents/sdk-csharp).

Upon receiving of CloudEvent events:

```csharp
using Arcus.EventGrid;
using Arcus.EventGrid.Parsers;
using CloudNative.CloudEvents;

string cloudEventJson = ...
EventBatch<Event> eventBatch = EventParser.Parse(cloudEventJson);
var events = eventBatch.Events;

// The type `CloudEvent` comes directly from the official SDK package
// and can be cast implicitly like so,
CloudEvent cloudEvent = events.First();

// Or explicitly.
CloudEvent cloudEvent = events.First().AsCloudEvent();
```

### Deserializing Event Grid Events

We provide support for deserializing [EventGrid events](https://docs.microsoft.com/en-us/azure/event-grid/event-schema).

```csharp
using Arcus.EventGrid;
using Arcus.EventGrid.Parsers;
using Microsoft.Azure.EventGrid.Models;

string eventGridEventJson = ...
EventBatch<Event> eventBatch = EventParser.Parse(eventGridEventJson);
var events = eventBatch.Events;

// The `EventGridEvent` can be cast implicitly like so,
EventGridEvent eventGridEvent = events.First();

// Or explicitly.
EventGridEvent eventGridEvent = events.First().AsEventGridEvent();
```

### Deserializing Custom Events

We provide support for deserializing events to typed event objects where the custom event payload is available via the `.GetPayload()` method.

If you want to have the original raw JSON event payload, you can get it via the `.Data` property.

```csharp
using Arcus.EventGrid;
using Arcus.EventGrid.Parsers;

// Parse from your custom event implementation with the `.Parse<>` function.
EventGridBatch<NewCarRegistered> eventGridBatch = EventGridParser.Parse<NewCarRegistered>(rawEvent);

// The event data type will be wrapped inside an `EventGridEvent<>` instance.
NewCarRegistered eventGridMessage = eventGridBatch.Events.First();

// The original event payload can now be accessed.
CarEventData typedEventPayload = eventGridMessage.GetPayload();
object untypedEventPayload = eventGridMessage.Data;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
---
title: "Endpoint validation"
layout: default
---

# Endpoint validation

We provide support for endpoint validation, when implementing your own custom web hook.

## Installation

The features described here require the following package:

```shell
PM> Install-Package Arcus.EventGrid.Security.WebApi
```
> **⚠ This package used to be called `Arcus.EventGrid.Security`. Please make sure that you migrate towards `Arcus.EventGrid.Security.WebApi` as it's not being actively maintained beyond v3.2.**

## Azure Event Grid authorization

Azure Event Grid authorization allows to secure your webhook 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.

### Enforce authorization globally

We created the `EventGridAuthorizationFilter` MVC filter that will secure the endpoint and handle the handshake.

```csharp
using Arcus.EventGrid.WebApi.Security;
using Microsoft.Extensions.DependencyInjection;

public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Looks for the 'x-api-key' header in the HTTP request and tries to match it with the secret retrieved in the secret store with the name 'MySecret'.
services.AddMvc(options => options.Filters.AddEventGridAuthorization(HttpRequestProperty.Header, "x-api-key", "MySecret")));
}
}
```

For this setup to work, an Arcus secret store is required as the provided secret name (in this case `"MySecret"`) will be looked up.
See [our official documentation](https://security.arcus-azure.net/features/secret-store/) for more information about setting this up.

#### Configuration

The `EventGridAuthorizationFilter` has some additional consumer-configurable options to influence the behavior of the authorization.

```csharp
using Arcus.EventGrid.WebApi.Security;
using Microsoft.Extensions.DependencyInjection;

public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Looks for the 'x-api-key' header in the HTTP request and tries to match it with the secret retrieved in the secret store with the name 'MySecret'.
services.AddMvc(options => options.Filters.AddEventGridAuthorization(HttpRequestProperty.Header, "x-api-key", "MySecret", options =>
{
// Indicates that the Azure Event Grid authorization should emit security events during the authorization of the request (default: `false`).
options.EmitSecurityEvents = true;
})));
}
}
```

### Enforce authorization per controller or operation

We created the `EventGridAuthorizationAttribute` attribute that will secure the endpoint and handle the handshake.
The attribute can be placed on both the controller as the operation.

```csharp
using Arcus.EventGrid.WebApi.Security;
using Microsoft.AspNetCore.Mvc;

[Route("events")]
[ApiController]
public class EventController : ControllerBase
{
// Looks for the 'x-api-key' header in the HTTP request and tries to match it with the secret retrieved in the secret store with the name 'MySecret'.
[EventGridAuthorization(HttpRequestProperty.Header, "x-api-key", "MySecret")]
public IHttpActionResult Get()
{
return Ok();
}
}
```

For this setup to work, an Arcus secret store is required as the provided secret name (in this case `"MySecret"`) will be looked up.
See [our official documentation](https://security.arcus-azure.net/features/secret-store/) for more information about setting this up.

#### Configuration

The `EventGridAuthorizationAttribute` attribute has some additional consumer-configurable options to influence the behavior of the authorization.

```csharp
// Indicates that the Azure Event Grid authorization should emit security events during the authorization of the request (default: `false`).
[EventGridAuthorization(..., EmitSecurityEvents = true)]
```

## Azure Event Grid subscription validation

This library provides an Azure Event Grid subscription validation. It can receive Azure Event Grid events from an Event subscription and validates the contents.
This is described in full at [the official Microsoft docs](https://docs.microsoft.com/en-us/azure/event-grid/receive-events).

### Enforce subscription validation per controller or operation

We created the `EventGridSubscriptionValidationAttribute` attribute that will validate all the incoming requests.
The attribute can be placed on both the controller as the operation.

```csharp
using Arcus.EventGrid.WebApi.Security;
using Microsoft.AspNetCore.Mvc;

[Route("events")]
[ApiController]
public class EventController : ControllerBase
{
// -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
// For CloudEvents validation:
// When receiving an HTTP OPTIONS request, looks for the `WebHook-Request-Origin` request header.
// -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
// For Azure Event Grid validation:
// Looks for the `Aeg-Event-Type` header in the HTTP request, if it contains the `SubscriptionValidation` value the request body will be deserialized and validated.
// The action attribute will short-circuit the incoming request and return the validation result as an `SubscriptionValidationResponse`
// (see: https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.eventgrid.models.subscriptionvalidationresponse?view=azure-dotnet).
// -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
[HttpGet, HttpOptions]
[EventGridSubscriptionValidation]
public IActionResult Validation()
{
return Ok();
}
}
```

### Use subscription validation in Azure Functions

The security library called `Arcus.EventGrid.Security.AzureFunctions` provides subscription validation as a dedicated service as shown in the example below.

The features described here require the following package:

```shell
PM> Install-Package Arcus.EventGrid.Security.AzureFunctions
```

Make sure you register the Azure EventGrid validation in the `Startup`:

```csharp
using Arcus.EventGrid.Security.Core;

[assembly: FunctionsStartup(typeof(Startup))]

public class Startup : FunctionsStartup
{
public void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddEventGridSubscriptionValidation();
}
}
```

This registration allows you to use the `IEventGridSubscriptionValidator` within your Azure Function:

```csharp
using Arcus.EventGrid.Security.Core.Validation;

public class AzureMonitorScaledFunction
{
private readonly IEventGridSubscriptionValidator _eventGridSubscriptionValidator

public AzureMonitorScaledFunction(IEventGridSubscriptionValidator eventGridSubscriptionValidator)
{
_eventGridSubscriptionValidator = eventGridSubscriptionValidator;
}

[FunctionName("azure-monitor-scaled-app-event")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "post", "options", Route = "v1/autoscale/azure-monitor/app")] HttpRequest request)
{
// Option #1: CloudEvents support.
if (HttpMethods.IsOptions(request.Method))
{
IActionResult result = _eventGridSubscriptionValidator.ValidateCloudEventsHandshakeRequest(request);
return result;
}

// Option #2: Azure EventGrid subscription event support.
if (request.Headers.TryGetValue("Aeg-Event-Type", out StringValues eventTypes)
&& eventTypes.Contains("SubscriptionValidation"))
{
IActionResult result = await _eventGridSubscriptionValidator.ValidateEventGridSubscriptionEventRequestAsync(request);
return result;
}

// Other logic...
}

}
```
Loading
Loading