Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(deps): deprecate arcus.security references in service-bus projects #471

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 18 additions & 55 deletions docs/preview/02-Features/02-message-handling/01-service-bus.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,24 +65,22 @@ public class Startup
public void ConfigureServices(IServiceCollection services)
{
// Add Service Bus Queue message pump and use OrdersMessageHandler to process the messages
// - ISecretProvider will be used to lookup the connection string scoped to the queue for secret ARCUS_SERVICEBUS_ORDERS_CONNECTIONSTRING
services.AddServiceBusQueueMessagePump("ARCUS_SERVICEBUS_ORDERS_CONNECTIONSTRING")
services.AddServiceBusQueueMessagePumpUsingManagedIdentity(
"<queue-name>", "<service-bus-fully-qualified-namespace>",)
.WithServiceBusMessageHandler<OrdersMessageHandler, Order>();

// Add Service Bus Topic message pump and use OrdersMessageHandler to process the messages on the 'My-Subscription-Name' subscription
// - Topic subscriptions over 50 characters will be truncated
// - ISecretProvider will be used to lookup the connection string scoped to the queue for secret ARCUS_SERVICEBUS_ORDERS_CONNECTIONSTRING
services.AddServiceBusTopicMessagePump("My-Subscription-Name", "ARCUS_SERVICEBUS_ORDERS_CONNECTIONSTRING")
services.AddServiceBusTopicMessagePumpUsingManagedIdentity(
"<subscription-name>", "<topic-name>", "<service-bus-fully-qualified-namespace>")
.WithServiceBusMessageHandler<OrdersMessageHandler, Order>();

// Note, that only a single call to the `.WithServiceBusMessageHandler` has to be made when the handler should be used across message pumps.
}
}
```

In this example, we are using the Azure Service Bus message pump to process a queue and a topic and use the connection string stored in the `ARCUS_SERVICEBUS_ORDERS_CONNECTIONSTRING` connection string.

> 💡 We support **connection strings that are scoped on the Service Bus namespace and entity** allowing you to choose the required security model for your applications. If you are using namespace-scoped connection strings you'll have to pass your queue/topic name as well.
> 💡 We also support **connection strings that are scoped on the Service Bus namespace and entity** allowing you to choose the required security model for your applications. If you are using namespace-scoped connection strings you'll have to pass your queue/topic name as well.

> ⚠ The order in which the message handlers are registered matters when a message is processed. If the first one can't handle the message, the second will be checked, and so forth.

Expand Down Expand Up @@ -117,7 +115,7 @@ public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddServiceBusTopicMessagePump(...)
services.AddServiceBusTopicMessagePumpUsingManagedIdentity(...)
.WithServiceBusMessageHandler<OrderMessageHandler, Order>(context => context.Properties["MessageType"].ToString() == "Order");
}
}
Expand Down Expand Up @@ -161,11 +159,11 @@ public class Startup
public void ConfigureServices(IServiceCollection services)
{
// Register the message body serializer in the dependency container where the dependent services will be injected.
services.AddServiceBusTopicMessagePump(...)
services.AddServiceBusTopicMessagePumpUsingManagedIdentity(...)
.WitServiceBusMessageHandler<OrderBatchMessageHandler>(..., messageBodySerializer: new OrderBatchMessageBodySerializer());

// Register the message body serializer in the dependency container where the dependent services are manually injected.
services.AddServiceBusTopicMessagePump(...)
services.AddServiceBusTopicMessagePumpUsingManagedIdentity(...)
.WithServiceBusMessageHandler(..., messageBodySerializerImplementationFactory: serviceProvider =>
{
var logger = serviceProvider.GetService<ILogger<OrderBatchMessageHandler>>();
Expand Down Expand Up @@ -213,7 +211,7 @@ public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddServiceBusTopicMessagePump(...)
services.AddServiceBusTopicMessagePumpUsingManagedIdentity(...)
.WithServiceMessageHandler<OrderMessageHandler, Order>((Order order) => order.Type == Department.Sales);
}
}
Expand Down Expand Up @@ -261,7 +259,7 @@ public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddServiceBusQueueMessagePump(...)
services.AddServiceBusQueueMessagePumpUsingManagedIdentity(...)
.WithServiceBusFallbackMessageHandler<WarnsUserFallbackMessageHandler>();
}
}
Expand Down Expand Up @@ -317,7 +315,7 @@ public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddServiceBusQueueMessagePump(...)
services.AddServiceBusQueueMessagePumpUsingManagedIdentity(...)
.WithServiceBusMessageHandler<AbandonUnknownOrderMessageHandler, Order>();
}
}
Expand Down Expand Up @@ -364,7 +362,7 @@ public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddServiceBusQueueMessagePump(...)
services.AddServiceBusQueueMessagePumpUsingManagedIdentity(...)
.WithServiceBusFallbackMessageHandler<DeadLetterFallbackMessageHandler>();
}
}
Expand All @@ -380,38 +378,12 @@ Next to that, we provide a **variety of overloads** to allow you to:
```csharp
using Microsoft.Extensions.DependencyInjection;

public class Startup
public class Program
{
public void ConfigureServices(IServiceCollection services)
{
// Specify the name of the Service Bus Queue:
services.AddServiceBusQueueMessagePump(
"My-Service-Bus-Queue-Name",
"ARCUS_SERVICEBUS_ORDERS_CONNECTIONSTRING");

// Specify the name of the Service Bus Topic, and provide a name for the Topic subscription:
services.AddServiceBusMessageTopicMessagePump<OrdersMessageHandler>(
"My-Service-Bus-Topic-Name",
"My-Service-Bus-Topic-Subscription-Name",
"ARCUS_SERVICEBUS_ORDERS_CONNECTIONSTRING");

// Specify a topic subscription prefix instead of a name to separate topic message pumps.
services.AddServiceBusTopicMessagePumpWithPrefix(
"My-Service-Bus-Topic-Name"
"My-Service-Bus-Subscription-Prefix",
"ARCUS_SERVICEBUS_ORDERS_CONNECTIONSTRING");

// Uses managed identity to authenticate with the Service Bus Topic:
services.AddServiceBusTopicMessagePumpUsingManagedIdentity(
topicName: properties.EntityPath,
subscriptionName: "Receive-All",
fullyQualifiedNamespace: "<your-namespace>.servicebus.windows.net"
// The optional client id to authenticate for a user assigned managed identity. More information on user assigned managed identities cam be found here:
// https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview#how-a-user-assigned-managed-identity-works-with-an-azure-vm
clientId: "<your-client-id>");

services.AddServiceBusTopicMessagePump(
"ARCUS_SERVICEBUS_ORDERS_CONNECTIONSTRING",

services.AddServiceBusTopicMessagePumpUsingManagedIdentity(...,
options =>
{
// Indicate whether or not messages should be automatically marked as completed
Expand Down Expand Up @@ -466,8 +438,7 @@ public class Startup
options.TopicSubscription = TopicSubscription.Automatic;
});

services.AddServiceBusQueueMessagePump(
"ARCUS_SERVICEBUS_ORDERS_CONNECTIONSTRING",
services.AddServiceBusQueueMessagePumpUsingManagedIdentity(...
options =>
{
// Indicate whether or not messages should be automatically marked as completed
Expand Down Expand Up @@ -518,17 +489,9 @@ public class Startup
options.Routing.Deserialization.AdditionalMembers = AdditionalMembersHandling.Ignore;
});

// Uses managed identity to authenticate with the Service Bus Topic:
services.AddServiceBusQueueMessagePumpUsingManagedIdentity(
queueName: "orders",
serviceBusNamespace: "<your-namespace>"
// The optional client id to authenticate for a user assigned managed identity. More information on user assigned managed identities cam be found here:
// https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview#how-a-user-assigned-managed-identity-works-with-an-azure-vm
clientId: "<your-client-id>");

// Multiple message handlers can be added to the services, based on the message type (ex. 'Order', 'Customer'...),
// the correct message handler will be selected.
services.AddServiceBusQueueMessagePump(...)
services.AddServiceBusQueueMessagePumpUsingManagedIdentity(...)
.WithServiceBusMessageHandler<OrdersMessageHandler, Order>()
.WithMessageHandler<CustomerMessageHandler, Customer>();
}
Expand Down Expand Up @@ -576,7 +539,7 @@ public void ConfigureServices(IServiceCollection services)
return new TrackedAzureServiceBusMessageRouter(serviceProvider, logger);
});

services.AddServiceBusQueueMessagePump(...);
services.AddServiceBusQueueMessagePumpUsingMangedIdentity(...);
}
```

Expand Down
26 changes: 0 additions & 26 deletions docs/preview/02-Features/04-service-bus-extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,6 @@ This features requires to install our NuGet package:
PM > Install-Package Arcus.Messaging.ServiceBus.Core
```

## Using Arcus secret store when registering the Service Bus client

When registering a `ServiceBusClient` via [Azure's client registration process](https://learn.microsoft.com/en-us/dotnet/api/overview/azure/messaging.servicebus-readme), the library provides an extension to pass-in a secret name instead of directly passing the Azure Service Bus connection string.
This secret name will correspond with a registered secret in the [Arcus secret store](https://security.arcus-azure.net/features/secret-store) that holds the Azure Service Bus connection string.

Following example shows how the secret name is passed to this extension overload:

```csharp
using Microsoft.Extensions.Azure;
using Microsoft.Extensions.DependencyInjection;

public class Program
{
public void ConfigureServices(IServiceCollection services)
{
// Adding Arcus secret store, more info: https://security.arcus-azure.net/features/secret-store
services.AddSecretStore(stores => stores.AddAzureKeyVaultWithManagedIdentity("https://my.vault.azure.net");

// Adding Service Bus client with secret in Arcus secret store.
services.AddAzureClients(clients => clients.AddServiceBusClient(connectionStringSecretName: "<your-secret-name>"));
}
}
```

🥇 Adding your Azure Service Bus client this way helps separating application configuration from sensitive secrets. For more information on the added-values of the Arcus secret store, see [our dedicated documentation page](https://security.arcus-azure.net/features/secret-store).

## Automatic tracking and Hierarchical correlating of Service Bus messages

The Arcus message pump/router automatically makes sure that received Azure Service Bus messages are tracked as request telemetry in Application Insights.
Expand Down
6 changes: 3 additions & 3 deletions docs/preview/02-Features/06-general-messaging.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ After the message pump and/or message handlers are registered, you can add one o
```csharp
using Arcus.Messaging.Pumps.Abstractions;

services.AddServiceBusMessagePump(...)
services.AddServiceBusMessagePumpUsingManagedIdentity(...)
.WithCircuitBreakerStateChangedEventHandler<MyFirstCircuitBreakerEventHandler>()
.WithCircuitBreakerStateChangedEventHandler<MySecondCircuitBreakerEventHandler>();
```
Expand Down Expand Up @@ -127,10 +127,10 @@ public class Program
{
public void ConfigureServices(IServiceCollection services)
{
services.AddServiceBusMessagePump(..., options => options.JobId = "abc-123")
services.AddServiceBusMessagePumpUsingManagedIdentity(..., options => options.JobId = "abc-123")
.WithServiceBusMessageHandler<..., ...>();

services.AddEventHubsMessagePump(..., options => options.JobId = "def-456")
services.AddEventHubsMessagePumpUsingManagedIdentity(..., options => options.JobId = "def-456")
.WithEventHubsMessageHandler<..., ...>();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace Arcus.Messaging.Pumps.ServiceBus
/// <summary>
/// Represents a client to interact with a Azure Service Bus.
/// </summary>
[Obsolete("Will be removed in v3.0, please use Microsoft's built-in Azure SDK clients to construct " + nameof(ServiceBusManagementClient) + " instances which can rotate Azure Service bus keys")]
public class AzureServiceBusClient
{
private readonly IAzureServiceBusManagementAuthentication _authentication;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using System;
using Microsoft.Azure.Management.ServiceBus;
using Microsoft.Extensions.Logging;

namespace Arcus.Messaging.Pumps.ServiceBus
{
/// <summary>
/// Represents the namespace of a Azure Service Bus resource; where the Azure Service Bus is located.
/// </summary>
[Obsolete("Will be removed in v3.0, please use Microsoft's built-in Azure SDK clients to construct " + nameof(ServiceBusManagementClient) + " instances which can rotate Azure Service bus keys")]
public class AzureServiceBusNamespace
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,51 @@ public class AzureServiceBusMessagePumpSettings
private readonly TokenCredential _tokenCredential;
private readonly IServiceProvider _serviceProvider;

/// <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="getConnectionStringFromConfigurationFunc">The function to look up the connection string from the configuration.</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="getConnectionStringFromConfigurationFunc"/>, <paramref name="options"/> or <paramref name="serviceProvider"/> is <c>null</c>.
/// </exception>
public AzureServiceBusMessagePumpSettings(
string entityName,
string subscriptionName,
ServiceBusEntityType serviceBusEntity,
Func<IConfiguration, string> getConnectionStringFromConfigurationFunc,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of having to retrieve the connctionstring from config.
Why not just pass in the connectionstring as a string ? Its the responsibility of the user to retrieve it from any location he wants.

AzureServiceBusMessagePumpOptions options,
IServiceProvider serviceProvider)
{
if (serviceBusEntity is ServiceBusEntityType.Topic && string.IsNullOrWhiteSpace(subscriptionName))
{
throw new ArgumentException("Requires a non-blank Azure Service bus topic subscription name", nameof(subscriptionName));
}

if (getConnectionStringFromConfigurationFunc is null)
{
throw new ArgumentNullException(nameof(getConnectionStringFromConfigurationFunc));
}

if (!Enum.IsDefined(typeof(ServiceBusEntityType), serviceBusEntity) || serviceBusEntity is ServiceBusEntityType.Unknown)
{
throw new ArgumentException(
$"Azure Service Bus entity type should either be '{ServiceBusEntityType.Queue}' or '{ServiceBusEntityType.Topic}'", nameof(serviceBusEntity));
}

_serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
_getConnectionStringFromConfigurationFunc = getConnectionStringFromConfigurationFunc;

EntityName = entityName;
SubscriptionName = subscriptionName;
ServiceBusEntity = serviceBusEntity;
Options = options ?? throw new ArgumentNullException(nameof(options));
}

/// <summary>
/// Initializes a new instance of the <see cref="AzureServiceBusMessagePumpSettings"/> class.
/// </summary>
Expand All @@ -38,6 +83,7 @@ public class AzureServiceBusMessagePumpSettings
/// <exception cref="ArgumentException">
/// Thrown when the <paramref name="getConnectionStringFromConfigurationFunc"/> nor the <paramref name="getConnectionStringFromSecretFunc"/> is available.
/// </exception>
[Obsolete("Will be removed in v3.0, please use the other constructor without the " + nameof(ISecretProvider))]
public AzureServiceBusMessagePumpSettings(
string entityName,
string subscriptionName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace Arcus.Messaging.Pumps.ServiceBus
/// <summary>
/// Represents the authentication with the Azure Service Bus.
/// </summary>
[Obsolete("Will be removed in v3.0, please use Microsoft's built-in Azure SDK clients to construct " + nameof(ServiceBusManagementClient) + " instances")]
public class DefaultAzureServiceBusManagementAuthentication : IAzureServiceBusManagementAuthentication
{
private readonly string _clientId, _clientSecretKey, _subscriptionId, _tenantId;
Expand Down
Loading
Loading