public async Task AzureServiceBusServer_Working_AsExpected()
        {
            var  queueClient = new QueueClient(_configuration["ConnectionString"], "cqelight");
            bool finished    = false;
            var  evtToSend   = new AzureEvent {
                Data = "evt_data"
            };

            var server = new AzureServiceBusServer(CONST_APP_ID_SERVER, _loggerFactory.Object,
                                                   new AzureServiceBusServerConfiguration(_configuration["ConnectionString"],
                                                                                          new QueueConfiguration(new JsonDispatcherSerializer(), "cqelight", false,
                                                                                                                 o =>
            {
                if (o is IDomainEvent receivedEvt)
                {
                    finished = receivedEvt.GetType() == typeof(AzureEvent) && (receivedEvt.As <AzureEvent>().Data) == "evt_data";
                }
            })));


            var client = new AzureServiceBusClient(CONST_APP_ID_CLIENT, queueClient, new AzureServiceBusClientConfiguration(
                                                       _configuration["ConnectionString"], null, null));
            await client.PublishEventAsync(evtToSend).ConfigureAwait(false);

            int currentWait = 0;

            while (!finished && currentWait <= 2000)
            {
                currentWait += 50;
                await Task.Delay(50).ConfigureAwait(false);
            }
            finished.Should().BeTrue();
        }
        public async Task DeadLettersMessageWithReasonAsync()
        {
            const string deadLetterReason    = "Json Serliazation issue";
            var          subscription        = nameof(DeadLettersMessageWithReasonAsync);
            var          aircraftlandedEvent = await CreateSubscriptionAndSendAircraftLandedEventAsync(subscription);

            var aircraftLandedHandler      = new AircraftLandedHandler(deadLetterReason);
            var mockMessageHandlerResolver = new Mock <IMessageHandlerResolver>();

            mockMessageHandlerResolver.Setup(m => m.Resolve(nameof(AircraftLanded))).Returns(aircraftLandedHandler);
            var mockMessageProcessorResolver = new Mock <IMessageProcessorResolver>();

            _azureServiceBusClient = new AzureServiceBusClient(_hostname, _topic, nameof(DeadLettersMessageWithReasonAsync), _tenantId);
            var messageBus = new Abstractions.MessageBus(mockMessageHandlerResolver.Object, new Mock <IMessageBusAdminClient>().Object,
                                                         _azureServiceBusClient, mockMessageProcessorResolver.Object);

            await messageBus.StartAsync();

            await Task.Delay(TimeSpan.FromSeconds(2));

            var messages = await ReceiveMessagesForSubscriptionAsync(subscription, true);

            Assert.Equal(1, aircraftLandedHandler.MessageCount);
            Assert.Equal(nameof(AircraftLanded), messages.First().Subject);
            Assert.Single(messages.Where(m => IsMatchingAircraftId <AircraftLanded>(m, aircraftlandedEvent.AircraftId)));
        }
        public void AcceptsServiceBusClientSettings()
        {
            _ = new AzureServiceBusClient("test.servicebus.windows.net", "topic", "subscription", "12345-12345",
                                          new ServiceBusProcessorOptions());


            var connectionString = "Endpoint=sb://test.servicebus.windows.net/;" +
                                   "SharedAccessKeyName=Manage;SharedAccessKey=12345=;";

            _ = new AzureServiceBusClient(connectionString, "topic", "subscription", new ServiceBusProcessorOptions());
        }
        public void CreateRotation_WithoutLogger_Throws()
        {
            var location = new AzureServiceBusNamespace("resource group", "namespace", ServiceBusEntityType.Topic, "entity name", "authorization rule name");
            var client   = new AzureServiceBusClient(Mock.Of <IAzureServiceBusManagementAuthentication>(), location, NullLogger.Instance);

            Assert.ThrowsAny <ArgumentException>(
                () => new AzureServiceBusKeyRotation(
                    serviceBusClient: client,
                    authentication: Mock.Of <IKeyVaultAuthentication>(),
                    configuration: Mock.Of <IKeyVaultConfiguration>(),
                    logger: null));
        }
        public async Task ThrowsHandlerExceptionIfNoMessageHandlerFound()
        {
            var mockTestHandler       = new Mock <ITestHandler>();
            var subscription          = nameof(CallsCorrectMessageHandlerUsingConnectionString);
            var aircraftTakenOffEvent = await CreateSubscriptionAndSendAircraftTakenOffEventAsync(subscription);

            _azureServiceBusClient = new AzureServiceBusClient(_connectionString, _topic, subscription);
            _azureServiceBusClient.AddErrorMessageHandler(mockTestHandler.Object.ErrorMessageHandler);
            await _azureServiceBusClient.StartAsync();

            await Task.Delay(TimeSpan.FromSeconds(10));

            mockTestHandler.Verify(m => m.ErrorMessageHandler(It.Is <MessageErrorReceivedEventArgs>(m =>
                                                                                                    m.Exception.GetType() == typeof(MessageHandlerNotFoundException))), Times.Exactly(10));
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="AzureServiceBusKeyRotation"/> class.
        /// </summary>
        /// <param name="serviceBusClient">The client to interact with the Azure Service Bus.</param>
        /// <param name="authentication">The instance to authenticate with the Azure Key Vault.</param>
        /// <param name="configuration">The instance containing the necessary configuration to interact with the Azure Key Vault.</param>
        /// <param name="logger">The instance to write diagnostic messages during rotation and interaction with the Azure Service Bus and Azure Key Vault.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown when the <paramref name="serviceBusClient"/>, <paramref name="authentication"/>, <paramref name="configuration"/>, or <paramref name="logger"/> is <c>null</c>.
        /// </exception>
        public AzureServiceBusKeyRotation(
            AzureServiceBusClient serviceBusClient,
            IKeyVaultAuthentication authentication,
            IKeyVaultConfiguration configuration,
            ILogger logger)
        {
            Guard.NotNull(serviceBusClient, nameof(serviceBusClient), "Requires an Azure Service Bus client to interact with the Service Bus when rotating the connection string keys");
            Guard.NotNull(authentication, nameof(authentication), "Requires an authentication instance to authenticate with the Azure Key Vault resource to set the new connection string keys");
            Guard.NotNull(configuration, nameof(configuration), "Requires an KeyVault configuration instance to locate the Key Vault resource on Azure");
            Guard.NotNull(logger, nameof(logger), "Requires an logger instance to write diagnostic trace messages when interacting with the Azure Service Bus and Azure Key Vault instances");

            _serviceBusClient = serviceBusClient;
            _authentication   = authentication;
            _configuration    = configuration;
            _logger           = logger;
        }
        public async Task CallsErrorMessageHandlerWithExceptionAsync()
        {
            var mockTestHandler = new Mock <ITestHandler>();
            var args            = new ProcessErrorEventArgs(new ServiceBusException("ServiceBusError",
                                                                                    ServiceBusFailureReason.GeneralError), ServiceBusErrorSource.Receive, "test.servicebus.windows.net",
                                                            "topic1", new CancellationToken());

            var sut = new AzureServiceBusClient("test.servicebus.windows.net", "topic", "subscription", "12345-12345");

            sut.AddMessageHandler(mockTestHandler.Object.MessageHandler);
            sut.AddErrorMessageHandler(mockTestHandler.Object.ErrorMessageHandler);
            await sut.CallErrorMessageHandlerAsync(args);

            mockTestHandler.Verify(m => m.ErrorMessageHandler(It.Is <MessageErrorReceivedEventArgs>(e =>
                                                                                                    e.Exception.GetType() == typeof(ServiceBusException))), Times.Once);
        }
        public async Task CallsCorrectMessageHandlerUsingManagedIdentity()
        {
            var mockTestHandler     = new Mock <ITestHandler>();
            var subscription        = nameof(CallsCorrectMessageHandlerUsingManagedIdentity);
            var aircraftlandedEvent = await CreateSubscriptionAndSendAircraftLandedEventAsync(subscription);

            _azureServiceBusClient = new AzureServiceBusClient(_hostname, _topic, subscription, _tenantId);
            AddHandlers(mockTestHandler, _azureServiceBusClient);
            await _azureServiceBusClient.StartAsync();

            await Task.Delay(TimeSpan.FromSeconds(5));

            mockTestHandler.Verify(m => m.MessageHandler(It.Is <MessageReceivedEventArgs>(m =>
                                                                                          GetAircraftIdFromMessage(m.Message) == aircraftlandedEvent.AircraftId)),
                                   Times.Once);
        }
Beispiel #9
0
        public async Task RotateServiceBusSecrets_WithValidArguments_RotatesPrimarySecondaryAlternatively()
        {
            // Arrange
            var config = TestConfig.Create();
            KeyRotationConfig keyRotationConfig = config.GetKeyRotationConfig();

            _logger.LogInformation("Using Service Principal [ClientID: '{ClientId}']", keyRotationConfig.ServicePrincipal.ClientId);
            const ServiceBusEntityType entity = ServiceBusEntityType.Topic;

            var keyVaultAuthentication = new ServicePrincipalAuthentication(
                keyRotationConfig.ServicePrincipal.ClientId,
                keyRotationConfig.ServicePrincipal.ClientSecret);

            var keyVaultConfiguration = new KeyVaultConfiguration(keyRotationConfig.KeyVault.VaultUri);
            var secretProvider        = new KeyVaultSecretProvider(keyVaultAuthentication, keyVaultConfiguration);

            AzureServiceBusClient azureServiceBusClient = CreateAzureServiceBusClient(keyRotationConfig, secretProvider, entity);
            var rotation = new AzureServiceBusKeyRotation(azureServiceBusClient, keyVaultAuthentication, keyVaultConfiguration, _logger);

            var        client = new ServiceBusConfiguration(keyRotationConfig, _logger);
            AccessKeys keysBefore1stRotation = await client.GetConnectionStringKeysForTopicAsync();

            // Act
            await rotation.RotateServiceBusSecretAsync(keyRotationConfig.KeyVault.SecretName);

            // Assert
            string secondaryConnectionString = await secretProvider.GetRawSecretAsync(keyRotationConfig.KeyVault.SecretName);

            AccessKeys keysAfter1stRotation = await client.GetConnectionStringKeysForTopicAsync();

            Assert.True(secondaryConnectionString == keysAfter1stRotation.SecondaryConnectionString, "Secondary connection string should be set in Azure Key Vault after first rotation");
            Assert.NotEqual(keysBefore1stRotation.PrimaryConnectionString, keysAfter1stRotation.PrimaryConnectionString);
            Assert.NotEqual(keysBefore1stRotation.SecondaryConnectionString, keysAfter1stRotation.SecondaryConnectionString);

            await rotation.RotateServiceBusSecretAsync(keyRotationConfig.KeyVault.SecretName);

            string primaryConnectionString = await secretProvider.GetRawSecretAsync(keyRotationConfig.KeyVault.SecretName);

            AccessKeys keysAfter2ndRotation = await client.GetConnectionStringKeysForTopicAsync();

            Assert.True(primaryConnectionString == keysAfter2ndRotation.PrimaryConnectionString, "Primary connection string should be set in Azure Key Vault after second rotation");
            Assert.NotEqual(keysAfter1stRotation.PrimaryConnectionString, keysAfter2ndRotation.PrimaryConnectionString);
            Assert.NotEqual(keysAfter2ndRotation.SecondaryConnectionString, keysAfter1stRotation.SecondaryConnectionString);
        }
Beispiel #10
0
        protected override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            ProxiedHttpMethod method;

            switch (request.Method.Method)
            {
            case "POST":
                method = ProxiedHttpMethod.Post;
                break;

            case "PUT":
                method = ProxiedHttpMethod.Put;
                break;

            case "PATCH":
                method = ProxiedHttpMethod.Patch;
                break;

            default:
                throw new InvalidOperationException($"Cannot handle MethodType: {request.Method.Method}");
            }

            ProxiedHttpRequestModel proxiedRequestModel = new ProxiedHttpRequestModel(method, await request.Content.ReadAsStringAsync(), $"{AuthTokenProvider.RetrieveType()} {AuthTokenProvider.Retrieve()}", request.RequestUri.AbsolutePath);

            try
            {
                await AzureServiceBusClient.SendAsync(new Message(UTF8Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(proxiedRequestModel))));
            }
            catch (Exception e)
            {
                if (Logger.IsErrorEnabled)
                {
                    Logger.Error($"Failed to send proxied Azure Service Bus HTTP Message. Reason: {e.ToString()}");
                }

                return(new HttpResponseMessage(HttpStatusCode.BadRequest)
                {
                    Content = new StringContent($"Client Exception: {e.ToString()}")
                });
            }

            //Indicate accepted since it's not technically handled.
            return(new HttpResponseMessage(HttpStatusCode.Accepted));
        }
Beispiel #11
0
        private AzureServiceBusClient CreateAzureServiceBusClient(
            KeyRotationConfig keyRotationConfig,
            ISecretProvider secretProvider,
            ServiceBusEntityType entity)
        {
            var serviceBusAuthentication = new DefaultAzureServiceBusManagementAuthentication(
                keyRotationConfig.ServicePrincipal.ClientId,
                keyRotationConfig.ServicePrincipal.ClientSecretKey,
                keyRotationConfig.ServiceBusNamespace.SubscriptionId,
                keyRotationConfig.ServiceBusNamespace.TenantId,
                secretProvider);

            var serviceBusLocation = new AzureServiceBusNamespace(
                keyRotationConfig.ServiceBusNamespace.ResourceGroup,
                keyRotationConfig.ServiceBusNamespace.Namespace,
                entity,
                keyRotationConfig.ServiceBusNamespace.TopicName,
                keyRotationConfig.ServiceBusNamespace.AuthorizationRuleName);

            var azureServiceBusClient = new AzureServiceBusClient(serviceBusAuthentication, serviceBusLocation, _logger);

            return(azureServiceBusClient);
        }
Beispiel #12
0
        public async Task AzureServiceBusClient_PublishEvent_AsExpected()
        {
            var queueClient = new QueueClient(_configuration["ConnectionString"], "cqelight");

            var client = new AzureServiceBusClient("DA8C3F43-36C5-45F8-A773-1F11C0B77223", queueClient, new AzureServiceBusClientConfiguration(
                                                       _configuration["ConnectionString"], null, null));

            await client.PublishEventAsync(new AzureEvent { Data = "test event data" });

            bool hasCorrectlyReceived = false;

            queueClient.RegisterMessageHandler((m, c) =>
            {
                hasCorrectlyReceived = m.ContentType == typeof(AzureEvent).AssemblyQualifiedName &&
                                       m.Body != null;

                var evt = Encoding.UTF8.GetString(m.Body).FromJson <AzureEvent>();

                hasCorrectlyReceived &= evt != null && evt.Data == "test event data";

                return(Task.CompletedTask);
            }, new MessageHandlerOptions(e =>
            {
                hasCorrectlyReceived = false;
                return(Task.CompletedTask);
            }));

            int elapsedTime = 0;

            while (!hasCorrectlyReceived && elapsedTime < 2000)
            {
                elapsedTime += 50;
                await Task.Delay(50);
            }

            hasCorrectlyReceived.Should().BeTrue();
        }
Beispiel #13
0
        public async Task RotateConnectionStringKey_WithSpecifiedEntity_RotatesKeyForEntity(ServiceBusEntityType entity, KeyType keyType)
        {
            // Arrange
            var    generator             = new Faker();
            string resourceGroup         = generator.Random.Word();
            string @namespace            = generator.Random.Word();
            string entityName            = generator.Random.Word();
            string authorizationRuleName = generator.Random.Word();

            string primaryConnectionString   = generator.Random.Words();
            string secondaryConnectionString = generator.Random.Words();
            var    response = new AzureOperationResponse <AccessKeys>
            {
                Body = new AccessKeys(
                    primaryConnectionString: primaryConnectionString,
                    secondaryConnectionString: secondaryConnectionString)
            };

            Mock <ITopicsOperations> stubTopics = CreateStubTopicsOperations(resourceGroup, @namespace, entityName, authorizationRuleName, response);
            Mock <IQueuesOperations> stubQueues = CreateStubQueueOperations(resourceGroup, @namespace, entityName, authorizationRuleName, response);
            Mock <IAzureServiceBusManagementAuthentication> stubAuthentication = CreateStubAuthentication(stubTopics.Object, stubQueues.Object);

            var client = new AzureServiceBusClient(
                stubAuthentication.Object,
                new AzureServiceBusNamespace(resourceGroup, @namespace, entity, entityName, authorizationRuleName),
                NullLogger.Instance);

            // Act
            string connectionString = await client.RotateConnectionStringKeyAsync(keyType);

            // Assert
            Assert.Equal(primaryConnectionString == connectionString, KeyType.PrimaryKey == keyType);
            Assert.Equal(secondaryConnectionString == connectionString, KeyType.SecondaryKey == keyType);
            Assert.Equal(stubTopics.Invocations.Count == 1 && stubQueues.Invocations.Count == 0, ServiceBusEntityType.Topic == entity);
            Assert.Equal(stubTopics.Invocations.Count == 0 && stubQueues.Invocations.Count == 1, ServiceBusEntityType.Queue == entity);
        }
Beispiel #14
0
 protected static void AddHandlers(Mock <ITestHandler> mockTestHandler, AzureServiceBusClient sut)
 {
     sut.AddMessageHandler(mockTestHandler.Object.MessageHandler);
     sut.AddErrorMessageHandler(mockTestHandler.Object.ErrorMessageHandler);
 }