Skip to content
Merged
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
3 changes: 2 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -506,4 +506,5 @@ dotnet_diagnostic.S1135.severity = suggestion # https://github.com/atc-net
dotnet_diagnostic.CA1062.severity = none # Do not demand null-checking when using nullable reference types.
dotnet_diagnostic.SA1011.severity = none # Space needed after closing square bracet "]" needed for nullable arrays
dotnet_diagnostic.SA1401.severity = none # Field should be private
dotnet_diagnostic.CA1051.severity = none # Do not declare visible instance fields
dotnet_diagnostic.CA1051.severity = none # Do not declare visible instance fields
dotnet_diagnostic.CA1812.severity = none # Internal classes are instantiated by IoC
62 changes: 31 additions & 31 deletions Atc.Azure.Messaging.sln
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 15.0.26124.0
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Atc.Azure.Messaging", "src\Atc.Azure.Messaging\Atc.Azure.Messaging.csproj", "{2F7702F2-A407-41FB-8C88-7C066237BC75}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Atc.Azure.Messaging.Tests", "test\Atc.Azure.Messaging.Tests\Atc.Azure.Messaging.Tests.csproj", "{0C49EE44-DAE3-4A7C-9D2D-D1190CAC85F0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2F7702F2-A407-41FB-8C88-7C066237BC75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2F7702F2-A407-41FB-8C88-7C066237BC75}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2F7702F2-A407-41FB-8C88-7C066237BC75}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2F7702F2-A407-41FB-8C88-7C066237BC75}.Release|Any CPU.Build.0 = Release|Any CPU
{0C49EE44-DAE3-4A7C-9D2D-D1190CAC85F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0C49EE44-DAE3-4A7C-9D2D-D1190CAC85F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0C49EE44-DAE3-4A7C-9D2D-D1190CAC85F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0C49EE44-DAE3-4A7C-9D2D-D1190CAC85F0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1EC093F7-1E03-4088-BA72-0DEB39AFEE82}
EndGlobalSection
EndGlobal

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 15.0.26124.0
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Atc.Azure.Messaging", "src\Atc.Azure.Messaging\Atc.Azure.Messaging.csproj", "{2F7702F2-A407-41FB-8C88-7C066237BC75}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Atc.Azure.Messaging.Tests", "test\Atc.Azure.Messaging.Tests\Atc.Azure.Messaging.Tests.csproj", "{0C49EE44-DAE3-4A7C-9D2D-D1190CAC85F0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2F7702F2-A407-41FB-8C88-7C066237BC75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2F7702F2-A407-41FB-8C88-7C066237BC75}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2F7702F2-A407-41FB-8C88-7C066237BC75}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2F7702F2-A407-41FB-8C88-7C066237BC75}.Release|Any CPU.Build.0 = Release|Any CPU
{0C49EE44-DAE3-4A7C-9D2D-D1190CAC85F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0C49EE44-DAE3-4A7C-9D2D-D1190CAC85F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0C49EE44-DAE3-4A7C-9D2D-D1190CAC85F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0C49EE44-DAE3-4A7C-9D2D-D1190CAC85F0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1EC093F7-1E03-4088-BA72-0DEB39AFEE82}
EndGlobalSection
EndGlobal
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,46 @@ builder.Services.AddSwaggerGen();
builder.Services.ConfigureMessagingServices(builder.Configuration);
```

## Connecting with Managed Identity

When connecting with Managed Identity you need to setup your configuration accordingly.

The following is an example of how you would configure your EventHub or ServiceBus with Managed Identity for [ATC Azure Options](https://github.com/atc-net/atc-azure-options)

```json
{
"EventHubOptions": {
"FullyQualifiedNamespace": "[your eventhub namespace].servicebus.windows.net"
},
"ServiceBusOptions": {
"FullyQualifiedNamespace": "[your servicebus namespace].servicebus.windows.net"
},
"ClientAuthorizationOptions": {
"TenantId": "[your tenant id]"
},
"EnvironmentOptions": {
"EnvironmentType": "[Local/DevTest/Production]"
}
}
```

It is important that the logged-in user/application has the `Azure Service Bus Data Sender` or `Azure Service Bus Data Owner` build-in role for [ServiceBus](https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-managed-service-identity#azure-built-in-roles-for-azure-service-bus).

And the corresponding `Azure Event Hubs Data Sender` or `Azure Event Hubs Data Owner` build-in roles for [Eventhubs](https://learn.microsoft.com/en-us/azure/event-hubs/authenticate-application#built-in-roles-for-azure-event-hubs)

The dependencies are registered using `ConfigureMessagingServices(IConfiguration, bool)` for the default implementation of [IAzureCredentialOptionsProvider](https://github.com/atc-net/atc-azure-options/blob/main/src/Atc.Azure.Options/Providers/AzureCredentialOptionsProvider.cs) and `ConfigureMessagingServices(IConfiguration, bool, IAzureCredentialOptionsProvider)` if you wish to use your own implementation of `IAzureCredentialOptionsProvider`.

Here's an example of the default implementation using a Minimal API setup

```csharp
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// Register Atc.Azure.Messaging dependencies
builder.Services.ConfigureMessagingServices(builder.Configuration, true);
```

## Publishing to EventHub

To publish events to an EventHub you need an instance of `IEventHubPublisher`, this can be constructed via the `IEventHubPublisherFactory` which exposes the `Create(string eventHubName)` method
Expand Down
8 changes: 4 additions & 4 deletions sample/SampleApi/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
builder.Services.AddSingleton<SendDataHandler>();

// Register Atc.Azure.Messaging dependencies
builder.Services.ConfigureMessagingServices(builder.Configuration);
var useManagedIdentity = false;
builder.Services.ConfigureMessagingServices(builder.Configuration, useManagedIdentity);

var app = builder.Build();
app.UseHttpsRedirection();
Expand All @@ -38,15 +39,14 @@ public SendDataHandler(
IEventHubPublisherFactory eventHubFactory,
IServiceBusPublisher serviceBusPublisher)
{
eventHubPublisher = eventHubFactory.Create("[existing eventhub");
eventHubPublisher = eventHubFactory.Create("[existing eventhub]");
this.serviceBusPublisher = serviceBusPublisher;
}

public async Task<Response> Post(Request request)
{
await eventHubPublisher.PublishAsync(request);

await serviceBusPublisher.PublishAsync("existing topic|queue", request);
await serviceBusPublisher.PublishAsync("[existing topic|queue]", request);

return new Response(
Guid.NewGuid().ToString("N"),
Expand Down
9 changes: 9 additions & 0 deletions sample/SampleApi/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,14 @@
"AllowedHosts": "*",
"EventHubOptions": {
"ConnectionString": "Endpoint=sb://[your eventhub namespace].servicebus.windows.net/;SharedAccessKeyName=[eventhub name];SharedAccessKey=[sas key]"
},
"ServiceBusOptions": {
"FullyQualifiedNamespace": "[your servicebus namespace].servicebus.windows.net"
},
"ClientAuthorizationOptions": {
"TenantId": "[your tenant id]"
},
"EnvironmentOptions": {
"EnvironmentType": "Local"
}
}
4 changes: 2 additions & 2 deletions src/Atc.Azure.Messaging/Atc.Azure.Messaging.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
</PropertyGroup>

<ItemGroup>
<None Include="..\..\README.md" Pack="true" PackagePath="\"/>
<None Include="..\..\README.md" Pack="true" PackagePath="\" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Atc.Azure.Options" Version="3.0.14" />
<PackageReference Include="Atc.Azure.Options" Version="3.0.18" />
<PackageReference Include="Azure.Messaging.EventHubs" Version="5.7.0" />
<PackageReference Include="Azure.Messaging.ServiceBus" Version="7.8.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Diagnostics.CodeAnalysis;
Copy link
Member

Choose a reason for hiding this comment

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

Move to GlobalUsings

using Atc.Azure.Options.Authorization;
using Atc.Azure.Options.Environment;
using Atc.Azure.Options.EventHub;
using Atc.Azure.Options.Providers;
using Azure.Identity;
using Azure.Messaging.EventHubs.Producer;

namespace Atc.Azure.Messaging.EventHub;

[SuppressMessage(
"Reliability",
"CA2000:Dispose objects before losing scope",
Justification = "EventHubPublisher is responsible for disposing EventHubProducerClient")]
internal sealed class EventHubCredentialsPublisherFactory : IEventHubPublisherFactory
{
private readonly string fullyQualifiedNamespace;
private readonly DefaultAzureCredentialOptions credentialOptions;

public EventHubCredentialsPublisherFactory(
EventHubOptions options,
EnvironmentOptions environmentOptions,
ClientAuthorizationOptions clientCredentialOptions,
IAzureCredentialOptionsProvider credentialOptionsProvider)
{
this.fullyQualifiedNamespace = options.FullyQualifiedNamespace;
this.credentialOptions = credentialOptionsProvider
.GetAzureCredentialOptions(
environmentOptions,
clientCredentialOptions);
}

public IEventHubPublisher Create(string eventHubName)
=> new EventHubPublisher(
new EventHubProducerClient(
fullyQualifiedNamespace,
eventHubName,
new DefaultAzureCredential(credentialOptions)));
}
2 changes: 1 addition & 1 deletion src/Atc.Azure.Messaging/EventHub/EventHubPublisher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace Atc.Azure.Messaging.EventHub;

public sealed class EventHubPublisher : IEventHubPublisher
internal sealed class EventHubPublisher : IEventHubPublisher
{
private readonly EventHubProducerClient client;

Expand Down
9 changes: 6 additions & 3 deletions src/Atc.Azure.Messaging/EventHub/EventHubPublisherFactory.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
using System.Diagnostics.CodeAnalysis;
using Atc.Azure.Options.EventHub;
using Azure.Messaging.EventHubs.Producer;

namespace Atc.Azure.Messaging.EventHub;

#pragma warning disable CA2000 // Dispose objects before losing scope

public class EventHubPublisherFactory : IEventHubPublisherFactory
[SuppressMessage(
"Reliability",
"CA2000:Dispose objects before losing scope",
Justification = "EventHubPublisher is responsible for disposing EventHubProducerClient")]
internal sealed class EventHubPublisherFactory : IEventHubPublisherFactory
{
private readonly string connectionString;

Expand Down
8 changes: 7 additions & 1 deletion src/Atc.Azure.Messaging/EventHub/IEventHubPublisher.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
namespace Atc.Azure.Messaging.EventHub;
namespace Atc.Azure.Messaging.EventHub;

/// <summary>
/// Publisher responsible for publishing objects with metadata to a specific EventHub.
/// </summary>
/// <remarks>
/// Is safe to cache and use in singletons for the lifetime of the application.
/// </remarks>
public interface IEventHubPublisher : IAsyncDisposable
{
Task PublishAsync(
Expand Down
3 changes: 3 additions & 0 deletions src/Atc.Azure.Messaging/EventHub/IEventHubPublisherFactory.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
namespace Atc.Azure.Messaging.EventHub;

/// <summary>
/// Factory responsible for creating <see cref="IEventHubPublisher"/>s for a specific EventHub namespace.
/// </summary>
public interface IEventHubPublisherFactory
{
IEventHubPublisher Create(string eventHubName);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using Azure.Messaging.ServiceBus;
using Azure.Messaging.ServiceBus;

namespace Atc.Azure.Messaging.ServiceBus;

public interface IServiceBusClientFactory
internal interface IServiceBusClientFactory
{
ServiceBusClient Create();
}
3 changes: 3 additions & 0 deletions src/Atc.Azure.Messaging/ServiceBus/IServiceBusPublisher.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
namespace Atc.Azure.Messaging.ServiceBus;

/// <summary>
/// Publisher responsible for publishing objects with metadata to a specific ServiceBus.
/// </summary>
public interface IServiceBusPublisher
{
Task PublishAsync(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Atc.Azure.Messaging.ServiceBus;

public interface IServiceBusSenderProvider
internal interface IServiceBusSenderProvider
{
ServiceBusSender GetSender(string topicName);
}
4 changes: 2 additions & 2 deletions src/Atc.Azure.Messaging/ServiceBus/ServiceBusClientFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Atc.Azure.Messaging.ServiceBus;

public class ServiceBusClientFactory : IServiceBusClientFactory
internal sealed class ServiceBusClientFactory : IServiceBusClientFactory
{
private readonly ServiceBusOptions options;

Expand All @@ -12,5 +12,5 @@ public ServiceBusClientFactory(ServiceBusOptions options)
this.options = options;
}

public ServiceBusClient Create() => new (options.ConnectionString);
public ServiceBusClient Create() => new ServiceBusClient(options.ConnectionString);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Atc.Azure.Options.Authorization;
Copy link
Member

Choose a reason for hiding this comment

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

Move to GlobalUsings

using Atc.Azure.Options.Environment;
using Atc.Azure.Options.Providers;
using Atc.Azure.Options.ServiceBus;
using Azure.Identity;
using Azure.Messaging.ServiceBus;

namespace Atc.Azure.Messaging.ServiceBus;

internal sealed class ServiceBusCredentialsClientFactory : IServiceBusClientFactory
{
private readonly string fullyQualifiedNamespace;
private readonly DefaultAzureCredentialOptions credentialOptions;

public ServiceBusCredentialsClientFactory(
ServiceBusOptions options,
EnvironmentOptions environmentOptions,
ClientAuthorizationOptions clientCredentialOptions,
IAzureCredentialOptionsProvider credentialOptionsProvider)
{
this.fullyQualifiedNamespace = options.FullyQualifiedNamespace;
this.credentialOptions = credentialOptionsProvider
.GetAzureCredentialOptions(
environmentOptions,
clientCredentialOptions);
}

public ServiceBusClient Create() => new ServiceBusClient(
fullyQualifiedNamespace,
new DefaultAzureCredential(credentialOptions));
}
2 changes: 1 addition & 1 deletion src/Atc.Azure.Messaging/ServiceBus/ServiceBusPublisher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Atc.Azure.Messaging.ServiceBus;

public class ServiceBusPublisher : IServiceBusPublisher
internal sealed class ServiceBusPublisher : IServiceBusPublisher
{
private readonly IServiceBusSenderProvider clientProvider;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Atc.Azure.Messaging.ServiceBus;

public sealed class ServiceBusSenderProvider : IServiceBusSenderProvider
internal sealed class ServiceBusSenderProvider : IServiceBusSenderProvider
{
private readonly ServiceBusClient client;
private readonly ConcurrentDictionary<string, ServiceBusSender> senders;
Expand Down
Loading