private (string eventHubNamespaceFQDN, string eventHubName) GetEventHubProperties(EventHubClientOptions eventHubClientOptions)
        {
            // If the authentication type for the event hub is ConnectionString, then parse the event hub properties (eventHubNamspaceFQDN and eventHubName) from the provided connection string,
            // else return the supplied eventHubClientOptions properties for eventHubNamspaceFQDN and eventHubOptions.
            var eventHubNamespaceFQDN = eventHubClientOptions.EventHubNamespaceFQDN;
            var eventHubName          = eventHubClientOptions.EventHubName;

            if (eventHubClientOptions.AuthenticationType == AuthenticationType.ConnectionString)
            {
                EnsureArg.IsNotNull(eventHubClientOptions.ConnectionString, nameof(eventHubClientOptions.ConnectionString));

                try
                {
                    var eventHubsConnectionStringProperties = EventHubsConnectionStringProperties.Parse(eventHubClientOptions.ConnectionString);
                    eventHubNamespaceFQDN = eventHubsConnectionStringProperties.FullyQualifiedNamespace;
                    eventHubName          = eventHubsConnectionStringProperties.EventHubName;
                }
#pragma warning disable CA1031
                catch (Exception ex)
#pragma warning restore CA1031
                {
                    _log.LogError(new Exception($"Unable to parse event hub properties. {ex.Message}"));
                }
            }

            return(eventHubNamespaceFQDN, eventHubName);
        }
        public void ValidateAllowsMultipleEventHubNamesIfEqual()
        {
            var eventHubName   = "myHub";
            var fakeConnection = $"Endpoint=sb://not-real.servicebus.windows.net/;SharedAccessKeyName=DummyKey;SharedAccessKey=[not_real];EntityPath={ eventHubName }";
            var properties     = EventHubsConnectionStringProperties.Parse(fakeConnection);

            Assert.That(() => properties.Validate(eventHubName, "dummy"), Throws.Nothing, "Validation should accept the same Event Hub in multiple places.");
        }
        public void ValidateAllowsSharedAccessSignatureAuthorization()
        {
            var eventHubName   = "myHub";
            var fakeConnection = "Endpoint=sb://not-real.servicebus.windows.net/;SharedAccessSignature=[not_real]";
            var properties     = EventHubsConnectionStringProperties.Parse(fakeConnection);

            Assert.That(() => properties.Validate(eventHubName, "dummy"), Throws.Nothing, "Validation should accept the shared access signature authorization.");
        }
        public void ValidateDetectsMultipleEventHubNames()
        {
            var eventHubName   = "myHub";
            var fakeConnection = "Endpoint=sb://not-real.servicebus.windows.net/;SharedAccessKeyName=DummyKey;SharedAccessKey=[not_real];EntityPath=[unique_fake]";
            var properties     = EventHubsConnectionStringProperties.Parse(fakeConnection);

            Assert.That(() => properties.Validate(eventHubName, "Dummy"), Throws.ArgumentException.And.Message.StartsWith(Resources.OnlyOneEventHubNameMayBeSpecified));
        }
예제 #5
0
        private IEventHubClient CreateEventHubClient(EventHubOutputConfiguration _)
        {
            Debug.Assert(this.outputConfiguration != null);

            if (this.outputConfiguration.UseAzureIdentity)
            {
                this.eventHubName = this.outputConfiguration.EventHubName;
                ensureEventHubName();

                if (string.IsNullOrWhiteSpace(this.outputConfiguration.FullyQualifiedNamespace))
                {
                    var emptyNamespaceMsg = $"{nameof(EventHubOutput)}: Event Hub namespace must not be empty when using Azure Identity. It can be specified in the '{nameof(EventHubOutputConfiguration.FullyQualifiedNamespace)}' configuration parameter";
                    healthReporter.ReportProblem(emptyNamespaceMsg, EventFlowContextIdentifiers.Configuration);
                    throw new Exception(emptyNamespaceMsg);
                }

                TokenCredential azureTokenCredential = this.outputConfiguration.AzureTokenCredential ?? new DefaultAzureCredential();

                return(new EventHubClientImpl(
                           new EventHubProducerClient(this.outputConfiguration.FullyQualifiedNamespace, this.eventHubName, azureTokenCredential)
                           ));
            }

            if (!string.IsNullOrWhiteSpace(this.outputConfiguration.ConnectionString))
            {
                var connString = EventHubsConnectionStringProperties.Parse(this.outputConfiguration.ConnectionString);
                this.eventHubName = connString.EventHubName ?? this.outputConfiguration.EventHubName;
                ensureEventHubName();

                return(new EventHubClientImpl(
                           new EventHubProducerClient(this.outputConfiguration.ConnectionString, this.eventHubName)
                           ));
            }

            var invalidConfigMsg =
                $"Invalid {nameof(EventHubOutput)} configuration encountered: '{nameof(EventHubOutputConfiguration.ConnectionString)}' value is empty and '{nameof(EventHubOutputConfiguration.UseAzureIdentity)}' is set to false. " +
                $"You need to specify either '{nameof(EventHubOutputConfiguration.ConnectionString)}' to EventHub or set '{nameof(EventHubOutputConfiguration.UseAzureIdentity)}' flag.";

            healthReporter.ReportProblem(invalidConfigMsg, EventFlowContextIdentifiers.Configuration);
            throw new Exception(invalidConfigMsg);

            void ensureEventHubName()
            {
                if (string.IsNullOrWhiteSpace(this.eventHubName))
                {
                    var emptyEventHubNameMsg = $"{nameof(EventHubOutput)}: Event Hub name must not be empty. It can be specified in the '{nameof(EventHubOutputConfiguration.ConnectionString)}' or '{nameof(EventHubOutputConfiguration.EventHubName)}' configuration parameter";
                    healthReporter.ReportProblem(emptyEventHubNameMsg);
                    throw new Exception(emptyEventHubNameMsg);
                }
            }
        }
예제 #6
0
        /// <summary>
        ///   Ensures that an Event Hubs namespace is available for the test run and captures its properties.
        /// </summary>
        ///
        /// <returns>The active Event Hubs namespace for this test run.</returns>
        ///
        private NamespaceProperties EnsureEventHubsNamespace()
        {
            // The call to "GetVariable" will validate the environment variable and bootstrap
            // test resource creation if needed.

            var environmentConnectionString = GetVariable(EventHubsNamespaceConnectionStringEnvironmentVariable);
            var parsed = EventHubsConnectionStringProperties.Parse(environmentConnectionString);

            return(new NamespaceProperties
                   (
                       parsed.FullyQualifiedNamespace.Substring(0, parsed.FullyQualifiedNamespace.IndexOf('.')),
                       environmentConnectionString.Replace($";EntityPath={ parsed.EventHubName }", string.Empty)
                   ));
        }
        public void ParseIgnoresUnknownTokens()
        {
            var endpoint         = "test.endpoint.com";
            var eventHub         = "some-path";
            var sasKey           = "sasKey";
            var sasKeyName       = "sasName";
            var connectionString = $"Endpoint=sb://{ endpoint };SharedAccessKeyName={ sasKeyName };Unknown=INVALID;SharedAccessKey={ sasKey };EntityPath={ eventHub };Trailing=WHOAREYOU";
            var parsed           = EventHubsConnectionStringProperties.Parse(connectionString);

            Assert.That(parsed.Endpoint?.Host, Is.EqualTo(endpoint).Using((IComparer <string>)StringComparer.OrdinalIgnoreCase), "The endpoint host should match.");
            Assert.That(parsed.SharedAccessKeyName, Is.EqualTo(sasKeyName), "The SAS key name should match.");
            Assert.That(parsed.SharedAccessKey, Is.EqualTo(sasKey), "The SAS key value should match.");
            Assert.That(parsed.EventHubName, Is.EqualTo(eventHub), "The Event Hub path should match.");
        }
예제 #8
0
        public async Task ConnectionStringParse()
        {
            await using var scope = await EventHubScope.CreateAsync(1);

            #region Snippet:EventHubs_Sample06_ConnectionStringParse

#if SNIPPET
            var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>";
            var eventHubName     = "<< NAME OF THE EVENT HUB >>";
#else
            var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString;
            var eventHubName     = scope.EventHubName;
#endif

            EventHubsConnectionStringProperties properties =
                EventHubsConnectionStringProperties.Parse(connectionString);

            TokenCredential credential = new DefaultAzureCredential();
            /*@@*/
            /*@@*/ credential = EventHubsTestEnvironment.Instance.Credential;

            var producer = new EventHubProducerClient(
                properties.FullyQualifiedNamespace,
                properties.EventHubName ?? eventHubName,
                credential);

            try
            {
                using var eventBatch = await producer.CreateBatchAsync();

                for (var index = 0; index < 5; ++index)
                {
                    var eventBody = new BinaryData($"Event #{ index }");
                    var eventData = new EventData(eventBody);

                    if (!eventBatch.TryAdd(eventData))
                    {
                        throw new Exception($"The event at { index } could not be added.");
                    }
                }

                await producer.SendAsync(eventBatch);
            }
            finally
            {
                await producer.CloseAsync();
            }

            #endregion
        }
        public void ParseCorrectlyParsesANamespaceConnectionString()
        {
            var endpoint              = "test.endpoint.com";
            var sasKey                = "sasKey";
            var sasKeyName            = "sasName";
            var sharedAccessSignature = "fakeSAS";
            var connectionString      = $"Endpoint=sb://{ endpoint };SharedAccessKeyName={ sasKeyName };SharedAccessKey={ sasKey };SharedAccessSignature={ sharedAccessSignature }";
            var parsed                = EventHubsConnectionStringProperties.Parse(connectionString);

            Assert.That(parsed.Endpoint?.Host, Is.EqualTo(endpoint).Using((IComparer <string>)StringComparer.OrdinalIgnoreCase), "The endpoint host should match.");
            Assert.That(parsed.SharedAccessKeyName, Is.EqualTo(sasKeyName), "The SAS key name should match.");
            Assert.That(parsed.SharedAccessKey, Is.EqualTo(sasKey), "The SAS key value should match.");
            Assert.That(parsed.SharedAccessSignature, Is.EqualTo(sharedAccessSignature), "The precomputed SAS should match.");
            Assert.That(parsed.EventHubName, Is.Null, "The Event Hub path was not included in the connection string");
        }
        public void ParseDoesNotForceTokenOrdering(string connectionString,
                                                   string endpoint,
                                                   string eventHub,
                                                   string sasKeyName,
                                                   string sasKey,
                                                   string shardAccessSignature)
        {
            var parsed = EventHubsConnectionStringProperties.Parse(connectionString);

            Assert.That(parsed.Endpoint?.Host, Is.EqualTo(endpoint).Using((IComparer <string>)StringComparer.OrdinalIgnoreCase), "The endpoint host should match.");
            Assert.That(parsed.SharedAccessKeyName, Is.EqualTo(sasKeyName), "The SAS key name should match.");
            Assert.That(parsed.SharedAccessKey, Is.EqualTo(sasKey), "The SAS key value should match.");
            Assert.That(parsed.SharedAccessSignature, Is.EqualTo(shardAccessSignature), "The precomputed SAS should match.");
            Assert.That(parsed.EventHubName, Is.EqualTo(eventHub), "The Event Hub path should match.");
        }
        public void ParseDoesAcceptsHostNamesAndUrisForTheEndpoint(string endpointValue)
        {
            var connectionString = $"Endpoint={ endpointValue };EntityPath=dummy";
            var parsed           = EventHubsConnectionStringProperties.Parse(connectionString);

            if (!Uri.TryCreate(endpointValue, UriKind.Absolute, out var valueUri))
            {
                valueUri = new Uri($"fake://{ endpointValue }");
            }

            Assert.That(parsed.Endpoint.Port, Is.EqualTo(-1), "The default port should be used.");
            Assert.That(parsed.Endpoint.Host, Does.Not.Contain(" "), "The host name should not contain any spaces.");
            Assert.That(parsed.Endpoint.Host, Does.Not.Contain(":"), "The host name should not contain any port separators (:).");
            Assert.That(parsed.Endpoint.Host, Does.Not.Contain(valueUri.Port), "The host name should not contain the port.");
            Assert.That(parsed.Endpoint.Host, Is.EqualTo(valueUri.Host), "The host name should have been normalized.");
            Assert.That(parsed.Endpoint.ToString(), Does.StartWith(GetEventHubsEndpointScheme()), "The parser's endpoint scheme should have been used.");
        }
        /// <summary>
        ///   Compares two <see cref="EventHubsConnectionStringProperties" /> instances for
        ///   structural equality.
        /// </summary>
        ///
        /// <param name="first">The first instance to consider.</param>
        /// <param name="second">The second instance to consider.</param>
        ///
        /// <returns><c>true</c> if the instances are equivalent; otherwise, <c>false</c>.</returns>
        ///
        private static bool PropertiesAreEquivalent(EventHubsConnectionStringProperties first,
                                                    EventHubsConnectionStringProperties second)
        {
            if (object.ReferenceEquals(first, second))
            {
                return(true);
            }

            if ((first == null) || (second == null))
            {
                return(false);
            }

            return(string.Equals(first.Endpoint.AbsoluteUri, second.Endpoint.AbsoluteUri, StringComparison.OrdinalIgnoreCase) &&
                   string.Equals(first.EventHubName, second.EventHubName, StringComparison.OrdinalIgnoreCase) &&
                   string.Equals(first.SharedAccessSignature, second.SharedAccessSignature, StringComparison.OrdinalIgnoreCase) &&
                   string.Equals(first.SharedAccessKeyName, second.SharedAccessKeyName, StringComparison.OrdinalIgnoreCase) &&
                   string.Equals(first.SharedAccessKey, second.SharedAccessKey, StringComparison.OrdinalIgnoreCase));
        }
        public void ToConnectionStringProducesTheConnectionStringForSharedAccessSignatures()
        {
            var properties = new EventHubsConnectionStringProperties
            {
                Endpoint              = new Uri("sb://place.endpoint.ext"),
                EventHubName          = "HubName",
                SharedAccessSignature = "FaKe#$1324@@"
            };

            var connectionString = properties.ToConnectionString();

            Assert.That(connectionString, Is.Not.Null, "The connection string should not be null.");
            Assert.That(connectionString.Length, Is.GreaterThan(0), "The connection string should have content.");

            var parsed = EventHubsConnectionStringProperties.Parse(connectionString);

            Assert.That(parsed, Is.Not.Null, "The connection string should be parsable.");
            Assert.That(PropertiesAreEquivalent(properties, parsed), Is.True, "The connection string should parse into the source properties.");
        }
        /// <summary>
        ///   Ensures that an Event Hubs namespace is available for the test run, using one if provided by the
        ///   <see cref="EventHubsNamespaceConnectionStringEnvironmentVariable" /> or creating a new Azure resource specific
        ///   to the current run.
        /// </summary>
        ///
        /// <returns>The active Event Hubs namespace for this test run.</returns>
        ///
        private NamespaceProperties EnsureEventHubsNamespace()
        {
            var environmentConnectionString = GetOptionalVariable(EventHubsNamespaceConnectionStringEnvironmentVariable);

            if (!string.IsNullOrEmpty(environmentConnectionString))
            {
                var parsed = EventHubsConnectionStringProperties.Parse(environmentConnectionString);

                return(new NamespaceProperties
                       (
                           parsed.FullyQualifiedNamespace.Substring(0, parsed.FullyQualifiedNamespace.IndexOf('.')),
                           environmentConnectionString.Replace($";EntityPath={ parsed.EventHubName }", string.Empty),
                           shouldRemoveAtCompletion: false
                       ));
            }

            return(Task
                   .Run(async() => await EventHubScope.CreateNamespaceAsync().ConfigureAwait(false))
                   .ConfigureAwait(false)
                   .GetAwaiter()
                   .GetResult());
        }
        public void ToConnectionStringNormalizesTheEndpointScheme(string scheme)
        {
            var properties = new EventHubsConnectionStringProperties
            {
                Endpoint            = new Uri(string.Concat(scheme, "myhub.servicebus.windows.net")),
                EventHubName        = "HubName",
                SharedAccessKey     = "FaKe#$1324@@",
                SharedAccessKeyName = "RootSharedAccessManagementKey"
            };

            var connectionString = properties.ToConnectionString();

            Assert.That(connectionString, Is.Not.Null, "The connection string should not be null.");
            Assert.That(connectionString.Length, Is.GreaterThan(0), "The connection string should have content.");

            var parsed = EventHubsConnectionStringProperties.Parse(connectionString);

            Assert.That(parsed, Is.Not.Null, "The connection string should be parsable.");
            Assert.That(parsed.Endpoint.Host, Is.EqualTo(properties.Endpoint.Host), "The host name of the endpoints should match.");

            var expectedScheme = new Uri(string.Concat(GetEventHubsEndpointScheme(), "fake.fake.com")).Scheme;

            Assert.That(parsed.Endpoint.Scheme, Is.EqualTo(expectedScheme), "The endpoint scheme should have been overridden.");
        }
        public void ValidateDetectsMultipleAuthorizationCredentials(string connectionString)
        {
            var properties = EventHubsConnectionStringProperties.Parse(connectionString);

            Assert.That(() => properties.Validate(null, "Dummy"), Throws.ArgumentException.And.Message.StartsWith(Resources.OnlyOneSharedAccessAuthorizationMayBeSpecified));
        }
예제 #17
0
        /// <summary>
        ///   Initializes a new instance of <see cref="EventHubsTestEnvironment"/>.
        /// </summary>
        ///
        public EventHubsTestEnvironment()
        {
            ParsedConnectionString   = new Lazy <EventHubsConnectionStringProperties>(() => EventHubsConnectionStringProperties.Parse(EventHubsConnectionString), LazyThreadSafetyMode.ExecutionAndPublication);
            ActiveEventHubsNamespace = new Lazy <NamespaceProperties>(EnsureEventHubsNamespace, LazyThreadSafetyMode.ExecutionAndPublication);

            ActivePerTestExecutionLimit = new Lazy <TimeSpan>(() =>
            {
                var interval = DefaultPerTestExecutionLimitMinutes;

                if (int.TryParse(GetOptionalVariable(EventHubsPerTestExecutionLimitEnvironmentVariable), out var environmentVariable))
                {
                    interval = environmentVariable;
                }

                return(TimeSpan.FromMinutes(interval));
            }, LazyThreadSafetyMode.PublicationOnly);
        }
        public void ValidateDetectsMissingConnectionStringInformation(string connectionString)
        {
            var properties = EventHubsConnectionStringProperties.Parse(connectionString);

            Assert.That(() => properties.Validate(null, "Dummy"), Throws.ArgumentException.And.Message.StartsWith(Resources.MissingConnectionInformation));
        }
 public void ToConnectionStringValidatesProperties(EventHubsConnectionStringProperties properties,
                                                   string testDescription)
 {
     Assert.That(() => properties.ToConnectionString(), Throws.InstanceOf <ArgumentException>(), $"The case for `{ testDescription }` failed.");
 }
        public void ParseDoesNotAllowAnInvalidEndpointFormat(string endpointValue)
        {
            var connectionString = $"Endpoint={endpointValue }";

            Assert.That(() => EventHubsConnectionStringProperties.Parse(connectionString), Throws.InstanceOf <FormatException>());
        }
예제 #21
0
        public async Task ConnectionStringParse()
        {
            await using var eventHubScope = await EventHubScope.CreateAsync(1);

            await using var storageScope = await StorageScope.CreateAsync();

            #region Snippet:EventHubs_Processor_Sample05_ConnectionStringParse

            TokenCredential credential = new DefaultAzureCredential();

            var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>";
            var blobContainerName       = "<< NAME OF THE BLOB CONTAINER >>";
            /*@@*/
            /*@@*/ storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString;
            /*@@*/ blobContainerName       = storageScope.ContainerName;

            var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>";
            var eventHubName  = "<< NAME OF THE EVENT HUB >>";
            var consumerGroup = "<< NAME OF THE EVENT HUB CONSUMER GROUP >>";
            /*@@*/
            /*@@*/ eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString;
            /*@@*/ eventHubName  = eventHubScope.EventHubName;
            /*@@*/ consumerGroup = eventHubScope.ConsumerGroups.First();
            /*@@*/ credential    = EventHubsTestEnvironment.Instance.Credential;

            var storageEndpoint = new BlobServiceClient(storageConnectionString).Uri;
            var blobUriBuilder  = new BlobUriBuilder(storageEndpoint);
            blobUriBuilder.BlobContainerName = blobContainerName;

            var storageClient = new BlobContainerClient(
                blobUriBuilder.ToUri(),
                credential);

            EventHubsConnectionStringProperties properties =
                EventHubsConnectionStringProperties.Parse(eventHubsConnectionString);

            var processor = new EventProcessorClient(
                storageClient,
                consumerGroup,
                properties.FullyQualifiedNamespace,
                properties.EventHubName ?? eventHubName,
                credential);

            try
            {
                using var cancellationSource = new CancellationTokenSource();
                cancellationSource.CancelAfter(TimeSpan.FromSeconds(30));

                // The event handlers are not relevant for this sample; for
                // illustration, they're delegating the implementation to the
                // host application.

                processor.ProcessEventAsync += Application.ProcessorEventHandler;
                processor.ProcessErrorAsync += Application.ProcessorErrorHandler;

                try
                {
                    await processor.StartProcessingAsync(cancellationSource.Token);

                    await Task.Delay(Timeout.Infinite, cancellationSource.Token);
                }
                catch (TaskCanceledException)
                {
                    // This is expected if the cancellation token is
                    // signaled.
                }
                finally
                {
                    // This may take up to the length of time defined
                    // as part of the configured TryTimeout of the processor;
                    // by default, this is 60 seconds.

                    await processor.StopProcessingAsync();
                }
            }
            catch
            {
                // If this block is invoked, then something external to the
                // processor was the source of the exception.
            }
            finally
            {
                // It is encouraged that you unregister your handlers when you have
                // finished using the Event Processor to ensure proper cleanup.

                processor.ProcessEventAsync -= Application.ProcessorEventHandler;
                processor.ProcessErrorAsync -= Application.ProcessorErrorHandler;
            }

            #endregion
        }
 public void ParseConsidersMissingValuesAsMalformed(string connectionString)
 {
     Assert.That(() => EventHubsConnectionStringProperties.Parse(connectionString), Throws.InstanceOf <FormatException>());
 }
        public void ParseValidatesArguments(string connectionString)
        {
            ExactTypeConstraint typeConstraint = connectionString is null ? Throws.ArgumentNullException : Throws.ArgumentException;

            Assert.That(() => EventHubsConnectionStringProperties.Parse(connectionString), typeConstraint);
        }