예제 #1
0
 public static string ConnectionStringUri(
     string namespaceName,
     string entityName,
     ServiceBusEntityType entityType)
 {
     return string.Format("{0}/{1}s/{2}/ConnectionDetails/?api-version={3}",
         namespaceName,
         entityType.ToString(),
         entityName,
         ServiceBusLatestVersion);
 }
예제 #2
0
        /// <summary>
        /// Removed shared access signature authorization for the service bus entity.
        /// </summary>
        /// <param name="namespaceName">The service bus namespace name</param>
        /// <param name="entityName">The fully qualified service bus entity name</param>
        /// <param name="entityType">The service bus entity type (e.g. Queue)</param>
        /// <param name="ruleName">The SAS authorization rule name</param>
        public virtual void RemoveAuthorizationRule(
            string namespaceName,
            string entityName,
            ServiceBusEntityType entityType,
            string ruleName)
        {
            bool removed = false;
            SharedAccessAuthorizationRule rule = (SharedAccessAuthorizationRule)GetAuthorizationRule(
                namespaceName,
                entityName,
                entityType,
                ruleName).Rule;

            // Create namespace manager
            NamespaceManager namespaceManager = CreateNamespaceManager(namespaceName);

            // Add the SAS rule and update the entity
            switch (entityType)
            {
            case ServiceBusEntityType.Queue:
                QueueDescription queue = namespaceManager.GetQueue(entityName);
                removed = queue.Authorization.Remove(rule);
                Debug.Assert(removed);
                namespaceManager.UpdateQueue(queue);
                break;

            case ServiceBusEntityType.Topic:
                TopicDescription topic = namespaceManager.GetTopic(entityName);
                removed = topic.Authorization.Remove(rule);
                Debug.Assert(removed);
                namespaceManager.UpdateTopic(topic);
                break;

            case ServiceBusEntityType.Relay:
                RelayDescription relay = namespaceManager.GetRelayAsync(entityName).Result;
                removed = relay.Authorization.Remove(rule);
                Debug.Assert(removed);
                namespaceManager.UpdateRelayAsync(relay).Wait();
                break;

            case ServiceBusEntityType.NotificationHub:
                NotificationHubDescription notificationHub = namespaceManager.GetNotificationHub(entityName);
                removed = notificationHub.Authorization.Remove(rule);
                Debug.Assert(removed);
                namespaceManager.UpdateNotificationHub(notificationHub);
                break;

            default:
                throw new Exception(string.Format(Resources.ServiceBusEntityTypeNotFound, entityType.ToString()));
            }
        }
        public void PublishMessage(string destination, ServiceBusEntityType entityType, Message message)
        {
            var connection = OpenConnection(destination, entityType);

            if (connection.client is IQueueClient)
            {
                var client = connection.client as IQueueClient;
                client.SendAsync(message).GetAwaiter().GetResult();
            }
            if (connection.client is ITopicClient)
            {
                var client = connection.client as ITopicClient;
                client.SendAsync(message).GetAwaiter().GetResult();
            }
            CloseConnection(connection.id);
        }
예제 #4
0
        /// <summary>
        /// Gets the authorization rule with the specified name in the entity level.
        /// </summary>
        /// <param name="namespaceName">The namespace name</param>
        /// <param name="entityName">The entity name</param>
        /// <param name="entityType">The entity type</param>
        /// <param name="ruleName">The rule name</param>
        /// <returns>The authorization rule that matches the specified name</returns>
        public virtual ExtendedAuthorizationRule GetAuthorizationRule(
            string namespaceName,
            string entityName,
            ServiceBusEntityType entityType,
            string ruleName)
        {
            AuthorizationRuleFilterOption options = new AuthorizationRuleFilterOption()
            {
                Namespace  = namespaceName,
                Name       = ruleName,
                EntityName = entityName,
                EntityType = entityType
            };

            return(FilterAuthorizationRules(options).FirstOrDefault());
        }
예제 #5
0
        /// <summary>
        /// Rotates the connection string key of the Azure Service Bus Queue, returning the new connection string as result.
        /// </summary>
        /// <param name="keyType">The type of key to rotate.</param>
        /// <returns>
        ///     The new connection string according to the <paramref name="keyType"/>.
        /// </returns>
        /// <exception cref="ArgumentOutOfRangeException">Thrown when the <paramref name="keyType"/> is not within the bounds of the enumration.</exception>
        public async Task <string> RotateConnectionStringKeysForQueueAsync(KeyType keyType)
        {
            Guard.For <ArgumentOutOfRangeException>(
                () => !Enum.IsDefined(typeof(KeyType), keyType),
                $"Requires a KeyType that is either '{nameof(KeyType.PrimaryKey)}' or '{nameof(KeyType.SecondaryKey)}'");

            var    parameters = new RegenerateAccessKeyParameters(keyType);
            string queueName  = _configuration.ServiceBusNamespace.QueueName;
            const ServiceBusEntityType entity = ServiceBusEntityType.Queue;

            try
            {
                using IServiceBusManagementClient client = await CreateServiceManagementClientAsync();

                _logger.LogTrace(
                    "Start rotating {KeyType} connection string of Azure Service Bus {EntityType} '{EntityName}'...",
                    keyType, entity, queueName);

                AccessKeys accessKeys = await client.Queues.RegenerateKeysAsync(
                    _configuration.ServiceBusNamespace.ResourceGroup,
                    _configuration.ServiceBusNamespace.Namespace,
                    queueName,
                    _configuration.ServiceBusNamespace.AuthorizationRuleName,
                    parameters);

                _logger.LogInformation(
                    "Rotated {KeyType} connection string of Azure Service Bus {EntityType} '{EntityName}'",
                    keyType, entity, queueName);

                switch (keyType)
                {
                case KeyType.PrimaryKey:   return(accessKeys.PrimaryConnectionString);

                case KeyType.SecondaryKey: return(accessKeys.SecondaryConnectionString);

                default:
                    throw new ArgumentOutOfRangeException(nameof(keyType), keyType, "Unknown key type");
                }
            }
            catch (Exception exception)
            {
                _logger.LogError(
                    exception, "Failed to rotate the {KeyType} connection string of the Azure Service Bus {EntityType} '{EntityName}'", keyType, entity, queueName);

                throw;
            }
        }
예제 #6
0
 private ExtendedAuthorizationRule CreateExtendedAuthorizationRule(
     AuthorizationRule rule,
     string namespaceName,
     string entityName,
     ServiceBusEntityType entityType)
 {
     return(new ExtendedAuthorizationRule()
     {
         Rule = rule,
         Name = rule.KeyName,
         Permission = rule.Rights.ToList(),
         ConnectionString = GetConnectionString(namespaceName, entityName, entityType, rule.KeyName),
         Namespace = namespaceName,
         EntityName = entityName,
         EntityType = entityType
     });
 }
예제 #7
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);
        }
        private async Task SetConnectionStringSecretAsync(IKeyVaultClient keyVaultClient, string secretName, string connectionString, KeyType keyType)
        {
            string vaultUri             = _configuration.VaultUri.OriginalString;
            ServiceBusEntityType entity = _serviceBusClient.Namespace.Entity;
            string entityName           = _serviceBusClient.Namespace.EntityName;

            try
            {
                _logger.LogTrace("Setting {KeyType} Azure Service Bus {EntityType} '{EntityName}' connection string key into Azure Key Vault...", keyType, entity, entityName);
                await keyVaultClient.SetSecretAsync(vaultUri, secretName, connectionString);

                _logger.LogInformation("{KeyType} Azure Service Bus {EntityType} '{EntityName}' connection string key set into Azure Key Vault", keyType, entity, entityName);
            }
            catch (Exception exception)
            {
                _logger.LogError(
                    exception, "Unable to set the {KeyType} Azure Service Bus {EntityType} '{EntityName}' connection string key into Azure Key Vault", keyType, entity, entityName);

                throw;
            }
        }
예제 #9
0
        public void LogServiceBusDependency_WithServiceBusDependency_CreatesDependencyTelemetry()
        {
            // Arrange
            var     spySink     = new InMemoryLogSink();
            string  operationId = $"operation-id-{Guid.NewGuid()}";
            ILogger logger      = CreateLogger(spySink, config => config.Enrich.WithProperty(ContextProperties.Correlation.OperationId, operationId));
            string  entityName  = $"entity-name-{Guid.NewGuid()}";
            const ServiceBusEntityType entityType = ServiceBusEntityType.Unknown;
            var startTime        = DateTimeOffset.UtcNow;
            var duration         = TimeSpan.FromSeconds(5);
            var telemetryContext = new Dictionary <string, object>
            {
                ["Namespace"] = "azure.servicebus.namespace"
            };

            logger.LogServiceBusDependency(entityName, entityType: entityType, isSuccessful: true, startTime: startTime, duration: duration, context: telemetryContext);
            LogEvent logEvent = Assert.Single(spySink.CurrentLogEmits);

            Assert.NotNull(logEvent);

            var converter = ApplicationInsightsTelemetryConverter.Create();

            // Act
            IEnumerable <ITelemetry> telemetries = converter.Convert(logEvent, formatProvider: null);

            // Assert
            AssertDoesNotContainLogProperty(logEvent, DependencyTracking.DependencyLogEntry);
            Assert.Collection(telemetries, telemetry =>
            {
                var dependencyTelemetry = Assert.IsType <DependencyTelemetry>(telemetry);
                Assert.Equal("Azure Service Bus", dependencyTelemetry.Type);
                Assert.Equal(entityName, dependencyTelemetry.Target);
                Assert.Equal(startTime, dependencyTelemetry.Timestamp);
                Assert.Equal(duration, dependencyTelemetry.Duration);
                Assert.True(dependencyTelemetry.Success);

                AssertContainsTelemetryProperty(dependencyTelemetry, "Namespace", "azure.servicebus.namespace");
                AssertContainsTelemetryProperty(dependencyTelemetry, "EntityType", entityType.ToString());
            });
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="AzureServiceBusNamespace"/> class.
        /// </summary>
        /// <param name="resourceGroup">The resource group where the Azure Service Bus resource is located.</param>
        /// <param name="namespace">The namespace where the Azure Service Bus is categorized.</param>
        /// <param name="entity">The entity type of the Azure Service Bus resource.</param>
        /// <param name="entityName">The entity name of the Azure Service Bus resource.</param>
        /// <param name="authorizationRuleName">The name of the authorization rule to use when authorizing with the Azure Service Bus.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown when the <paramref name="resourceGroup"/>, <paramref name="namespace"/>, <paramref name="entityName"/>, or <paramref name="authorizationRuleName"/> is <c>null</c>.
        /// </exception>
        /// <exception cref="ArgumentException">Thrown when the <paramref name="entity"/> is not defined within the bounds of the enumeration.</exception>
        public AzureServiceBusNamespace(
            string resourceGroup,
            string @namespace,
            ServiceBusEntityType entity,
            string entityName,
            string authorizationRuleName)
        {
            Guard.NotNullOrWhitespace(resourceGroup, nameof(resourceGroup));
            Guard.NotNullOrWhitespace(@namespace, nameof(@namespace));
            Guard.NotNullOrWhitespace(entityName, nameof(entityName));
            Guard.NotNullOrWhitespace(authorizationRuleName, nameof(authorizationRuleName));
            Guard.For <ArgumentException>(
                () => !Enum.IsDefined(typeof(ServiceBusEntityType), entity),
                $"Azure Service Bus entity '{entity}' is not defined in the '{nameof(ServiceBusEntityType)}' enumeration");
            Guard.For <ArgumentOutOfRangeException>(
                () => entity is ServiceBusEntityType.Unknown, "Azure Service Bus entity type 'Unknown' is not supported here");

            ResourceGroup         = resourceGroup;
            Namespace             = @namespace;
            Entity                = entity;
            EntityName            = entityName;
            AuthorizationRuleName = authorizationRuleName;
        }
예제 #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);
        }
예제 #12
0
        private List <ExtendedAuthorizationRule> GetAuthorizationRuleCore(
            string namespaceName,
            string entityName,
            ServiceBusEntityType entityType,
            Predicate <AuthorizationRule> match)
        {
            NamespaceManager         namespaceManager = CreateNamespaceManager(namespaceName);
            List <AuthorizationRule> rules            = null;

            switch (entityType)
            {
            case ServiceBusEntityType.Queue:
                rules = namespaceManager.GetQueue(entityName).Authorization.GetRules(match);
                break;

            case ServiceBusEntityType.Topic:
                rules = namespaceManager.GetTopic(entityName).Authorization.GetRules(match);
                break;

            case ServiceBusEntityType.Relay:
                rules = namespaceManager.GetRelayAsync(entityName).Result.Authorization.GetRules(match);
                break;

            case ServiceBusEntityType.NotificationHub:
                rules = namespaceManager.GetNotificationHub(entityName).Authorization.GetRules(match);
                break;

            default:
                throw new InvalidOperationException();
            }

            return(rules.Select(r => CreateExtendedAuthorizationRule(
                                    r,
                                    namespaceName,
                                    entityName,
                                    entityType)).ToList());
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="AzureServiceBusMessagePumpSettings"/> class.
        /// </summary>
        /// <param name="entityName">The name of the entity to process.</param>
        /// <param name="subscriptionName">The name of the subscription to process.</param>
        /// <param name="serviceBusEntity">The entity type of the Azure Service Bus.</param>
        /// <param name="serviceBusNamespace">
        ///     The Service Bus namespace to connect to. This is likely to be similar to <c>{yournamespace}.servicebus.windows.net</c>.
        /// </param>
        /// <param name="tokenCredential">The client credentials to authenticate with the Azure Service Bus.</param>
        /// <param name="options">The options that influence the behavior of the <see cref="AzureServiceBusMessagePump"/>.</param>
        /// <param name="serviceProvider">The collection of services to use during the lifetime of the <see cref="AzureServiceBusMessagePump"/>.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown when the <paramref name="options"/>, <paramref name="serviceProvider"/>, or <paramref name="tokenCredential"/> is <c>null</c>.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///     Thrown when the <paramref name="serviceBusNamespace"/> is blank or the <paramref name="serviceBusEntity"/> is outside the bounds of the enumeration.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Thrown when the <paramref name="serviceBusEntity"/> represents the unsupported value <see cref="ServiceBusEntityType.Unknown"/>.
        /// </exception>
        public AzureServiceBusMessagePumpSettings(
            string entityName,
            string subscriptionName,
            ServiceBusEntityType serviceBusEntity,
            string serviceBusNamespace,
            TokenCredential tokenCredential,
            AzureServiceBusMessagePumpOptions options,
            IServiceProvider serviceProvider)
        {
            Guard.NotNull(options, nameof(options), "Requires message pump options that influence the behavior of the message pump");
            Guard.NotNull(serviceProvider, nameof(serviceProvider), "Requires a service provider to get additional registered services during the lifetime of the message pump");
            Guard.NotNull(tokenCredential, nameof(tokenCredential), "Requires a token credential instance to authenticate with the Azure Service Bus");
            Guard.NotNullOrWhitespace(entityName, nameof(entityName), "Requires a non-blank entity name for the Azure Service Bus when using the token credentials");
            Guard.NotNullOrWhitespace(serviceBusNamespace, nameof(serviceBusNamespace), "Requires a non-blank fully qualified Azure Service Bus namespace when using the token credentials");
            Guard.For <ArgumentException>(() => !Enum.IsDefined(typeof(ServiceBusEntityType), serviceBusEntity),
                                          $"Azure Service Bus entity '{serviceBusEntity}' is not defined in the '{nameof(ServiceBusEntityType)}' enumeration");
            Guard.For <ArgumentOutOfRangeException>(() => serviceBusEntity is ServiceBusEntityType.Unknown,
                                                    "Azure Service Bus entity type 'Unknown' is not supported here");

            _serviceProvider = serviceProvider;
            _tokenCredential = tokenCredential;

            EntityName       = entityName;
            SubscriptionName = subscriptionName;
            ServiceBusEntity = serviceBusEntity;
            Options          = options;

            if (serviceBusNamespace.EndsWith(".servicebus.windows.net"))
            {
                FullyQualifiedNamespace = serviceBusNamespace;
            }
            else
            {
                FullyQualifiedNamespace = serviceBusNamespace + ".servicebus.windows.net";
            }
        }
        /// <summary>
        /// Gets available connection strings for the specified entity.
        /// </summary>
        /// <param name="namespaceName">The namespace name</param>
        /// <param name="entityName">The entity name</param>
        /// <param name="entityType">The entity type</param>
        /// <returns>List of all available connection strings</returns>
        public virtual List<ServiceBusConnectionDetail> GetConnectionString(
            string namespaceName,
            string entityName,
            ServiceBusEntityType entityType)
        {
            switch (entityType)
            {
                case ServiceBusEntityType.Queue:
                    return ServiceBusClient.Queues.GetConnectionDetails(namespaceName, entityName).ConnectionDetails
                        .ToList();

                case ServiceBusEntityType.Topic:
                    return ServiceBusClient.Topics.GetConnectionDetails(namespaceName, entityName).ConnectionDetails
                        .ToList();

                case ServiceBusEntityType.Relay:
                    return ServiceBusClient.Relays.GetConnectionDetails(namespaceName, entityName).ConnectionDetails
                        .ToList();

                case ServiceBusEntityType.NotificationHub:
                    return ServiceBusClient.NotificationHubs.GetConnectionDetails(namespaceName, entityName)
                        .ConnectionDetails
                        .ToList();

                default:
                    throw new Exception(string.Format(Resources.ServiceBusEntityTypeNotFound, entityType.ToString()));
            }
            
        }
        /// <summary>
        /// Gets the connection string with the given name for the entity.
        /// </summary>
        /// <param name="namespaceName">The namespace name</param>
        /// <param name="entityType"></param>
        /// <param name="keyName">The connection string key name</param>
        /// <param name="entityName"></param>
        /// <returns>The connection string value</returns>
        public virtual string GetConnectionString(
            string namespaceName,
            string entityName,
            ServiceBusEntityType entityType,
            string keyName)
        {
            List<ServiceBusConnectionDetail> connectionStrings = GetConnectionString(namespaceName, entityName, entityType);
            ServiceBusConnectionDetail connectionString = connectionStrings.Find(c => c.KeyName.Equals(
                keyName,
                StringComparison.OrdinalIgnoreCase));

            return connectionString.ConnectionString;
        }
        private List<ExtendedAuthorizationRule> GetAuthorizationRuleCore(
            string namespaceName,
            string entityName,
            ServiceBusEntityType entityType,
            Predicate<AuthorizationRule> match)
        {
            NamespaceManager namespaceManager = CreateNamespaceManager(namespaceName);
            List<AuthorizationRule> rules = null;

            switch (entityType)
            {
                case ServiceBusEntityType.Queue:
                    rules = namespaceManager.GetQueue(entityName).Authorization.GetRules(match);
                    break;

                case ServiceBusEntityType.Topic:
                    rules = namespaceManager.GetTopic(entityName).Authorization.GetRules(match);
                    break;

                case ServiceBusEntityType.Relay:
                    rules = namespaceManager.GetRelayAsync(entityName).Result.Authorization.GetRules(match);
                    break;

                case ServiceBusEntityType.NotificationHub:
                    rules = namespaceManager.GetNotificationHub(entityName).Authorization.GetRules(match);
                    break;

                default:
                    throw new InvalidOperationException();
            }

            return rules.Select(r => CreateExtendedAuthorizationRule(
                r,
                namespaceName,
                entityName,
                entityType)).ToList();
        }
 private ExtendedAuthorizationRule CreateExtendedAuthorizationRule(
     AuthorizationRule rule,
     string namespaceName,
     string entityName,
     ServiceBusEntityType entityType)
 {
     return new ExtendedAuthorizationRule()
     {
         Rule = rule,
         Name = rule.KeyName,
         Permission = rule.Rights.ToList(),
         ConnectionString = GetConnectionString(namespaceName, entityName, entityType, rule.KeyName),
         Namespace = namespaceName,
         EntityName = entityName,
         EntityType = entityType
     };
 }
        public async Task RotateServiceBusSecret_WithValidArguments_RotatesPrimarySecondaryAlternately(ServiceBusEntityType entity)
        {
            // Arrange
            string vaultUrl   = BogusGenerator.Internet.UrlWithPath(protocol: "https");
            string secretName = BogusGenerator.Random.Word();
            AzureServiceBusNamespace @namespace = GenerateAzureServiceBusLocation(entity);
            var response = new AzureOperationResponse <AccessKeys>
            {
                Body = new AccessKeys(
                    primaryConnectionString: BogusGenerator.Random.Words(),
                    secondaryConnectionString: BogusGenerator.Random.Words())
            };

            Mock <ITopicsOperations> stubTopics = CreateStubTopicsOperations(@namespace, response);
            Mock <IQueuesOperations> stubQueues = CreateStubQueueOperations(@namespace, response);
            Mock <IAzureServiceBusManagementAuthentication> stubServiceBusAuthentication = CreateStubAuthentication(stubTopics.Object, stubQueues.Object);
            Mock <IKeyVaultAuthentication> stubKeyVaultAuthentication = CreateStubKeyVaultAuthentication(vaultUrl, secretName, response.Body);

            var rotation = new AzureServiceBusKeyRotation(
                new AzureServiceBusClient(stubServiceBusAuthentication.Object, @namespace, NullLogger.Instance),
                stubKeyVaultAuthentication.Object, new KeyVaultConfiguration(vaultUrl), NullLogger.Instance);

            // Act
            await rotation.RotateServiceBusSecretAsync(secretName);

            // Assert
            Assert.Empty(DetermineNonRelevantInvocations(entity, stubTopics.Invocations, stubQueues.Invocations));
            Assert.Collection(DetermineRelevantInvocations(entity, stubTopics.Invocations, stubQueues.Invocations),
                              invocation => AssertInvocationKeyRotation(invocation, KeyType.SecondaryKey),
                              invocation => AssertInvocationKeyRotation(invocation, KeyType.PrimaryKey));

            await rotation.RotateServiceBusSecretAsync(secretName);

            Assert.Empty(DetermineNonRelevantInvocations(entity, stubTopics.Invocations, stubQueues.Invocations));
            Assert.Collection(DetermineRelevantInvocations(entity, stubTopics.Invocations, stubQueues.Invocations).Skip(2),
                              invocation => AssertInvocationKeyRotation(invocation, KeyType.PrimaryKey),
                              invocation => AssertInvocationKeyRotation(invocation, KeyType.SecondaryKey));
        }
예제 #19
0
        /// <summary>
        /// Updates shared access signature authorization for the service bus entity. This authorization works on
        /// public Microsoft Azure environments and Windows Azure Pack on prim as well.
        /// </summary>
        /// <param name="namespaceName">The service bus namespace name</param>
        /// <param name="entityName">The fully qualified service bus entity name</param>
        /// <param name="entityType">The service bus entity type (e.g. Queue)</param>
        /// <param name="ruleName">The SAS authorization rule name</param>
        /// <param name="primaryKey">The SAS primary key. It'll be generated if empty</param>
        /// <param name="secondaryKey">The SAS secondary key</param>
        /// <param name="permissions">Set of permissions given to the rule</param>
        /// <returns>The created Shared Access Signature authorization rule</returns>
        public virtual ExtendedAuthorizationRule UpdateSharedAccessAuthorization(
            string namespaceName,
            string entityName,
            ServiceBusEntityType entityType,
            string ruleName,
            string primaryKey,
            string secondaryKey,
            params AccessRights[] permissions)
        {
            bool removed = false;
            ExtendedAuthorizationRule rule = GetAuthorizationRule(namespaceName, entityName, entityType, ruleName);

            if (null == rule)
            {
                throw new ArgumentException(Resources.ServiceBusAuthorizationRuleNotFound);
            }

            SharedAccessAuthorizationRule oldRule = (SharedAccessAuthorizationRule)rule.Rule;

            SharedAccessAuthorizationRule newRule = new SharedAccessAuthorizationRule(
                ruleName,
                string.IsNullOrEmpty(primaryKey) ? SharedAccessAuthorizationRule.GenerateRandomKey() : primaryKey,
                secondaryKey,
                permissions ?? oldRule.Rights);

            // Create namespace manager
            NamespaceManager namespaceManager = CreateNamespaceManager(namespaceName);

            // Add the SAS rule and update the entity
            switch (entityType)
            {
            case ServiceBusEntityType.Queue:
                QueueDescription queue = namespaceManager.GetQueue(entityName);
                removed = queue.Authorization.Remove(oldRule);
                Debug.Assert(removed);
                queue.Authorization.Add(newRule);
                namespaceManager.UpdateQueue(queue);
                break;

            case ServiceBusEntityType.Topic:
                TopicDescription topic = namespaceManager.GetTopic(entityName);
                removed = topic.Authorization.Remove(oldRule);
                Debug.Assert(removed);
                topic.Authorization.Add(newRule);
                namespaceManager.UpdateTopic(topic);
                break;

            case ServiceBusEntityType.Relay:
                RelayDescription relay = namespaceManager.GetRelayAsync(entityName).Result;
                removed = relay.Authorization.Remove(oldRule);
                Debug.Assert(removed);
                relay.Authorization.Add(newRule);
                namespaceManager.UpdateRelayAsync(relay).Wait();
                break;

            case ServiceBusEntityType.NotificationHub:
                NotificationHubDescription notificationHub = namespaceManager.GetNotificationHub(entityName);
                removed = notificationHub.Authorization.Remove(oldRule);
                Debug.Assert(removed);
                notificationHub.Authorization.Add(newRule);
                namespaceManager.UpdateNotificationHub(notificationHub);
                break;

            default:
                throw new Exception(string.Format(Resources.ServiceBusEntityTypeNotFound, entityType.ToString()));
            }

            return(CreateExtendedAuthorizationRule(newRule, namespaceName, entityName, entityType));
        }
        /// <summary>
        ///     Logs an Azure Service Bus Dependency.
        /// </summary>
        /// <param name="logger">Logger to use</param>
        /// <param name="entityName">Name of the Service Bus entity</param>
        /// <param name="isSuccessful">Indication whether or not the operation was successful</param>
        /// <param name="measurement">Measuring the latency to call the Service Bus dependency</param>
        /// <param name="entityType">Type of the Service Bus entity</param>
        /// <param name="context">Context that provides more insights on the dependency that was measured</param>
        public static void LogServiceBusDependency(this ILogger logger, string entityName, bool isSuccessful, DependencyMeasurement measurement, ServiceBusEntityType entityType = ServiceBusEntityType.Unknown, Dictionary <string, object> context = null)
        {
            Guard.NotNull(logger, nameof(logger));
            Guard.NotNull(measurement, nameof(measurement));

            LogServiceBusDependency(logger, entityName, isSuccessful, measurement.StartTime, measurement.Elapsed, entityType, context);
        }
예제 #21
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ServiceBusOutputAttribute"/> class.
 /// </summary>
 /// <param name="queueOrTopicName">The name of the queue or topic to bind to.</param>
 /// <param name="entityType">The type of the entity to bind to.</param>
 public ServiceBusOutputAttribute(string queueOrTopicName, ServiceBusEntityType entityType = ServiceBusEntityType.Queue)
 {
     QueueOrTopicName = queueOrTopicName;
     EntityType       = entityType;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ServiceBusAttribute"/> class.
 /// </summary>
 /// <param name="queueOrTopicName">The name of the queue or topic to bind to.</param>
 /// <param name="serviceBusEntityType">The type of the entity to bind to.</param>
 public ServiceBusAttribute(string queueOrTopicName, ServiceBusEntityType serviceBusEntityType = ServiceBusEntityType.Queue)
 {
     QueueOrTopicName     = queueOrTopicName;
     ServiceBusEntityType = serviceBusEntityType;
 }
 public void PublishMessage(string destination, ServiceBusEntityType entityType, Message message)
 {
     Connection.PublishMessage(destination, entityType, message);
 }
        /// <summary>
        /// Gets the authorization rule with the specified name in the entity level.
        /// </summary>
        /// <param name="namespaceName">The namespace name</param>
        /// <param name="entityName">The entity name</param>
        /// <param name="entityType">The entity type</param>
        /// <param name="ruleName">The rule name</param>
        /// <returns>The authorization rule that matches the specified name</returns>
        public virtual ExtendedAuthorizationRule GetAuthorizationRule(
            string namespaceName,
            string entityName,
            ServiceBusEntityType entityType,
            string ruleName)
        {
            AuthorizationRuleFilterOption options = new AuthorizationRuleFilterOption()
            {
                Namespace = namespaceName,
                Name = ruleName,
                EntityName = entityName,
                EntityType = entityType
            };

            return FilterAuthorizationRules(options).FirstOrDefault();
        }
 public void CreatesLocation_WithBlankOutOfBoundsEntity_Throws(ServiceBusEntityType entity)
 {
     Assert.Throws <ArgumentException>(
         () => new AzureServiceBusNamespace("resource group", "namespace", entity, "entity name", "authorization rule name"));
 }
        /// <summary>
        /// Updates shared access signature authorization for the service bus entity. This authorization works on
        /// public Microsoft Azure environments and Windows Azure Pack on prim as well.
        /// </summary>
        /// <param name="namespaceName">The service bus namespace name</param>
        /// <param name="entityName">The fully qualified service bus entity name</param>
        /// <param name="entityType">The service bus entity type (e.g. Queue)</param>
        /// <param name="ruleName">The SAS authorization rule name</param>
        /// <param name="primaryKey">The SAS primary key. It'll be generated if empty</param>
        /// <param name="secondaryKey">The SAS secondary key</param>
        /// <param name="permissions">Set of permissions given to the rule</param>
        /// <returns>The created Shared Access Signature authorization rule</returns>
        public virtual ExtendedAuthorizationRule UpdateSharedAccessAuthorization(
            string namespaceName,
            string entityName,
            ServiceBusEntityType entityType,
            string ruleName,
            string primaryKey,
            string secondaryKey,
            params AccessRights[] permissions)
        {
            bool removed = false;
            ExtendedAuthorizationRule rule = GetAuthorizationRule( namespaceName, entityName, entityType, ruleName);
            if (null == rule)
            {
                throw new ArgumentException(Resources.ServiceBusAuthorizationRuleNotFound);
            }

            SharedAccessAuthorizationRule oldRule = (SharedAccessAuthorizationRule)rule.Rule;

            SharedAccessAuthorizationRule newRule = new SharedAccessAuthorizationRule(
                ruleName,
                string.IsNullOrEmpty(primaryKey) ? SharedAccessAuthorizationRule.GenerateRandomKey() : primaryKey,
                secondaryKey,
                permissions ?? oldRule.Rights);

            // Create namespace manager
            NamespaceManager namespaceManager = CreateNamespaceManager(namespaceName);

            // Add the SAS rule and update the entity
            switch (entityType)
            {
                case ServiceBusEntityType.Queue:
                    QueueDescription queue = namespaceManager.GetQueue(entityName);
                    removed = queue.Authorization.Remove(oldRule);
                    Debug.Assert(removed);
                    queue.Authorization.Add(newRule);
                    namespaceManager.UpdateQueue(queue);
                    break;

                case ServiceBusEntityType.Topic:
                    TopicDescription topic = namespaceManager.GetTopic(entityName);
                    removed = topic.Authorization.Remove(oldRule);
                    Debug.Assert(removed);
                    topic.Authorization.Add(newRule);
                    namespaceManager.UpdateTopic(topic);
                    break;

                case ServiceBusEntityType.Relay:
                    RelayDescription relay = namespaceManager.GetRelayAsync(entityName).Result;
                    removed = relay.Authorization.Remove(oldRule);
                    Debug.Assert(removed);
                    relay.Authorization.Add(newRule);
                    namespaceManager.UpdateRelayAsync(relay).Wait();
                    break;

                case ServiceBusEntityType.NotificationHub:
                    NotificationHubDescription notificationHub = namespaceManager.GetNotificationHub(entityName);
                    removed = notificationHub.Authorization.Remove(oldRule);
                    Debug.Assert(removed);
                    notificationHub.Authorization.Add(newRule);
                    namespaceManager.UpdateNotificationHub(notificationHub);
                    break;

                default:
                    throw new Exception(string.Format(Resources.ServiceBusEntityTypeNotFound, entityType.ToString()));
            }

            return CreateExtendedAuthorizationRule(newRule, namespaceName, entityName, entityType);
        }
        /// <summary>
        /// Removed shared access signature authorization for the service bus entity.
        /// </summary>
        /// <param name="namespaceName">The service bus namespace name</param>
        /// <param name="entityName">The fully qualified service bus entity name</param>
        /// <param name="entityType">The service bus entity type (e.g. Queue)</param>
        /// <param name="ruleName">The SAS authorization rule name</param>
        public virtual void RemoveAuthorizationRule(
            string namespaceName,
            string entityName,
            ServiceBusEntityType entityType,
            string ruleName)
        {
            bool removed = false;
            SharedAccessAuthorizationRule rule = (SharedAccessAuthorizationRule)GetAuthorizationRule(
                namespaceName,
                entityName,
                entityType,
                ruleName).Rule;

            // Create namespace manager
            NamespaceManager namespaceManager = CreateNamespaceManager(namespaceName);

            // Add the SAS rule and update the entity
            switch (entityType)
            {
                case ServiceBusEntityType.Queue:
                    QueueDescription queue = namespaceManager.GetQueue(entityName);
                    removed = queue.Authorization.Remove(rule);
                    Debug.Assert(removed);
                    namespaceManager.UpdateQueue(queue);
                    break;

                case ServiceBusEntityType.Topic:
                    TopicDescription topic = namespaceManager.GetTopic(entityName);
                    removed = topic.Authorization.Remove(rule);
                    Debug.Assert(removed);
                    namespaceManager.UpdateTopic(topic);
                    break;

                case ServiceBusEntityType.Relay:
                    RelayDescription relay = namespaceManager.GetRelayAsync(entityName).Result;
                    removed = relay.Authorization.Remove(rule);
                    Debug.Assert(removed);
                    namespaceManager.UpdateRelayAsync(relay).Wait();
                    break;

                case ServiceBusEntityType.NotificationHub:
                    NotificationHubDescription notificationHub = namespaceManager.GetNotificationHub(entityName);
                    removed = notificationHub.Authorization.Remove(rule);
                    Debug.Assert(removed);
                    namespaceManager.UpdateNotificationHub(notificationHub);
                    break;

                default:
                    throw new Exception(string.Format(Resources.ServiceBusEntityTypeNotFound, entityType.ToString()));
            }
        }
        /// <summary>
        ///     Logs an Azure Service Bus Dependency.
        /// </summary>
        /// <param name="logger">Logger to use</param>
        /// <param name="entityName">Name of the Service Bus entity</param>
        /// <param name="isSuccessful">Indication whether or not the operation was successful</param>
        /// <param name="startTime">Point in time when the interaction with the dependency was started</param>
        /// <param name="duration">Duration of the operation</param>
        /// <param name="entityType">Type of the Service Bus entity</param>
        /// <param name="context">Context that provides more insights on the dependency that was measured</param>
        public static void LogServiceBusDependency(this ILogger logger, string entityName, bool isSuccessful, DateTimeOffset startTime, TimeSpan duration, ServiceBusEntityType entityType = ServiceBusEntityType.Unknown, Dictionary <string, object> context = null)
        {
            Guard.NotNull(logger, nameof(logger));
            Guard.NotNullOrWhitespace(entityName, nameof(entityName));

            context = context ?? new Dictionary <string, object>();

            logger.LogWarning(ServiceBusDependencyFormat, "Azure Service Bus", entityType, entityName, duration, startTime.ToString(FormatSpecifiers.InvariantTimestampFormat), isSuccessful, context);
        }
예제 #29
0
        public ServiceBusListener(
            string functionId,
            ServiceBusEntityType entityType,
            string entityPath,
            bool isSessionsEnabled,
            bool autoCompleteMessages,
            ITriggeredFunctionExecutor triggerExecutor,
            ServiceBusOptions options,
            string connection,
            MessagingProvider messagingProvider,
            ILoggerFactory loggerFactory,
            bool singleDispatch,
            ServiceBusClientFactory clientFactory,
            ConcurrencyManager concurrencyManager)
        {
            _entityPath              = entityPath;
            _isSessionsEnabled       = isSessionsEnabled;
            _autoCompleteMessages    = autoCompleteMessages;
            _triggerExecutor         = triggerExecutor;
            _cancellationTokenSource = new CancellationTokenSource();
            _logger     = loggerFactory.CreateLogger <ServiceBusListener>();
            _functionId = functionId;

            _client = new Lazy <ServiceBusClient>(
                () =>
                clientFactory.CreateClientFromSetting(connection));

            _batchReceiver = new Lazy <ServiceBusReceiver>(
                () => messagingProvider.CreateBatchMessageReceiver(
                    _client.Value,
                    _entityPath,
                    options.ToReceiverOptions()));

            _messageProcessor = new Lazy <MessageProcessor>(
                () =>
            {
                var processorOptions = options.ToProcessorOptions(_autoCompleteMessages, concurrencyManager.Enabled);
                return(messagingProvider.CreateMessageProcessor(_client.Value, _entityPath, processorOptions));
            });

            _sessionMessageProcessor = new Lazy <SessionMessageProcessor>(
                () =>
            {
                var sessionProcessorOptions = options.ToSessionProcessorOptions(_autoCompleteMessages, concurrencyManager.Enabled);
                return(messagingProvider.CreateSessionMessageProcessor(_client.Value, _entityPath, sessionProcessorOptions));
            });

            _scaleMonitor = new Lazy <ServiceBusScaleMonitor>(
                () => new ServiceBusScaleMonitor(
                    functionId,
                    entityType,
                    _entityPath,
                    connection,
                    _batchReceiver,
                    loggerFactory,
                    clientFactory));

            if (concurrencyManager.Enabled)
            {
                _concurrencyUpdateManager = new ConcurrencyUpdateManager(concurrencyManager, _messageProcessor, _sessionMessageProcessor, _isSessionsEnabled, _functionId, _logger);
            }

            _singleDispatch    = singleDispatch;
            _serviceBusOptions = options;

            _details = new Lazy <string>(() => $"namespace='{_client.Value?.FullyQualifiedNamespace}', enityPath='{_entityPath}', singleDispatch='{_singleDispatch}', " +
                                         $"isSessionsEnabled='{_isSessionsEnabled}', functionId='{_functionId}'");
        }
예제 #30
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);
        }