public async Task CreateClientFormsTheCorrectEndpoint() { var options = new EventHubClientOptions(); var host = "my.eventhub.com"; var eventHubPath = "some-path"; var resource = $"amqps://{ host }/{ eventHubPath }"; var signature = new SharedAccessSignature(resource, "keyName", "KEY", TimeSpan.FromHours(1)); var credential = new SharedAccessSignatureCredential(signature); var client = (AmqpEventHubClient)TrackOneEventHubClient.CreateClient(host, eventHubPath, credential, options); try { var endpoint = client.ConnectionStringBuilder.Endpoint; Assert.That(endpoint.Scheme.ToLowerInvariant(), Contains.Substring(options.TransportType.GetUriScheme().ToLowerInvariant()), "The scheme should be part of the endpoint."); Assert.That(endpoint.Host.ToLowerInvariant(), Contains.Substring(host.ToLowerInvariant()), "The host should be part of the endpoint."); Assert.That(endpoint.AbsolutePath.ToLowerInvariant(), Contains.Substring(eventHubPath.ToLowerInvariant()), "The host should be part of the endpoint."); } finally { await client?.CloseAsync(); } }
public void AsSharedAccessSignatureCredentialShouldRefreshTokenValidityForSharedKeys() { var beforeResource = "amqps://before/path"; var afterResource = "amqps://after/path"; var beforeSpan = TimeSpan.FromHours(4); var afterSpan = TimeSpan.FromHours(8); var keyName = "keyName"; var keyValue = "keyValue"; var expectedSignature = new SharedAccessSignature(beforeResource, keyName, keyValue, beforeSpan); var keyCredential = new EventHubsSharedAccessKeyCredential(keyName, keyValue); SharedAccessSignatureCredential sasCredential = keyCredential.AsSharedAccessSignatureCredential(beforeResource, beforeSpan); SharedAccessSignature beforeSignature = GetSharedAccessSignature(sasCredential); Assert.That(beforeSignature.SignatureExpiration, Is.EqualTo(expectedSignature.SignatureExpiration).Within(TimeSpan.FromSeconds(5)), "The expiration should match."); expectedSignature = new SharedAccessSignature(afterResource, keyName, keyValue, afterSpan); sasCredential = keyCredential.AsSharedAccessSignatureCredential(afterResource, afterSpan); SharedAccessSignature afterSignature = GetSharedAccessSignature(sasCredential); Assert.That(afterSignature.SignatureExpiration, Is.EqualTo(expectedSignature.SignatureExpiration).Within(TimeSpan.FromSeconds(5)), "The expiration should match."); }
/// <summary> /// Initializes a new instance of the <see cref="ServiceBusConnection"/> class. /// </summary> /// /// <param name="connectionString">The connection string to use for connecting to the Service Bus namespace.</param> /// <param name="options">A set of options to apply when configuring the connection.</param> /// /// <remarks> /// If the connection string is copied from the Service Bus entity itself, it will contain the name of the desired Service Bus entity, /// and can be used directly without passing the name="entityName" />. The name of the Service Bus entity should be /// passed only once, either as part of the connection string or separately. /// </remarks> /// internal ServiceBusConnection( string connectionString, ServiceBusClientOptions options) { Argument.AssertNotNullOrEmpty(connectionString, nameof(connectionString)); ValidateConnectionOptions(options); var connectionStringProperties = ServiceBusConnectionStringProperties.Parse(connectionString); ValidateConnectionStringProperties(connectionStringProperties, nameof(connectionString)); FullyQualifiedNamespace = connectionStringProperties.Endpoint.Host; TransportType = options.TransportType; EntityPath = connectionStringProperties.EntityPath; RetryOptions = options.RetryOptions; SharedAccessSignature sharedAccessSignature; if (string.IsNullOrEmpty(connectionStringProperties.SharedAccessSignature)) { sharedAccessSignature = new SharedAccessSignature( BuildConnectionResource(options.TransportType, FullyQualifiedNamespace, EntityPath), connectionStringProperties.SharedAccessKeyName, connectionStringProperties.SharedAccessKey); } else { sharedAccessSignature = new SharedAccessSignature(connectionStringProperties.SharedAccessSignature); } var sharedCredential = new SharedAccessSignatureCredential(sharedAccessSignature); var tokenCredential = new ServiceBusTokenCredential( sharedCredential, BuildConnectionResource(TransportType, FullyQualifiedNamespace, EntityPath)); #pragma warning disable CA2214 // Do not call overridable methods in constructors. This internal method is virtual for testing purposes. _innerClient = CreateTransportClient(tokenCredential, options); #pragma warning restore CA2214 // Do not call overridable methods in constructors }
/// <summary> /// Initializes a new instance of the <see cref="ServiceBusConnection"/> class. /// </summary> /// /// <param name="connectionString">The connection string to use for connecting to the Service Bus namespace.</param> /// <param name="options">A set of options to apply when configuring the connection.</param> /// /// <remarks> /// If the connection string is copied from the Service Bus entity itself, it will contain the name of the desired Service Bus entity, /// and can be used directly without passing the name="entityName" />. The name of the Service Bus entity should be /// passed only once, either as part of the connection string or separately. /// </remarks> /// internal ServiceBusConnection( string connectionString, ServiceBusClientOptions options) { Argument.AssertNotNullOrEmpty(connectionString, nameof(connectionString)); options = options?.Clone() ?? new ServiceBusClientOptions(); ValidateConnectionOptions(options); ConnectionStringProperties connectionStringProperties = ConnectionStringParser.Parse(connectionString); if (string.IsNullOrEmpty(connectionStringProperties.Endpoint?.Host) || string.IsNullOrEmpty(connectionStringProperties.SharedAccessKeyName) || string.IsNullOrEmpty(connectionStringProperties.SharedAccessKey)) { throw new ArgumentException(Resources1.MissingConnectionInformation, nameof(connectionString)); } FullyQualifiedNamespace = connectionStringProperties.Endpoint.Host; TransportType = options.TransportType; EntityPath = connectionStringProperties.EntityPath; Options = options; RetryOptions = options.RetryOptions; var sharedAccessSignature = new SharedAccessSignature ( BuildAudienceResource(options.TransportType, FullyQualifiedNamespace, EntityPath), connectionStringProperties.SharedAccessKeyName, connectionStringProperties.SharedAccessKey ); var sharedCredential = new SharedAccessSignatureCredential(sharedAccessSignature); var tokenCredential = new ServiceBusTokenCredential( sharedCredential, BuildAudienceResource(TransportType, FullyQualifiedNamespace, EntityPath)); _innerClient = CreateTransportClient(tokenCredential, options); }
public async Task ConnectionTransportCanRetrievePartitionProperties(EventHubsTransportType transportType) { var partitionCount = 4; await using (EventHubScope scope = await EventHubScope.CreateAsync(partitionCount)) { var options = new EventHubConnectionOptions(); var credential = new SharedAccessSignatureCredential ( new SharedAccessSignature ( $"{ options.TransportType.GetUriScheme() }://{ TestEnvironment.FullyQualifiedNamespace }/{ scope.EventHubName }".ToLowerInvariant(), TestEnvironment.SharedAccessKeyName, TestEnvironment.SharedAccessKey, TimeSpan.FromHours(4) ) ); await using (var connection = new TestConnectionWithTransport(TestEnvironment.FullyQualifiedNamespace, scope.EventHubName, credential, new EventHubConnectionOptions { TransportType = transportType })) { var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(20)); var properties = await connection.GetPropertiesAsync(); var partition = properties.PartitionIds.First(); var partitionProperties = await connection.GetPartitionPropertiesAsync(partition, cancellation.Token); Assert.That(partitionProperties, Is.Not.Null, "A set of partition properties should have been returned."); Assert.That(partitionProperties.Id, Is.EqualTo(partition), "The partition identifier should match."); Assert.That(partitionProperties.EventHubName, Is.EqualTo(scope.EventHubName).Using((IEqualityComparer <string>)StringComparer.InvariantCultureIgnoreCase), "The Event Hub path should match."); Assert.That(partitionProperties.BeginningSequenceNumber, Is.Not.EqualTo(default(long)), "The beginning sequence number should have been populated."); Assert.That(partitionProperties.LastEnqueuedSequenceNumber, Is.Not.EqualTo(default(long)), "The last sequence number should have been populated."); Assert.That(partitionProperties.LastEnqueuedOffset, Is.Not.EqualTo(default(long)), "The last offset should have been populated."); } } }
public async Task ClientCanRetrievePartitionProperties() { var partitionCount = 4; await using (var scope = await EventHubScope.CreateAsync(partitionCount)) { var clientOptions = new EventHubClientOptions(); var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); var connectionProperties = ConnectionStringParser.Parse(connectionString); var credential = new SharedAccessSignatureCredential ( new SharedAccessSignature ( $"{ clientOptions.TransportType.GetUriScheme() }://{ connectionProperties.Endpoint.Host }/{ connectionProperties.EventHubPath }".ToLowerInvariant(), connectionProperties.SharedAccessKeyName, connectionProperties.SharedAccessKey, TimeSpan.FromHours(4) ) ); await using (var client = new EventHubClient(connectionProperties.Endpoint.Host, connectionProperties.EventHubPath, credential)) { var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(20)); var properties = await client.GetPropertiesAsync(); var partition = properties.PartitionIds.First(); var partitionProperties = await client.GetPartitionPropertiesAsync(partition, cancellation.Token); Assert.That(partitionProperties, Is.Not.Null, "A set of partition properties should have been returned."); Assert.That(partitionProperties.Id, Is.EqualTo(partition), "The partition identifier should match."); Assert.That(partitionProperties.EventHubPath, Is.EqualTo(connectionProperties.EventHubPath).Using((IEqualityComparer <string>)StringComparer.InvariantCultureIgnoreCase), "The Event Hub path should match."); Assert.That(partitionProperties.BeginningSequenceNumber, Is.Not.EqualTo(default(Int64)), "The beginning sequence number should have been populated."); Assert.That(partitionProperties.LastEnqueuedSequenceNumber, Is.Not.EqualTo(default(Int64)), "The last sequance number should have been populated."); Assert.That(partitionProperties.LastEnqueuedOffset, Is.Not.Null.Or.Empty, "The last offset should have been populated."); } } }
/// <summary> /// Initializes a new instance of the <see cref="EventHubConnection"/> class. /// </summary> /// /// <param name="connectionString">The connection string to use for connecting to the Event Hubs namespace; it is expected that the shared key properties are contained in this connection string, but not the Event Hub name.</param> /// <param name="eventHubName">The name of the specific Event Hub to associate the connection with.</param> /// <param name="connectionOptions">A set of options to apply when configuring the connection.</param> /// /// <remarks> /// If the connection string is copied from the Event Hub itself, it will contain the name of the desired Event Hub, /// and can be used directly without passing the <paramref name="eventHubName" />. The name of the Event Hub should be /// passed only once, either as part of the connection string or separately. /// </remarks> /// public EventHubConnection(string connectionString, string eventHubName, EventHubConnectionOptions connectionOptions) { Argument.AssertNotNullOrEmpty(connectionString, nameof(connectionString)); connectionOptions = connectionOptions?.Clone() ?? new EventHubConnectionOptions(); ValidateConnectionOptions(connectionOptions); ConnectionStringProperties connectionStringProperties = ConnectionStringParser.Parse(connectionString); ValidateConnectionProperties(connectionStringProperties, eventHubName, nameof(connectionString)); var fullyQualifiedNamespace = connectionStringProperties.Endpoint.Host; if (string.IsNullOrEmpty(eventHubName)) { eventHubName = connectionStringProperties.EventHubName; } var sharedAccessSignature = new SharedAccessSignature ( BuildAudienceResource(connectionOptions.TransportType, fullyQualifiedNamespace, eventHubName), connectionStringProperties.SharedAccessKeyName, connectionStringProperties.SharedAccessKey ); var sharedCredentials = new SharedAccessSignatureCredential(sharedAccessSignature); var tokenCredentials = new EventHubTokenCredential(sharedCredentials, BuildAudienceResource(connectionOptions.TransportType, fullyQualifiedNamespace, eventHubName)); FullyQualifiedNamespace = fullyQualifiedNamespace; EventHubName = eventHubName; Options = connectionOptions; #pragma warning disable CA2214 // Do not call overridable methods in constructors. This internal method is virtual for testing purposes. InnerClient = CreateTransportClient(fullyQualifiedNamespace, eventHubName, tokenCredentials, connectionOptions); #pragma warning restore CA2214 // Do not call overridable methods in constructors. }
public async Task CreateClientPopulatesTheProxy() { var options = new EventHubClientOptions { TransportType = TransportType.AmqpWebSockets, Proxy = Mock.Of <IWebProxy>() }; var host = "my.eventhub.com"; var eventHubPath = "some-path"; var signature = new SharedAccessSignature(options.TransportType, host, eventHubPath, "keyName", "KEY", TimeSpan.FromHours(1)); var credential = new SharedAccessSignatureCredential(signature); var client = (AmqpEventHubClient)TrackOneEventHubClient.CreateClient(host, eventHubPath, credential, options); try { Assert.That(client.WebProxy, Is.SameAs(options.Proxy), "The client should honor the proxy."); } finally { await client?.CloseAsync(); } }
public async Task ConnectionCanConnectToEventHubsUsingArguments() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { var options = new EventHubConnectionOptions(); var credential = new SharedAccessSignatureCredential ( new SharedAccessSignature ( $"{ options.TransportType.GetUriScheme() }://{ TestEnvironment.FullyQualifiedNamespace }/{ scope.EventHubName }".ToLowerInvariant(), TestEnvironment.SharedAccessKeyName, TestEnvironment.SharedAccessKey, TimeSpan.FromHours(4) ) ); await using (var connection = new TestConnectionWithTransport(TestEnvironment.FullyQualifiedNamespace, scope.EventHubName, credential)) { Assert.That(() => connection.GetPropertiesAsync(), Throws.Nothing); } } }
/// <summary> /// Retrieves the shared access signature from the credential using its private accessor. /// </summary> /// /// <param name="instance">The instance to retrieve the key from.</param> /// /// <returns>The shared access key</returns> /// private static SharedAccessSignature GetSharedAccessSignature(SharedAccessSignatureCredential instance) => (SharedAccessSignature) typeof(SharedAccessSignatureCredential) .GetProperty("SharedAccessSignature", BindingFlags.Instance | BindingFlags.NonPublic) .GetValue(instance, null);