diff --git a/claim-check/code-samples/sample-1/FunctionConsumer1/FunctionConsumer1.cs b/claim-check/code-samples/sample-1/FunctionConsumer1/FunctionConsumer1.cs index f8a59e70..6cc01ddd 100644 --- a/claim-check/code-samples/sample-1/FunctionConsumer1/FunctionConsumer1.cs +++ b/claim-check/code-samples/sample-1/FunctionConsumer1/FunctionConsumer1.cs @@ -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); } } } diff --git a/claim-check/code-samples/sample-1/FunctionConsumer1/FunctionConsumer1.csproj b/claim-check/code-samples/sample-1/FunctionConsumer1/FunctionConsumer1.csproj index c4d33d14..35555ad8 100644 --- a/claim-check/code-samples/sample-1/FunctionConsumer1/FunctionConsumer1.csproj +++ b/claim-check/code-samples/sample-1/FunctionConsumer1/FunctionConsumer1.csproj @@ -1,6 +1,6 @@ - net9.0 + net10.0 v4 Exe enable @@ -10,13 +10,13 @@ - + - + diff --git a/claim-check/code-samples/sample-1/bicep/main.bicep b/claim-check/code-samples/sample-1/bicep/main.bicep index 7e1560f5..98ce7634 100644 --- a/claim-check/code-samples/sample-1/bicep/main.bicep +++ b/claim-check/code-samples/sample-1/bicep/main.bicep @@ -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) @@ -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: { @@ -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.') @@ -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 @@ -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: { @@ -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: { diff --git a/claim-check/code-samples/sample-1/readme.md b/claim-check/code-samples/sample-1/readme.md index 94bbc669..aaf0d2c4 100644 --- a/claim-check/code-samples/sample-1/readme.md +++ b/claim-check/code-samples/sample-1/readme.md @@ -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. @@ -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) @@ -48,7 +48,7 @@ Install the prerequisites and follow the steps to deploy and run the examples. az login az account set -s - NAME_PREFIX= + NAME_PREFIX= LOCATION=eastus2 RESOURCE_GROUP_NAME="rg-${NAME_PREFIX}-${LOCATION}" @@ -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 diff --git a/claim-check/code-samples/sample-2/ClientConsumer2/ClientConsumer2.csproj b/claim-check/code-samples/sample-2/ClientConsumer2/ClientConsumer2.csproj index d99c105c..d524cd36 100644 --- a/claim-check/code-samples/sample-2/ClientConsumer2/ClientConsumer2.csproj +++ b/claim-check/code-samples/sample-2/ClientConsumer2/ClientConsumer2.csproj @@ -2,7 +2,7 @@ Exe - net9.0 + net10.0 enable enable Pnp.Samples.ClaimCheckPattern @@ -25,11 +25,10 @@ - - - - - + + + + diff --git a/claim-check/code-samples/sample-2/ClientConsumer2/SampleSettingsValidator.cs b/claim-check/code-samples/sample-2/ClientConsumer2/SampleSettingsValidator.cs index 055512f5..16a5c006 100644 --- a/claim-check/code-samples/sample-2/ClientConsumer2/SampleSettingsValidator.cs +++ b/claim-check/code-samples/sample-2/ClientConsumer2/SampleSettingsValidator.cs @@ -5,13 +5,14 @@ public static class SampleSettingsValidator /// /// Ensure the required app settings are present /// - /// + /// The list of configuration keys that must be present. /// - public static void ThrowIfMissingSettings(this IConfiguration configuration, List settings) + public static void ThrowIfMissingSettings(this IConfiguration configuration, List 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."); } } diff --git a/claim-check/code-samples/sample-2/bicep/main.bicep b/claim-check/code-samples/sample-2/bicep/main.bicep index a2d93a6e..fc38cafc 100644 --- a/claim-check/code-samples/sample-2/bicep/main.bicep +++ b/claim-check/code-samples/sample-2/bicep/main.bicep @@ -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({ @@ -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: { @@ -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: { @@ -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: { @@ -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: { @@ -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: { @@ -271,6 +271,6 @@ resource eventGridBlobCreatedEventHubSubscription 'Microsoft.EventGrid/systemTop eventDeliverySchema: 'EventGridSchema' } dependsOn:[ - gridEventHubDataOwnwerRoleAssignment + gridEventHubDataOwnerRoleAssignment ] } diff --git a/claim-check/code-samples/sample-2/readme.md b/claim-check/code-samples/sample-2/readme.md index 7e2177aa..4f8fc449 100644 --- a/claim-check/code-samples/sample-2/readme.md +++ b/claim-check/code-samples/sample-2/readme.md @@ -1,6 +1,6 @@ # Sample 2: Automatic claim check token generation with Event Grid, Event Hubs as messaging system -## Technologies used: Azure Blob Storage, Azure Event Grid, Azure Event Hub, .NET 9.0 +## Technologies used: Azure Blob Storage, Azure Event Grid, Azure Event Hub, .NET 10.0 Like in Sample 1, a reference message is automatically generated by [Event Grid](https://azure.microsoft.com/services/event-grid/) when the payload is uploaded to Azure Blob Storage. In this sample, [Event Hubs](https://learn.microsoft.com/azure/event-hubs) is used as the messaging system. @@ -8,7 +8,7 @@ Using Event Hubs enable integration with a existing Event Hub-based solutions an > 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 an Event Hub. A consumer CLI application receives the message from the queue, extracts the reference, and dowloads the blob from the storage account.](images/sample-2-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 an Event Hub. A consumer CLI application receives the message from the queue, extracts the reference, and downloads the blob from the storage account.](images/sample-2-diagram.png) 1. The payload uploaded to Azure Blob Storage. 1. A Blob Created event is generated by Event Grid. @@ -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 CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) - Optionally, an IDE, like [Visual Studio](https://visualstudio.microsoft.com/downloads/) or [Visual Studio Code](https://code.visualstudio.com/). @@ -46,7 +46,7 @@ Install the prerequisites and follow the steps to deploy and run the examples. az login az account set -s - NAME_PREFIX="" + NAME_PREFIX="" LOCATION=eastus2 RESOURCE_GROUP_NAME="rg-${NAME_PREFIX}-${LOCATION}" @@ -81,7 +81,7 @@ Install the prerequisites and follow the steps to deploy and run the examples. ### :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 diff --git a/claim-check/code-samples/sample-3/FunctionConsumer3/FunctionConsumer3.csproj b/claim-check/code-samples/sample-3/FunctionConsumer3/FunctionConsumer3.csproj index 9ecdf5f3..5ccc8b7a 100644 --- a/claim-check/code-samples/sample-3/FunctionConsumer3/FunctionConsumer3.csproj +++ b/claim-check/code-samples/sample-3/FunctionConsumer3/FunctionConsumer3.csproj @@ -1,6 +1,6 @@ - net9.0 + net10.0 v4 Exe enable @@ -10,13 +10,13 @@ - + - + diff --git a/claim-check/code-samples/sample-3/bicep/main.bicep b/claim-check/code-samples/sample-3/bicep/main.bicep index 8a726b7e..e36392d0 100644 --- a/claim-check/code-samples/sample-3/bicep/main.bicep +++ b/claim-check/code-samples/sample-3/bicep/main.bicep @@ -14,19 +14,19 @@ param principalId string param namePrefix string @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 Service Bus to grant "Service Bus Data Owner" privileges.') -resource serviceBusDataOwnwerRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { +resource serviceBusDataOwnerRole 'Microsoft.Authorization/roleDefinitions@2022-05-01-preview' existing = { name: '090c5cfd-751d-490a-894a-3ce6f1109419' scope: subscription() } @description('Allows for receive access to Azure Service Bus resources.') -resource serviceBusDataReceiverRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { +resource serviceBusDataReceiverRole 'Microsoft.Authorization/roleDefinitions@2022-05-01-preview' existing = { name: '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0' scope: subscription() } @@ -34,7 +34,7 @@ resource serviceBusDataReceiverRole 'Microsoft.Authorization/roleDefinitions@202 /*** 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' = { +resource storageAccount 'Microsoft.Storage/storageAccounts@2025-06-01' = { name: 'st${namePrefix}cc' location: location sku: { @@ -87,7 +87,7 @@ resource blobContributorRoleAssignment 'Microsoft.Authorization/roleAssignments@ } @description('The Azure Event Grid system topic to use with the sample apps. This will be used to forward BlobCreated events to the Service Bus Queue.') -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: { @@ -99,7 +99,7 @@ resource eventGridStorageBlobTopic 'Microsoft.EventGrid/systemTopics@2023-12-15- } } -resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2021-12-01-preview' = { +resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2025-07-01' = { name: 'la-${namePrefix}' location: location properties: { @@ -114,7 +114,7 @@ resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2021-12-01-previ } @description('The Azure Service Bus namespace to use with the sample apps.') -resource serviceBusNamespace 'Microsoft.ServiceBus/namespaces@2022-10-01-preview' = { +resource serviceBusNamespace 'Microsoft.ServiceBus/namespaces@2025-05-01-preview' = { name: 'sbns-${namePrefix}' location: location sku: { @@ -174,18 +174,18 @@ resource userServiceBusDataReceiverRoleAssignment 'Microsoft.Authorization/roleA @description('Set permissions to give the Event Grid System Managed identity access to Service Bus') resource gridServiceBusDataOwnwerRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(serviceBusNamespace.id, serviceBusDataOwnwerRole.id, eventGridStorageBlobTopic.id) + name: guid(serviceBusNamespace.id, serviceBusDataOwnerRole.id, eventGridStorageBlobTopic.id) scope: serviceBusNamespace properties: { principalId: eventGridStorageBlobTopic.identity.principalId - roleDefinitionId: serviceBusDataOwnwerRole.id + roleDefinitionId: serviceBusDataOwnerRole.id principalType: 'ServicePrincipal' description: 'Allows this Microsoft Entra principal to access Event Hub data.' } } @description('Event Grid subscription to forward BlobCreated events to our Service Bus Queue.') -resource eventGridBlobCreatedServiceBusSubscription 'Microsoft.EventGrid/systemTopics/eventSubscriptions@2023-12-15-preview' = { +resource eventGridBlobCreatedServiceBusSubscription 'Microsoft.EventGrid/systemTopics/eventSubscriptions@2025-04-01-preview' = { parent: eventGridStorageBlobTopic name: 'eventhub' properties: { diff --git a/claim-check/code-samples/sample-3/readme.md b/claim-check/code-samples/sample-3/readme.md index 2e5e08f9..a0d9dc5f 100644 --- a/claim-check/code-samples/sample-3/readme.md +++ b/claim-check/code-samples/sample-3/readme.md @@ -1,6 +1,6 @@ # Sample 3: Automatic claim check token generation with Event Grid, Service Bus as messaging system -## Technologies used: Azure Blob Storage, Azure Event Grid, Azure Service Bus, Azure Functions, .NET 9.0 +## Technologies used: Azure Blob Storage, Azure Event Grid, Azure Service Bus, Azure Functions, .NET 10.0 Like in samples 1 and 2, a reference message is automatically generated by [Event Grid](https://azure.microsoft.com/services/event-grid/) when the payload is uploaded to Azure Blob Storage. In this sample, [Service Bus](https://learn.microsoft.com/azure/service-bus) is used as the messaging system. @@ -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) @@ -48,7 +48,7 @@ Install the prerequisites and follow the steps to deploy and run the examples. az login az account set -s - NAME_PREFIX= + NAME_PREFIX= LOCATION=eastus2 RESOURCE_GROUP_NAME="rg-${NAME_PREFIX}-${LOCATION}" @@ -77,20 +77,20 @@ 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 Service Bus. - 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 Service Bus 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 Service Bus queue and process messages as they arrive. - Two applications are provided as sample that illustrate consuming the claim check message sent via Azure Event Hubs: one implemented as a Command Line Interface (CLI) application, and the other one implemented as an Azure Function, showcasing the serveless approach. + Two sample applications illustrate consuming the claim check message sent via Azure Service Bus: one implemented as a Command Line Interface (CLI) application and the other as an Azure Function, showcasing the serverless approach. ```bash cd FunctionConsumer3 - func start + func start --dotnet-isolated ``` - > Please note: For demo purposes, the sample application will write the payload content to the the screen. Keep that in mind before you try sending really large payloads. + > Please note: For demo purposes, the sample application will write the payload content to 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 diff --git a/claim-check/code-samples/sample-4/ClientProducer4/ClientProducer4.csproj b/claim-check/code-samples/sample-4/ClientProducer4/ClientProducer4.csproj index af077a13..8bbbef92 100644 --- a/claim-check/code-samples/sample-4/ClientProducer4/ClientProducer4.csproj +++ b/claim-check/code-samples/sample-4/ClientProducer4/ClientProducer4.csproj @@ -1,7 +1,7 @@ Exe - net9.0 + net10.0 enable enable Pnp.Samples.ClaimCheckPattern @@ -23,11 +23,10 @@ - - + + - - - + + diff --git a/claim-check/code-samples/sample-4/FunctionConsumer4/FunctionConsumer4.csproj b/claim-check/code-samples/sample-4/FunctionConsumer4/FunctionConsumer4.csproj index ac5ecb4a..3242252c 100644 --- a/claim-check/code-samples/sample-4/FunctionConsumer4/FunctionConsumer4.csproj +++ b/claim-check/code-samples/sample-4/FunctionConsumer4/FunctionConsumer4.csproj @@ -1,6 +1,6 @@ - net9.0 + net10.0 v4 Exe enable @@ -9,13 +9,13 @@ - + - + diff --git a/claim-check/code-samples/sample-4/bicep/main.bicep b/claim-check/code-samples/sample-4/bicep/main.bicep index f6c4baf8..f4ed04f0 100644 --- a/claim-check/code-samples/sample-4/bicep/main.bicep +++ b/claim-check/code-samples/sample-4/bicep/main.bicep @@ -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: { @@ -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: { @@ -98,7 +98,7 @@ resource blobContributorRoleAssignment 'Microsoft.Authorization/roleAssignments@ } @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: { @@ -156,12 +156,12 @@ resource eventHubDiagnostics 'Microsoft.Insights/diagnosticSettings@2021-05-01-p } @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.' } diff --git a/claim-check/code-samples/sample-4/readme.md b/claim-check/code-samples/sample-4/readme.md index 35e75209..ad11710b 100644 --- a/claim-check/code-samples/sample-4/readme.md +++ b/claim-check/code-samples/sample-4/readme.md @@ -1,21 +1,21 @@ # Sample 4: Manual token generation, Azure Event Hubs with Kafka as messaging system -## Technologies used: Azure Blob Storage, Azure Event Hubs with Kafka API enabled, Azure Functions, .NET 9.0 +## Technologies used: Azure Blob Storage, Azure Event Hubs with Kafka API enabled, Azure Functions, .NET 10.0 In this example the client application uploads the payload to Azure Blob Storage and manually generates the claim check token, which is sent via Event Hubs. -The sample producer CLI application uses the Apache Kafka libraries to send the messages to [Event Hubs with Kafka enabled](https://learn.microsoft.com/azure/event-hubs/event-hubs-create-kafka-enabled), to demonstrate the ease of using other Azure services like Azure Blob Storage, Azure functions etc. with a different messaging protocol like Kafka. The Azure Function is used to demonstrate a client application that acts as the consumer for the payload. +The sample producer CLI application uses the Apache Kafka libraries to send messages to [Event Hubs with Kafka enabled](https://learn.microsoft.com/azure/event-hubs/event-hubs-create-kafka-enabled), demonstrating how to use Azure services such as Azure Blob Storage and Azure Functions, etc., with a different messaging protocol such as Kafka. The Azure Function demonstrates a consumer application for the payload. -> 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 a client CLI application acting as a producer and an Azure Function as the consumer, with Azure Blob Storage serving as the data store and Event Hubs as the messaging syste. The producer uploads the payload to Blob Storage, manually creates the claim-check message containing the blob location, and sends the message using the Kafka API to Event Hubs. The consumer Function receives the message from Event Hubs, extracts the reference, and dowloads the blob from the storage account.](images/sample-4-diagram.png) +![A diagram showing a client CLI application acting as a producer and an Azure Function as the consumer, with Azure Blob Storage serving as the data store and Event Hubs as the messaging system. The producer uploads the payload to Blob Storage, manually creates the claim-check message containing the blob location, and sends the message using the Kafka API to Event Hubs. The consumer Function receives the message from Event Hubs, extracts the reference, and downloads the blob from the storage account.](images/sample-4-diagram.png) 1. The producer CLI application uploads the payload to Azure Blob Storage. 1. The producer creates the claim-check message containing the blob location, and sends the message using the Kafka API to Event Hubs. 1. The consumer Function receives the message from Event Hubs. 1. The Function extracts the reference to the payload blob from the message and downloads the blob directly from storage. -## :rocket: Deployment guide +## :rocket: Deployment Guide Install the prerequisites and follow the steps to deploy and run the examples. @@ -26,11 +26,11 @@ 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) -- Optionally, an IDE, like [Visual Studio](https://visualstudio.microsoft.com/downloads/) or [Visual Studio Code](https://code.visualstudio.com/). +- Optionally, an IDE, like [Visual Studio](https://visualstudio.microsoft.com/downloads/) or [Visual Studio Code](https://code.visualstudio.com/). ### Steps @@ -47,7 +47,7 @@ Install the prerequisites and follow the steps to deploy and run the examples. az login az account set -s - NAME_PREFIX= + NAME_PREFIX= LOCATION=eastus2 RESOURCE_GROUP_NAME="rg-${NAME_PREFIX}-${LOCATION}" @@ -80,10 +80,10 @@ Install the prerequisites and follow the steps to deploy and run the examples. ```bash cd ./FunctionConsumer4 - func start + func start --dotnet-isolated ``` - > Please note: For demo purposes, the sample application will write the payload content to the the screen. Keep that in mind before you try sending really large payloads. +> Please note: For demo purposes, the sample application will write the payload content to the screen. Keep that in mind before you try sending really large payloads. ### :checkered_flag: Try it out