| | 1 | | // Copyright (c) Microsoft Corporation. All rights reserved. |
| | 2 | | // Licensed under the MIT License. |
| | 3 | |
|
| | 4 | | using System; |
| | 5 | | using System.Text; |
| | 6 | | using System.Threading; |
| | 7 | | using System.Threading.Tasks; |
| | 8 | | using Azure.Identity; |
| | 9 | | using Azure.Messaging.EventHubs.Consumer; |
| | 10 | | using Azure.Messaging.EventHubs.Producer; |
| | 11 | | using Azure.Messaging.EventHubs.Samples.Infrastructure; |
| | 12 | |
|
| | 13 | | namespace Azure.Messaging.EventHubs.Samples |
| | 14 | | { |
| | 15 | | /// <summary> |
| | 16 | | /// An example of publishing and reading from an Event Hub using an Azure Active Directory application |
| | 17 | | /// with a client secret for authorization. |
| | 18 | | /// </summary> |
| | 19 | | /// |
| | 20 | | /// <remarks> |
| | 21 | | /// This sample requires a service principal in addition to the Event Hubs environment used for |
| | 22 | | /// samples. The following script may be used to create all the resources needed to run this sample that can be f |
| | 23 | | /// https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/eventhub/Azure.Messaging.EventHubs/assets/identity- |
| | 24 | | /// </remarks> |
| | 25 | | /// |
| | 26 | | /// <seealso href="https://docs.microsoft.com/en-us/azure/active-directory/develop/app-objects-and-service-principal |
| | 27 | | /// <seealso href="https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow |
| | 28 | | /// |
| | 29 | | public class Sample12_AuthenticateWithClientSecretCredential : IEventHubsIdentitySample |
| | 30 | | { |
| | 31 | | /// <summary> |
| | 32 | | /// The name of the sample. |
| | 33 | | /// </summary> |
| | 34 | | /// |
| 0 | 35 | | public string Name => nameof(Sample12_AuthenticateWithClientSecretCredential); |
| | 36 | |
|
| | 37 | | /// <summary> |
| | 38 | | /// A short description of the sample. |
| | 39 | | /// </summary> |
| | 40 | | /// |
| 0 | 41 | | public string Description => "An example of interacting with an Event Hub using an Azure Active Directory applic |
| | 42 | |
|
| | 43 | | /// <summary> |
| | 44 | | /// Runs the sample using the specified Event Hubs connection information. |
| | 45 | | /// </summary> |
| | 46 | | /// |
| | 47 | | /// <param name="fullyQualifiedNamespace">The fully qualified Event Hubs namespace. This is likely to be simila |
| | 48 | | /// <param name="eventHubName">The name of the Event Hub, sometimes known as its path, that the sample should ru |
| | 49 | | /// <param name="tenantId">The Azure Active Directory tenant that holds the service principal.</param> |
| | 50 | | /// <param name="clientId">The Azure Active Directory client identifier of the service principal.</param> |
| | 51 | | /// <param name="secret">The Azure Active Directory secret of the service principal.</param> |
| | 52 | | /// |
| | 53 | | public async Task RunAsync(string fullyQualifiedNamespace, |
| | 54 | | string eventHubName, |
| | 55 | | string tenantId, |
| | 56 | | string clientId, |
| | 57 | | string secret) |
| | 58 | | { |
| 0 | 59 | | int eventsPublished = 0; |
| 0 | 60 | | int eventsRead = 0; |
| | 61 | |
|
| | 62 | | // Service principal authentication is a means for applications to authenticate against Azure Active |
| | 63 | | // Directory and consume Azure services. This is advantageous compared to using a connection string for |
| | 64 | | // authorization, as it offers a far more robust mechanism for transparently updating credentials in place, |
| | 65 | | // without an application being explicitly aware or involved. |
| | 66 | | // |
| | 67 | | // For this example, we'll take advantage of a service principal to publish and receive events. To do so, w |
| | 68 | | // use of the ClientSecretCredential from the Azure.Identity library to enable the Event Hubs clients to per |
| | 69 | | // using a service principal. |
| | 70 | |
|
| 0 | 71 | | ClientSecretCredential credential = new ClientSecretCredential(tenantId, clientId, secret); |
| | 72 | |
|
| | 73 | | // To start, we'll publish a small number of events using a producer client. To ensure that our client is a |
| | 74 | | // take advantage of the asynchronous dispose when we are done or when an exception is encountered. |
| | 75 | |
|
| 0 | 76 | | await using (var producerClient = new EventHubProducerClient(fullyQualifiedNamespace, eventHubName, credenti |
| | 77 | | { |
| 0 | 78 | | using EventDataBatch eventBatch = await producerClient.CreateBatchAsync(); |
| 0 | 79 | | eventBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes("Hello, Event Hubs!"))); |
| 0 | 80 | | eventBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes("The middle event is this one"))); |
| 0 | 81 | | eventBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes("Goodbye, Event Hubs!"))); |
| | 82 | |
|
| 0 | 83 | | await producerClient.SendAsync(eventBatch); |
| | 84 | |
|
| 0 | 85 | | eventsPublished = eventBatch.Count; |
| 0 | 86 | | Console.WriteLine("The event batch has been published."); |
| 0 | 87 | | } |
| | 88 | |
|
| | 89 | | // With our events published, we'll create a consumer client to read them. We'll stop reading after we've r |
| | 90 | | // batch. |
| | 91 | |
|
| 0 | 92 | | await using (var consumerClient = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName |
| | 93 | | { |
| | 94 | | // To ensure that we do not wait for an indeterminate length of time, we'll stop reading after we receiv |
| | 95 | | // fresh Event Hub, those will be the three that we had published. We'll also ask for cancellation afte |
| | 96 | | // safe. |
| | 97 | |
|
| 0 | 98 | | using CancellationTokenSource cancellationSource = new CancellationTokenSource(); |
| 0 | 99 | | cancellationSource.CancelAfter(TimeSpan.FromSeconds(60)); |
| | 100 | |
|
| 0 | 101 | | await foreach (PartitionEvent partitionEvent in consumerClient.ReadEventsAsync(cancellationSource.Token) |
| | 102 | | { |
| 0 | 103 | | Console.WriteLine($"Event Read: { Encoding.UTF8.GetString(partitionEvent.Data.Body.ToArray()) }"); |
| 0 | 104 | | eventsRead++; |
| | 105 | |
|
| 0 | 106 | | if (eventsRead >= eventsPublished) |
| | 107 | | { |
| | 108 | | break; |
| | 109 | | } |
| | 110 | | } |
| 0 | 111 | | } |
| | 112 | |
|
| 0 | 113 | | Console.WriteLine(); |
| 0 | 114 | | } |
| | 115 | | } |
| | 116 | | } |