Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public async Task RunAsync(

// download the payload
var payload = await _downloader.DownloadAsync(payloadUri);
_logger.LogInformation("Payload content (Url {Uri)}\n {Payload}", payloadUri, payload);
_logger.LogInformation("Payload content (Url {Uri})\n {Payload}", payloadUri, payload);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
Expand All @@ -10,13 +10,13 @@
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.27.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.2.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.51.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Storage" Version="6.8.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues" Version="5.5.3" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="2.0.7" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="2.1.0" />
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.23.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="2.0.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="2.50.0" />
<PackageReference Include="Azure.Identity" Version="1.17.1" />
</ItemGroup>

Expand Down
20 changes: 10 additions & 10 deletions claim-check/code-samples/sample-1/bicep/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ targetScope = 'resourceGroup'
param location string = resourceGroup().location

@minLength(36)
@description('The guid of the principal running the valet key generation code. In Azure this would be replaced with the managed identity of the Azure Function, when running locally it will be your user.')
@description('The GUID of the principal running the valet key generation code. In Azure this would be replaced with the managed identity of the Azure Function, when running locally it will be your user.')
param principalId string

@minLength(3)
Expand All @@ -16,21 +16,21 @@ param namePrefix string
/*** EXISTING RESOURCES ***/

@description('Built-in Azure RBAC role that is applied to a Storage account to grant "Storage Blob Data Contributor" privileges.')
resource storageBlobDataContributorRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
resource storageBlobDataContributorRole 'Microsoft.Authorization/roleDefinitions@2022-05-01-preview' existing = {
name: 'ba92f5b4-2d11-453d-a403-e96b0029c9fe'
scope: subscription()
}

@description('Built-in Azure RBAC role that is applied to a Storage account to grant "Storage Queue Data Contributor" privileges.')
resource storageQueueDataContributorRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
resource storageQueueDataContributorRole 'Microsoft.Authorization/roleDefinitions@2022-05-01-preview' existing = {
name: '974c5e8b-45b9-4653-ba55-5f855dd0fb88'
scope: subscription()
}

/*** NEW RESOURCES ***/

@description('The Azure Storage account which will be where authorized clients upload large blobs to. The Azure Function will hand out scoped, time-limited SaS tokens for this blobs in this account.')
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
@description('The Azure Storage account which will be where authorized clients upload large blobs to. The Azure Function will hand out scoped, time-limited SAS tokens for this blobs in this account.')
resource storageAccount 'Microsoft.Storage/storageAccounts@2025-06-01' = {
name: 'st${namePrefix}cc'
location: location
sku: {
Expand Down Expand Up @@ -69,7 +69,7 @@ resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
}
}

resource QueueServices 'queueServices' = {
resource queueServices 'queueServices' = {
name: 'default'

@description('The queue to serve as the message queue for the sample.')
Expand All @@ -93,8 +93,8 @@ resource blobContributorRoleAssignment 'Microsoft.Authorization/roleAssignments@

@description('Set permissions to give the user principal access to Storage Queues from the sample applications')
resource queueContributorRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(storageAccount::QueueServices::claimcheckqueue.id, storageQueueDataContributorRole.id, principalId)
scope: storageAccount::QueueServices::claimcheckqueue
name: guid(storageAccount::queueServices::claimcheckqueue.id, storageQueueDataContributorRole.id, principalId)
scope: storageAccount::queueServices::claimcheckqueue
properties: {
principalId: principalId
roleDefinitionId: storageQueueDataContributorRole.id
Expand All @@ -104,7 +104,7 @@ resource queueContributorRoleAssignment 'Microsoft.Authorization/roleAssignments
}

@description('Event Grid system topic to subscribe to blob created events.')
resource eventGridStorageBlobTopic 'Microsoft.EventGrid/systemTopics@2023-12-15-preview' = {
resource eventGridStorageBlobTopic 'Microsoft.EventGrid/systemTopics@2025-04-01-preview' = {
name: '${storageAccount.name}${guid(namePrefix, 'storage')}'
location: location
identity: {
Expand All @@ -117,7 +117,7 @@ resource eventGridStorageBlobTopic 'Microsoft.EventGrid/systemTopics@2023-12-15-
}

@description('Event Grid system topic subscription to queue blob created events.')
resource eventGridBlobCreatedQueueSubscription 'Microsoft.EventGrid/systemTopics/eventSubscriptions@2023-12-15-preview' = {
resource eventGridBlobCreatedQueueSubscription 'Microsoft.EventGrid/systemTopics/eventSubscriptions@2025-04-01-preview' = {
parent: eventGridStorageBlobTopic
name: 'storagequeue'
properties: {
Expand Down
20 changes: 10 additions & 10 deletions claim-check/code-samples/sample-1/readme.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Sample 1: Automatic claim check token generation with Event Grid, Azure Queue Storage as messaging system
# Sample 1: Automatic claim check token generation with Event Grid, Azure Queue Storage as the messaging system

## Technologies used: Azure Blob Storage, Azure Event Grid, Azure Functions, Azure Queue Storage, .NET 9.0
## Technologies used: Azure Blob Storage, Azure Event Grid, Azure Functions, Azure Queue Storage, .NET 10.0

This example uses Azure Blob Storage to store the payload, but any service that supports [Event Grid](https://azure.microsoft.com/services/event-grid/) integration can be used. A client application uploads the payload to Azure Blob Store and Event Grid automatically generates an event, with a reference to the blob, that can be used as a claim check token. The event is forwarded to an Azure Queue Storage queue from where it can be retrieved by the consumer sample app.

This approach allows a client application to poll the queue, get the message, extract the reference to the payload blob, and use it to download the payload directly from Azure Blob Storage. Azure Functions can also consume the Event Grid message directly.

> This example uses [`DefaultAzureCredential`](https://learn.microsoft.com/dotnet/azure/sdk/authentication/#defaultazurecredential) for authentication while accessing Azure resources. the user principal must be provided as a parameter to the included Bicep script. The Bicep script is responsible for assigning the necessary RBAC (Role-Based Access Control) permissions for accessing the various Azure resources. While the principal can be the account associated with the interactive user, there are alternative [configurations](https://learn.microsoft.com/dotnet/azure/sdk/authentication/?tabs=command-line#exploring-the-sequence-of-defaultazurecredential-authentication-methods) available.
> This example uses [`DefaultAzureCredential`](https://learn.microsoft.com/dotnet/azure/sdk/authentication/#defaultazurecredential) for authentication while accessing Azure resources. The user principal must be provided as a parameter to the included Bicep script. The Bicep script is responsible for assigning the necessary RBAC (Role-Based Access Control) permissions for accessing the various Azure resources. While the principal can be the account associated with the interactive user, there are alternative [configurations](https://learn.microsoft.com/dotnet/azure/sdk/authentication/?tabs=command-line#exploring-the-sequence-of-defaultazurecredential-authentication-methods) available.

![A diagram showing Event Grid connected to Azure Blob Storage. As blobs are created, Event Grid forwards a message, containing the reference to the blob, to Azure Queue Storage. A consumer Function receives the message from the queue, extracts the reference, and dowloads the blob from the storage account.](images/sample-1-diagram.png)
![A diagram showing Event Grid connected to Azure Blob Storage. As blobs are created, Event Grid forwards a message, containing the reference to the blob, to Azure Queue Storage. A consumer Function receives the message from the queue, extracts the reference, and downloads the blob from the storage account.](images/sample-1-diagram.png)

1. The payload uploaded to Azure Blob Storage.
1. A Blob Created event is generated by Event Grid.
Expand All @@ -27,7 +27,7 @@ Install the prerequisites and follow the steps to deploy and run the examples.
- [Azure Cloud Shell](https://shell.azure.com/)
- [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/windows/wsl/install)
- [Git](https://git-scm.com/downloads)
- [.NET 9 SDK](https://dotnet.microsoft.com/download/dotnet/9.0)
- [.NET 10 SDK](https://dotnet.microsoft.com/download/dotnet/10.0)
- [Azure Functions Core Tools](https://learn.microsoft.com/azure/azure-functions/functions-run-local#install-the-azure-functions-core-tools)
- [Azurite](/azure/storage/common/storage-use-azurite)
- [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli)
Expand All @@ -48,7 +48,7 @@ Install the prerequisites and follow the steps to deploy and run the examples.
az login
az account set -s <Name or ID of subscription>

NAME_PREFIX=<unique value between three to five characters>
NAME_PREFIX=<unique value between three to five characters lowercase>
LOCATION=eastus2
RESOURCE_GROUP_NAME="rg-${NAME_PREFIX}-${LOCATION}"

Expand Down Expand Up @@ -76,18 +76,18 @@ Install the prerequisites and follow the steps to deploy and run the examples.

1. Launch the consumer sample application to receive and process claim check messages from Azure Queue Storage.

The message consumer sample application for this scenario is implemented as an Azure Function, showcasing the serveless approach. Run the sample application to connect to the the queue and process messages as they arrive.
The message consumer sample application for this scenario is implemented as an Azure Function, showcasing the serverless approach. Run the sample application to connect to the queue and process messages as they arrive.

```bash
cd sample-1\FunctionConsumer1
func start
cd FunctionConsumer1
func start --dotnet-isolated
```

> Please note: For demo purposes, the sample consumer application will write the payload content to the the screen. Keep that in mind before you try sending really large payloads.

### :checkered_flag: Try it out

To generate a claim check message you just have to drop a file in the created Azure Storage account. You can use Azure **Storage browser** to do that. [Refer this to know how to upload blobs to a container using Storage Explorer](https://learn.microsoft.com/azure/storage/blobs/quickstart-storage-explorer#upload-blobs-to-the-container).
To generate a claim check message you just have to drop a file in the created Azure Storage account. You can use Azure **Storage browser** to do that. [Refer this to know how to upload blobs to a container using Storage Explorer](https://learn.microsoft.com/azure/storage/blobs/quickstart-storage-explorer#upload-blobs-to-the-container). Inside the **payloads** Container.

### :broom: Clean up

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>Pnp.Samples.ClaimCheckPattern</RootNamespace>
Expand All @@ -25,11 +25,10 @@
<PackageReference Include="Azure.Messaging.EventHubs" Version="5.12.2" />
<PackageReference Include="Azure.Messaging.EventHubs.Processor" Version="5.12.2" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.27.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.10" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.10" />
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.10" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.10" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="10.0.2" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ public static class SampleSettingsValidator
/// <summary>
/// Ensure the required app settings are present
/// </summary>
/// <param name="settings"></param>
/// <param name="requiredSettings">The list of configuration keys that must be present.</param>
/// <exception cref="ApplicationException"></exception>
public static void ThrowIfMissingSettings(this IConfiguration configuration, List<string> settings)
public static void ThrowIfMissingSettings(this IConfiguration configuration, List<string> requiredSettings)
{
if (settings.Any(option => string.IsNullOrWhiteSpace(configuration.GetSection(option).Value)))
var missingSettings = requiredSettings.Where(option => string.IsNullOrWhiteSpace(configuration.GetSection(option).Value)).ToList();
if (missingSettings.Any())
{
throw new ApplicationException($"Configure options {string.Join(", ", settings)} in appsettings.json and run again.");
throw new ApplicationException($"Configure required options {string.Join(", ", missingSettings)} in appsettings.json and run again.");
}
}

Expand Down
30 changes: 15 additions & 15 deletions claim-check/code-samples/sample-2/bicep/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,20 @@ param namePrefix string
/*** EXISTING RESOURCES ***/

@description('Built-in Azure RBAC role that is applied to a Storage account to grant "Storage Blob Data Contributor" privileges.')
resource storageBlobDataContributorRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
resource storageBlobDataContributorRole 'Microsoft.Authorization/roleDefinitions@2022-05-01-preview' existing = {
name: 'ba92f5b4-2d11-453d-a403-e96b0029c9fe'
scope: subscription()
}

@description('Built-in Azure RBAC role that is applied to an Event Hub to grant "Azure Event Hubs Data Owner" privileges.')
resource eventHubDataOwnwerRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
resource eventHubDataOwnerRole 'Microsoft.Authorization/roleDefinitions@2022-05-01-preview' existing = {
name: 'f526a384-b230-433a-b45c-95f59c4a2dec'
scope: subscription()
}

/*** NEW RESOURCES ***/

resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2021-12-01-preview' = {
resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2025-07-01' = {
name: 'la-${namePrefix}'
location: location
properties: any({
Expand All @@ -44,7 +44,7 @@ resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2021-12-01-previ
}

@description('The Azure Storage account which will be where authorized clients upload large blobs to. The Azure Function will hand out scoped, time-limited SaS tokens for this blobs in this account.')
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
resource storageAccount 'Microsoft.Storage/storageAccounts@2025-06-01' = {
name: 'st${namePrefix}cc'
location: location
sku: {
Expand Down Expand Up @@ -97,7 +97,7 @@ resource blobContributorRoleAssignment 'Microsoft.Authorization/roleAssignments@
}

@description('The Azure Event Grid system topic to use with the sample apps. This topic will be used to forward BlobCreated events to the Azure Event Hub.')
resource eventGridStorageBlobTopic 'Microsoft.EventGrid/systemTopics@2023-12-15-preview' = {
resource eventGridStorageBlobTopic 'Microsoft.EventGrid/systemTopics@2025-04-01-preview' = {
name: '${storageAccount.name}${guid(namePrefix, 'storage')}'
location: location
identity: {
Expand All @@ -110,7 +110,7 @@ resource eventGridStorageBlobTopic 'Microsoft.EventGrid/systemTopics@2023-12-15-
}

@description('The Azure Storage account to use together with Event Hubs. Used to support the functionality of the EventProcessor class')
resource eventHubStorageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
resource eventHubStorageAccount 'Microsoft.Storage/storageAccounts@2025-06-01' = {
name: 'st${namePrefix}ehub'
location: location
sku: {
Expand Down Expand Up @@ -167,7 +167,7 @@ resource eventProcessorBlobContributorRoleAssignment 'Microsoft.Authorization/ro
}

@description('The Azure Event Hubs namespace to use with the sample apps.')
resource eventHubNamespace 'Microsoft.EventHub/namespaces@2023-01-01-preview' = {
resource eventHubNamespace 'Microsoft.EventHub/namespaces@2025-05-01-preview' = {
name: 'evhns-${namePrefix}'
location: location
sku: {
Expand Down Expand Up @@ -224,31 +224,31 @@ resource eventHubDiagnostics 'Microsoft.Insights/diagnosticSettings@2021-05-01-p
}

@description('Set permissions to give the Event Grid System Managed identity access to Event Hub')
resource gridEventHubDataOwnwerRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(eventHubNamespace.id, eventHubDataOwnwerRole.id, eventGridStorageBlobTopic.id)
resource gridEventHubDataOwnerRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(eventHubNamespace.id, eventHubDataOwnerRole.id, eventGridStorageBlobTopic.id)
scope: eventHubNamespace
properties: {
principalId: eventGridStorageBlobTopic.identity.principalId
roleDefinitionId: eventHubDataOwnwerRole.id
roleDefinitionId: eventHubDataOwnerRole.id
principalType: 'ServicePrincipal'
description: 'Allows this Microsoft Entra principal to access Event Hub data.'
}
}

@description('Set permissions to give the user principal access to Event Hub')
resource userEventHubDataOwnwerRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(eventHubNamespace.id, eventHubDataOwnwerRole.id, principalId)
resource userEventHubDataOwnerRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(eventHubNamespace.id, eventHubDataOwnerRole.id, principalId)
scope: eventHubNamespace
properties: {
principalId: principalId
roleDefinitionId: eventHubDataOwnwerRole.id
roleDefinitionId: eventHubDataOwnerRole.id
principalType: 'User'
description: 'Allows this Microsoft Entra principal to access Event Hub data.'
}
}

@description('Event Grid subscription to forward BlobCreated events to our Azure Hub.')
resource eventGridBlobCreatedEventHubSubscription 'Microsoft.EventGrid/systemTopics/eventSubscriptions@2023-12-15-preview' = {
resource eventGridBlobCreatedEventHubSubscription 'Microsoft.EventGrid/systemTopics/eventSubscriptions@2025-04-01-preview' = {
parent: eventGridStorageBlobTopic
name: 'eventhub'
properties: {
Expand All @@ -271,6 +271,6 @@ resource eventGridBlobCreatedEventHubSubscription 'Microsoft.EventGrid/systemTop
eventDeliverySchema: 'EventGridSchema'
}
dependsOn:[
gridEventHubDataOwnwerRoleAssignment
gridEventHubDataOwnerRoleAssignment
]
}
Loading