Skip to content
This repository was archived by the owner on Apr 29, 2022. It is now read-only.

Commit 5415991

Browse files
Merge pull request #44 from AntonyVorontsov/feature/ssl-option
Feature/ssl option
2 parents df383a5 + 7a38d16 commit 5415991

File tree

7 files changed

+227
-2
lines changed

7 files changed

+227
-2
lines changed

RabbitMQ.Client.Core.DependencyInjection.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Examples.AdvancedConfigurat
4747
EndProject
4848
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Examples.BatchMessageHandler", "examples\Examples.BatchMessageHandler\Examples.BatchMessageHandler.csproj", "{BC9BE326-AEFE-42F2-B592-80126188514D}"
4949
EndProject
50+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example.SslProducer", "examples\Example.SslProducer\Example.SslProducer.csproj", "{863CDE58-B16B-4058-8C48-DB78058DDDC9}"
51+
EndProject
5052
Global
5153
GlobalSection(SolutionConfigurationPlatforms) = preSolution
5254
Debug|Any CPU = Debug|Any CPU
@@ -81,6 +83,10 @@ Global
8183
{BC9BE326-AEFE-42F2-B592-80126188514D}.Debug|Any CPU.Build.0 = Debug|Any CPU
8284
{BC9BE326-AEFE-42F2-B592-80126188514D}.Release|Any CPU.ActiveCfg = Release|Any CPU
8385
{BC9BE326-AEFE-42F2-B592-80126188514D}.Release|Any CPU.Build.0 = Release|Any CPU
86+
{863CDE58-B16B-4058-8C48-DB78058DDDC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
87+
{863CDE58-B16B-4058-8C48-DB78058DDDC9}.Debug|Any CPU.Build.0 = Debug|Any CPU
88+
{863CDE58-B16B-4058-8C48-DB78058DDDC9}.Release|Any CPU.ActiveCfg = Release|Any CPU
89+
{863CDE58-B16B-4058-8C48-DB78058DDDC9}.Release|Any CPU.Build.0 = Release|Any CPU
8490
EndGlobalSection
8591
GlobalSection(SolutionProperties) = preSolution
8692
HideSolutionNode = FALSE
@@ -94,6 +100,7 @@ Global
94100
{85907F19-00B0-4BA6-9B7C-0452A174903D} = {9D0289B2-C566-46CC-A53A-471BCBA0F277}
95101
{0C713913-8D54-49E7-AADD-45497216E2EF} = {04EFD8F7-5120-4072-9728-64203F6F4873}
96102
{BC9BE326-AEFE-42F2-B592-80126188514D} = {04EFD8F7-5120-4072-9728-64203F6F4873}
103+
{863CDE58-B16B-4058-8C48-DB78058DDDC9} = {04EFD8F7-5120-4072-9728-64203F6F4873}
97104
EndGlobalSection
98105
GlobalSection(ExtensibilityGlobals) = postSolution
99106
SolutionGuid = {0EBBD182-65B2-47F9-ABBE-64B5B8C9652F}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>netcoreapp3.1</TargetFramework>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.3" />
10+
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.3" />
11+
</ItemGroup>
12+
13+
<ItemGroup>
14+
<ProjectReference Include="..\..\src\RabbitMQ.Client.Core.DependencyInjection\RabbitMQ.Client.Core.DependencyInjection.csproj" />
15+
</ItemGroup>
16+
17+
<ItemGroup>
18+
<None Remove="appsettings.json" />
19+
<Content Include="appsettings.json">
20+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
21+
</Content>
22+
</ItemGroup>
23+
24+
</Project>
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using System.Collections.Generic;
2+
using System.IO;
3+
using System.Net.Security;
4+
using System.Threading.Tasks;
5+
using Microsoft.Extensions.Configuration;
6+
using Microsoft.Extensions.DependencyInjection;
7+
using RabbitMQ.Client.Core.DependencyInjection;
8+
using RabbitMQ.Client.Core.DependencyInjection.Configuration;
9+
using RabbitMQ.Client.Core.DependencyInjection.Services;
10+
11+
namespace Example.SslProducer
12+
{
13+
public static class Program
14+
{
15+
public static IConfiguration Configuration { get; set; }
16+
17+
public static async Task Main()
18+
{
19+
var builder = new ConfigurationBuilder()
20+
.SetBasePath(Directory.GetCurrentDirectory())
21+
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
22+
Configuration = builder.Build();
23+
24+
var serviceCollection = new ServiceCollection();
25+
ConfigureServices(serviceCollection);
26+
27+
var serviceProvider = serviceCollection.BuildServiceProvider();
28+
var queueService = serviceProvider.GetRequiredService<IQueueService>();
29+
30+
for (var i = 0; i < 10; i++)
31+
{
32+
var message = new
33+
{
34+
Name = "Custom message",
35+
Flag = true,
36+
Index = i,
37+
Numbers = new[] { 1, 2, 3 }
38+
};
39+
await queueService.SendAsync(message, "exchange.name", "routing.key");
40+
}
41+
}
42+
43+
static void ConfigureServices(IServiceCollection services)
44+
{
45+
// You can either use a json configuration or bind options by yourself.
46+
var rabbitMqConfiguration = Configuration.GetSection("RabbitMq");
47+
// There are both examples of json and manual configuration.
48+
//var rabbitMqConfiguration = GetClientOptions();
49+
50+
var exchangeOptions = GetExchangeOptions();
51+
52+
services.AddRabbitMqClient(rabbitMqConfiguration)
53+
.AddProductionExchange("exchange.name", exchangeOptions);
54+
}
55+
56+
static RabbitMqClientOptions GetClientOptions() =>
57+
new RabbitMqClientOptions
58+
{
59+
UserName = "guest",
60+
Password = "guest",
61+
TcpEndpoints = new List<RabbitMqTcpEndpoint>
62+
{
63+
new RabbitMqTcpEndpoint
64+
{
65+
HostName = "127.0.0.1",
66+
Port = 5671,
67+
SslOption = new RabbitMqSslOption
68+
{
69+
Enabled = true,
70+
ServerName = "yourCA",
71+
CertificatePath = "/path/tp/client-key-store.p12",
72+
CertificatePassphrase = "yourPathPhrase",
73+
AcceptablePolicyErrors = SslPolicyErrors.RemoteCertificateChainErrors | SslPolicyErrors.RemoteCertificateNameMismatch
74+
}
75+
}
76+
}
77+
};
78+
79+
static RabbitMqExchangeOptions GetExchangeOptions() =>
80+
new RabbitMqExchangeOptions
81+
{
82+
Queues = new List<RabbitMqQueueOptions>
83+
{
84+
new RabbitMqQueueOptions
85+
{
86+
Name = "myqueue",
87+
RoutingKeys = new HashSet<string> { "routing.key" }
88+
}
89+
}
90+
};
91+
}
92+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"RabbitMq": {
3+
"TcpEndpoints": [
4+
{
5+
"HostName": "127.0.0.1",
6+
"Port": 5671,
7+
"SslOption": {
8+
"Enabled": true,
9+
"ServerName": "yourCA",
10+
"CertificatePath": "/path/tp/client-key-store.p12",
11+
"CertificatePassphrase": "yourPathPhrase",
12+
"AcceptablePolicyErrors": "RemoteCertificateChainErrors, RemoteCertificateNameMismatch"
13+
}
14+
}
15+
],
16+
"UserName": "guest",
17+
"Password": "guest"
18+
},
19+
"RabbitMqExchange": {
20+
"Queues": [
21+
{
22+
"Name": "myqueue",
23+
"RoutingKeys": [ "routing.key" ]
24+
}
25+
]
26+
}
27+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System.Net.Security;
2+
3+
namespace RabbitMQ.Client.Core.DependencyInjection.Configuration
4+
{
5+
/// <summary>
6+
/// Ssl option model.
7+
/// </summary>
8+
public class RabbitMqSslOption
9+
{
10+
/// <summary>
11+
/// Canonical server name.
12+
/// </summary>
13+
public string ServerName { get; set; }
14+
15+
/// <summary>
16+
/// Path to the certificate.
17+
/// </summary>
18+
public string CertificatePath { get; set; }
19+
20+
/// <summary>
21+
/// A passphrase for the certificate.
22+
/// </summary>
23+
public string CertificatePassphrase { get; set; }
24+
25+
/// <summary>
26+
/// Flag that defines if certificate should be used.
27+
/// </summary>
28+
public bool Enabled { get; set; } = true;
29+
30+
/// <summary>
31+
/// Acceptable policy errors.
32+
/// </summary>
33+
/// <remarks>
34+
/// SslPolicyErrors is a flag enum, so you can have multiple set values.
35+
/// </remarks>
36+
public SslPolicyErrors? AcceptablePolicyErrors { get; set; }
37+
}
38+
}

src/RabbitMQ.Client.Core.DependencyInjection/Configuration/RabbitMqTcpEndpoint.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,13 @@ public class RabbitMqTcpEndpoint
1414
/// Tcp connection port.
1515
/// </summary>
1616
public int Port { get; set; } = 5672;
17+
18+
/// <summary>
19+
/// Ssl option.
20+
/// </summary>
21+
/// <remarks>
22+
/// Should be null if certificate should not be used.
23+
/// </remarks>
24+
public RabbitMqSslOption SslOption { get; set; }
1725
}
1826
}

src/RabbitMQ.Client.Core.DependencyInjection/Services/RabbitMqConnectionFactory.cs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Linq;
34
using System.Threading;
45
using RabbitMQ.Client.Core.DependencyInjection.Configuration;
@@ -41,8 +42,7 @@ public IConnection CreateRabbitMqConnection(RabbitMqClientOptions options)
4142

4243
if (options.TcpEndpoints?.Any() == true)
4344
{
44-
var clientEndpoints = options.TcpEndpoints.Select(x => new AmqpTcpEndpoint(x.HostName, x.Port)).ToList();
45-
return TryToCreateConnection(() => factory.CreateConnection(clientEndpoints), options.InitialConnectionRetries, options.InitialConnectionRetryTimeoutMilliseconds);
45+
return CreateConnectionWithTcpEndpoints(options, factory);
4646
}
4747

4848
return string.IsNullOrEmpty(options.ClientProvidedName)
@@ -57,6 +57,35 @@ public IConnection CreateRabbitMqConnection(RabbitMqClientOptions options)
5757
/// <returns>A consumer instance <see cref="AsyncEventingBasicConsumer"/>.</returns>
5858
public AsyncEventingBasicConsumer CreateConsumer(IModel channel) => new AsyncEventingBasicConsumer(channel);
5959

60+
static IConnection CreateConnectionWithTcpEndpoints(RabbitMqClientOptions options, ConnectionFactory factory)
61+
{
62+
var clientEndpoints = new List<AmqpTcpEndpoint>();
63+
foreach (var endpoint in options.TcpEndpoints)
64+
{
65+
var sslOption = endpoint.SslOption;
66+
if (sslOption != null)
67+
{
68+
var convertedOption = new SslOption(sslOption.ServerName, sslOption.CertificatePath, sslOption.Enabled);
69+
if (!string.IsNullOrEmpty(sslOption.CertificatePassphrase))
70+
{
71+
convertedOption.CertPassphrase = sslOption.CertificatePassphrase;
72+
}
73+
74+
if (sslOption.AcceptablePolicyErrors != null)
75+
{
76+
convertedOption.AcceptablePolicyErrors = sslOption.AcceptablePolicyErrors.Value;
77+
}
78+
79+
clientEndpoints.Add(new AmqpTcpEndpoint(endpoint.HostName, endpoint.Port, convertedOption));
80+
}
81+
else
82+
{
83+
clientEndpoints.Add(new AmqpTcpEndpoint(endpoint.HostName, endpoint.Port));
84+
}
85+
}
86+
return TryToCreateConnection(() => factory.CreateConnection(clientEndpoints), options.InitialConnectionRetries, options.InitialConnectionRetryTimeoutMilliseconds);
87+
}
88+
6089
static IConnection CreateNamedConnection(RabbitMqClientOptions options, ConnectionFactory factory)
6190
{
6291
if (options.HostNames?.Any() == true)

0 commit comments

Comments
 (0)