public void GetTokenIgnoresScopeAndCancellationToken()
        {
            var value      = "TOkEn!";
            var signature  = new SharedAccessSignature("hub-name", "keyName", "key", value, DateTimeOffset.UtcNow.AddHours(4));
            var credential = new SharedAccessCredential(signature);

            Assert.That(credential.GetToken(new TokenRequestContext(new[] { "test", "this" }), CancellationToken.None).Token, Is.SameAs(signature.Value), "The credential should return the signature as the token.");
        }
        public void GetTokenReturnsTheSignatureValue()
        {
            var value      = "TOkEn!";
            var signature  = new SharedAccessSignature("hub-name", "keyName", "key", value, DateTimeOffset.UtcNow.AddHours(4));
            var credential = new SharedAccessCredential(signature);

            Assert.That(credential.GetToken(new TokenRequestContext(), default).Token, Is.SameAs(signature.Value), "The credential should return the signature as the token.");
        }
        public void SasConstructorInitializesProperties()
        {
            var signature        = new SharedAccessSignature("hub-name", "keyName", "key");
            var sourceCredential = new AzureSasCredential(signature.Value);
            var credential       = new SharedAccessCredential(sourceCredential);

            Assert.That(GetSharedAccessSignature(credential).Value, Is.EqualTo(sourceCredential.Signature), "The signature should match the source credential.");
            Assert.That(GetSourceSasCredential(credential), Is.SameAs(sourceCredential), "The source SAS credential should match.");
            Assert.That(GetSourceKeyCredential(credential), Is.Null, "The source named key credential should not be populated.");
        }
        public void GetTokenDoesNotExtendATokenCloseToExpiringWhenCreatedWithoutTheKey()
        {
            var tokenExpiration = DateTimeOffset.UtcNow.Add(TimeSpan.FromSeconds(GetSignatureRefreshBuffer().TotalSeconds / 2));
            var value           = $"SharedAccessSignature sr=https%3A%2F%2Ffake-test.servicebus.windows.net%2F&sig=nNBNavJfBiHuXUzWOLhSvI3bVgqbQUzA7Po8%2F4wQQng%3D&se={ ToUnixTime(tokenExpiration) }&skn=fakeKey";
            var sourceSignature = new SharedAccessSignature("fake-test", "fakeKey", "ABC123", value, tokenExpiration).Value;
            var signature       = new SharedAccessSignature(sourceSignature);
            var credential      = new SharedAccessCredential(signature);

            Assert.That(credential.GetToken(new TokenRequestContext(), default).ExpiresOn, Is.EqualTo(tokenExpiration).Within(TimeSpan.FromMinutes(1)));
        }
        public void GetTokenExtendsAnExpiredTokenWhenCreatedWithTheSharedKey()
        {
            var value      = "TOkEn!";
            var signature  = new SharedAccessSignature("hub-name", "keyName", "key", value, DateTimeOffset.UtcNow.Subtract(TimeSpan.FromHours(2)));
            var credential = new SharedAccessCredential(signature);

            var expectedExpiration = DateTimeOffset.Now.Add(GetSignatureExtensionDuration());

            Assert.That(credential.GetToken(new TokenRequestContext(), default).ExpiresOn, Is.EqualTo(expectedExpiration).Within(TimeSpan.FromMinutes(1)));
        }
        public async Task GetTokenAsyncIgnoresScopeAndCancellationToken()
        {
            var         value        = "TOkEn!";
            var         signature    = new SharedAccessSignature("hub-name", "keyName", "key", value, DateTimeOffset.UtcNow.AddHours(4));
            var         credential   = new SharedAccessCredential(signature);
            var         cancellation = new CancellationTokenSource();
            AccessToken token        = await credential.GetTokenAsync(new TokenRequestContext(new string[0]), cancellation.Token);

            Assert.That(token.Token, Is.SameAs(signature.Value), "The credential should return the signature as the token.");
        }
        public void SignatureConstructorInitializesProperties()
        {
            var value      = "TOkEn!";
            var signature  = new SharedAccessSignature("hub-name", "keyName", "key", value, DateTimeOffset.UtcNow.AddHours(4));
            var credential = new SharedAccessCredential(signature);

            Assert.That(GetSharedAccessSignature(credential), Is.SameAs(signature), "The credential should match.");
            Assert.That(GetSourceSasCredential(credential), Is.Null, "The source SAS credential should not be populated.");
            Assert.That(GetSourceKeyCredential(credential), Is.Null, "The source named key credential should not be populated.");
        }
        public void GetTokenDoesNotExtendAnExpiredTokenWhenCreatedWithoutTheKey()
        {
            var expectedExpiration = DateTimeOffset.UtcNow.Subtract(TimeSpan.FromHours(2));
            var value           = $"SharedAccessSignature sr=https%3A%2F%2Ffake-test.servicebus.windows.net%2F&sig=nNBNavJfBiHuXUzWOLhSvI3bVgqbQUzA7Po8%2F4wQQng%3D&se={ ToUnixTime(expectedExpiration) }&skn=fakeKey";
            var sourceSignature = new SharedAccessSignature("fake-test", "fakeKey", "ABC123", value, expectedExpiration).Value;
            var signature       = new SharedAccessSignature(sourceSignature);
            var credential      = new SharedAccessCredential(signature);

            Assert.That(credential.GetToken(new TokenRequestContext(), default).ExpiresOn, Is.EqualTo(expectedExpiration).Within(TimeSpan.FromMinutes(1)));
        }
        public void GetTokenExtendsATokenCloseToExpiringWhenCreatedWithTheSharedKey()
        {
            var value           = "TOkEn!";
            var tokenExpiration = DateTimeOffset.UtcNow.Add(TimeSpan.FromSeconds(GetSignatureRefreshBuffer().TotalSeconds / 2));
            var signature       = new SharedAccessSignature("hub-name", "keyName", "key", value, tokenExpiration);
            var credential      = new SharedAccessCredential(signature);

            var expectedExpiration = DateTimeOffset.Now.Add(GetSignatureExtensionDuration());

            Assert.That(credential.GetToken(new TokenRequestContext(), default).ExpiresOn, Is.EqualTo(expectedExpiration).Within(TimeSpan.FromMinutes(1)));
        }
        public async Task GetTokenAsyncSetsTheCorrectTypeForSharedAccessTokens()
        {
            var value = "TOkEn!";
            var signature = new SharedAccessSignature("hub", "keyName", "key", value, DateTimeOffset.Parse("2015-10-27T00:00:00Z"));
            var sasCredential = new SharedAccessCredential(signature);
            var credential = new EventHubTokenCredential(sasCredential);
            var provider = new CbsTokenProvider(credential, default);

            CbsToken cbsToken = await provider.GetTokenAsync(new Uri("http://www.here.com"), "nobody", new string[0]);

            Assert.That(cbsToken, Is.Not.Null, "The token should have been produced");
            Assert.That(cbsToken.TokenType, Is.EqualTo(GetSharedAccessTokenType()), "The token type should match");
        }
        public void KeyConstructorInitializesProperties()
        {
            var signature           = new SharedAccessSignature("hub-name", "keyName", "key");
            var sourceCredential    = new AzureNamedKeyCredential(signature.SharedAccessKeyName, signature.SharedAccessKey);
            var credential          = new SharedAccessCredential(sourceCredential, signature.Resource);
            var credentialSignature = GetSharedAccessSignature(credential);

            var(signatureKeyName, signatureKeyValue) = sourceCredential;

            Assert.That(credentialSignature.SharedAccessKeyName, Is.EqualTo(signatureKeyName), "The shared key name should match the source credential.");
            Assert.That(credentialSignature.SharedAccessKey, Is.EqualTo(signatureKeyValue), "The shared key should match the source credential.");
            Assert.That(GetSourceSasCredential(credential), Is.Null, "The source SAS credential should not be populated.");
            Assert.That(GetSourceKeyCredential(credential), Is.SameAs(sourceCredential), "The source key credential should match.");
        }
        public void SasCredentialUpdatesAreRespected()
        {
            var tokenExpiration  = TimeSpan.FromSeconds(GetSignatureRefreshBuffer().TotalSeconds / 2);
            var signature        = new SharedAccessSignature("hub-name", "keyName", "key", tokenExpiration);
            var sourceCredential = new AzureSasCredential(signature.Value);
            var credential       = new SharedAccessCredential(sourceCredential);

            Assert.That(GetSharedAccessSignature(credential).Value, Is.EqualTo(sourceCredential.Signature), "The signature should match the source credential.");

            var updatedSignature = new SharedAccessSignature("hub-name", "newKeyName", "newKey", tokenExpiration.Add(TimeSpan.FromMinutes(30)));

            sourceCredential.Update(updatedSignature.Value);

            var accessToken = credential.GetToken(new TokenRequestContext(), CancellationToken.None);

            Assert.That(accessToken.Token, Is.EqualTo(updatedSignature.Value));
            Assert.That(accessToken.ExpiresOn, Is.EqualTo(updatedSignature.SignatureExpiration).Within(TimeSpan.FromMinutes(5)));
        }
        public async Task ConnectionTransportCanRetrievePartitionProperties(EventHubsTransportType transportType)
        {
            var partitionCount = 4;

            await using (EventHubScope scope = await EventHubScope.CreateAsync(partitionCount))
            {
                var options = new EventHubConnectionOptions();

                var credential = new SharedAccessCredential
                                 (
                    new SharedAccessSignature
                    (
                        $"{ options.TransportType.GetUriScheme() }://{ EventHubsTestEnvironment.Instance.FullyQualifiedNamespace }/{ scope.EventHubName }".ToLowerInvariant(),
                        EventHubsTestEnvironment.Instance.SharedAccessKeyName,
                        EventHubsTestEnvironment.Instance.SharedAccessKey,
                        TimeSpan.FromHours(4)
                    )
                                 );

                await using (var connection = new TestConnectionWithRetryPolicy(EventHubsTestEnvironment.Instance.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 void NamedKeyCredentialUpdatesAreRespected()
        {
            var updatedKeyName      = "updated-name";
            var updatedKey          = "updated-Key";
            var signature           = new SharedAccessSignature("hub-name", "keyName", "key");
            var sourceCredential    = new AzureNamedKeyCredential(signature.SharedAccessKeyName, signature.SharedAccessKey);
            var credential          = new SharedAccessCredential(sourceCredential, signature.Resource);
            var credentialSignature = GetSharedAccessSignature(credential);

            var(signatureKeyName, signatureKeyValue) = sourceCredential;

            Assert.That(credentialSignature.SharedAccessKeyName, Is.EqualTo(signatureKeyName), "The shared key name should match the source credential.");
            Assert.That(credentialSignature.SharedAccessKey, Is.EqualTo(signatureKeyValue), "The shared key should match the source credential.");

            sourceCredential.Update(updatedKeyName, updatedKey);
            _ = credential.GetToken(new TokenRequestContext(), CancellationToken.None);

            var newSignature = GetSharedAccessSignature(credential);

            Assert.That(newSignature.SharedAccessKeyName, Is.EqualTo(updatedKeyName));
            Assert.That(newSignature.SharedAccessKey, Is.EqualTo(updatedKey));
            Assert.That(newSignature.SignatureExpiration, Is.EqualTo(signature.SignatureExpiration).Within(TimeSpan.FromMinutes(5)));
        }
        public async Task ConnectionCanConnectToEventHubsUsingArguments()
        {
            await using (EventHubScope scope = await EventHubScope.CreateAsync(1))
            {
                var options = new EventHubConnectionOptions();

                var credential = new SharedAccessCredential
                                 (
                    new SharedAccessSignature
                    (
                        $"{ options.TransportType.GetUriScheme() }://{ EventHubsTestEnvironment.Instance.FullyQualifiedNamespace }/{ scope.EventHubName }".ToLowerInvariant(),
                        EventHubsTestEnvironment.Instance.SharedAccessKeyName,
                        EventHubsTestEnvironment.Instance.SharedAccessKey,
                        TimeSpan.FromHours(4)
                    )
                                 );

                await using (var connection = new TestConnectionWithRetryPolicy(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, credential))
                {
                    Assert.That(() => connection.GetPropertiesAsync(), Throws.Nothing);
                }
            }
        }
        /// <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 SharedAccessCredential(sharedAccessSignature);
            var tokenCredential  = new ServiceBusTokenCredential(sharedCredential);

#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>
 ///   Retrieves the shared access signature from the credential using its private field.
 /// </summary>
 ///
 /// <param name="instance">The instance to retrieve the key from.</param>
 ///
 /// <returns>The shared access key.</returns>
 ///
 private static SharedAccessSignature GetSharedAccessSignature(SharedAccessCredential instance) =>
 (SharedAccessSignature)
 typeof(SharedAccessCredential)
 .GetField("_sharedAccessSignature", BindingFlags.Instance | BindingFlags.NonPublic)
 .GetValue(instance);
 /// <summary>
 ///   Retrieves the source named key credential instance from the credential using its private field.
 /// </summary>
 ///
 /// <param name="instance">The instance to retrieve the key from.</param>
 ///
 /// <returns>The source credential.</returns>
 ///
 private static AzureNamedKeyCredential GetSourceKeyCredential(SharedAccessCredential instance) =>
 (AzureNamedKeyCredential)
 typeof(SharedAccessCredential)
 .GetField("_sourceKeyCredential", BindingFlags.Instance | BindingFlags.NonPublic)
 .GetValue(instance);