Skip to content

Commit a6b990d

Browse files
committed
* Add ITlsSettings interface
* Add `TlsSettings` class * Pass TLS settings to Amqp ConnectionFactory * Ensure test passes
1 parent b7db37c commit a6b990d

File tree

4 files changed

+122
-8
lines changed

4 files changed

+122
-8
lines changed

RabbitMQ.AMQP.Client/IConnectionSettings.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
using System.Net.Security;
2+
using System.Security.Authentication;
3+
using System.Security.Cryptography.X509Certificates;
4+
15
namespace RabbitMQ.AMQP.Client;
26

37
public interface IConnectionSettings : IEquatable<IConnectionSettings>
@@ -11,4 +15,36 @@ public interface IConnectionSettings : IEquatable<IConnectionSettings>
1115
string ConnectionName { get; }
1216
string Path { get; }
1317
bool UseSsl { get; }
18+
ITlsSettings? TlsSettings { get; }
19+
}
20+
21+
/// <summary>
22+
/// Contains the TLS/SSL settings for a connection.
23+
/// </summary>
24+
public interface ITlsSettings
25+
{
26+
/// <summary>
27+
/// Client certificates to use for mutual authentication.
28+
/// </summary>
29+
X509CertificateCollection ClientCertificates { get; }
30+
31+
/// <summary>
32+
/// Supported protocols to use.
33+
/// </summary>
34+
SslProtocols Protocols { get; }
35+
36+
/// <summary>
37+
/// Specifies whether certificate revocation should be performed during handshake.
38+
/// </summary>
39+
bool CheckCertificateRevocation { get; }
40+
41+
/// <summary>
42+
/// Gets or sets a certificate validation callback to validate remote certificate.
43+
/// </summary>
44+
RemoteCertificateValidationCallback? RemoteCertificateValidationCallback { get; }
45+
46+
/// <summary>
47+
/// Gets or sets a local certificate selection callback to select the certificate which should be used for authentication.
48+
/// </summary>
49+
LocalCertificateSelectionCallback? LocalCertificateSelectionCallback { get; }
1450
}

RabbitMQ.AMQP.Client/ILifeCycle.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ public enum State
99
Closed,
1010
}
1111

12-
1312
public class Error(string? errorCode, string? description)
1413
{
1514
public string? Description { get; } = description;
@@ -21,15 +20,13 @@ public override string ToString()
2120
}
2221
}
2322

24-
25-
2623
public delegate void LifeCycleCallBack(object sender, State previousState, State currentState, Error? failureCause);
2724

2825
public interface ILifeCycle
2926
{
3027
Task CloseAsync();
31-
28+
3229
public State State { get; }
33-
30+
3431
event LifeCycleCallBack ChangeState;
3532
}

RabbitMQ.AMQP.Client/Impl/AmqpConnection.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,27 @@ void onOpened(Amqp.IConnection connection, Open open1)
162162

163163
var cf = new ConnectionFactory();
164164

165+
if (_connectionSettings.UseSsl && _connectionSettings.TlsSettings is not null)
166+
{
167+
cf.SSL.Protocols = _connectionSettings.TlsSettings.Protocols;
168+
cf.SSL.CheckCertificateRevocation = _connectionSettings.TlsSettings.CheckCertificateRevocation;
169+
170+
if (_connectionSettings.TlsSettings.ClientCertificates.Count > 0)
171+
{
172+
cf.SSL.ClientCertificates = _connectionSettings.TlsSettings.ClientCertificates;
173+
}
174+
175+
if (_connectionSettings.TlsSettings.LocalCertificateSelectionCallback is not null)
176+
{
177+
cf.SSL.LocalCertificateSelectionCallback = _connectionSettings.TlsSettings.LocalCertificateSelectionCallback;
178+
}
179+
180+
if (_connectionSettings.TlsSettings.RemoteCertificateValidationCallback is not null)
181+
{
182+
cf.SSL.RemoteCertificateValidationCallback = _connectionSettings.TlsSettings.RemoteCertificateValidationCallback;
183+
}
184+
}
185+
165186
try
166187
{
167188
_nativeConnection = await cf.CreateAsync(_connectionSettings.Address, open: open, onOpened: onOpened)

RabbitMQ.AMQP.Client/Impl/ConnectionSettings.cs

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
using Amqp;
1+
using System.Net.Security;
2+
using System.Security.Authentication;
3+
using System.Security.Cryptography.X509Certificates;
4+
using Amqp;
25

36
namespace RabbitMQ.AMQP.Client.Impl;
47

@@ -95,21 +98,35 @@ public class ConnectionSettings : IConnectionSettings
9598
private readonly Address _address;
9699
private readonly string _connectionName = "";
97100
private readonly string _virtualHost = "/";
101+
private readonly ITlsSettings? _tlsSettings;
98102

99-
public ConnectionSettings(string address)
103+
public ConnectionSettings(string address, ITlsSettings? tlsSettings = null)
100104
{
101105
_address = new Address(address);
106+
_tlsSettings = tlsSettings;
107+
108+
if (_address.UseSsl && _tlsSettings == null)
109+
{
110+
_tlsSettings = new TlsSettings();
111+
}
102112
}
103113

104114
public ConnectionSettings(string host, int port,
105115
string user, string password,
106-
string virtualHost, string scheme, string connectionName)
116+
string virtualHost, string scheme, string connectionName,
117+
ITlsSettings? tlsSettings = null)
107118
{
108119
_address = new Address(host: host, port: port,
109120
user: user, password: password,
110121
path: "/", scheme: scheme);
111122
_connectionName = connectionName;
112123
_virtualHost = virtualHost;
124+
_tlsSettings = tlsSettings;
125+
126+
if (_address.UseSsl && _tlsSettings == null)
127+
{
128+
_tlsSettings = new TlsSettings();
129+
}
113130
}
114131

115132
public string Host => _address.Host;
@@ -122,6 +139,8 @@ public ConnectionSettings(string host, int port,
122139
public string Path => _address.Path;
123140
public bool UseSsl => _address.UseSsl;
124141

142+
public ITlsSettings? TlsSettings => _tlsSettings;
143+
125144
public override string ToString()
126145
{
127146
return
@@ -307,3 +326,44 @@ public override string ToString()
307326
return $"BackOffDelayPolicy{{ Attempt={_attempt}, TotalAttempt={_totalAttempt}, IsActive={IsActive} }}";
308327
}
309328
}
329+
330+
public class TlsSettings : ITlsSettings
331+
{
332+
internal const SslProtocols DefaultSslProtocols = SslProtocols.None;
333+
334+
private readonly SslProtocols _protocols;
335+
private readonly X509CertificateCollection _clientCertificates;
336+
private readonly bool _checkCertificateRevocation = false;
337+
private readonly RemoteCertificateValidationCallback? _remoteCertificateValidationCallback;
338+
private readonly LocalCertificateSelectionCallback? _localCertificateSelectionCallback;
339+
340+
public TlsSettings() : this(DefaultSslProtocols)
341+
{
342+
}
343+
344+
public TlsSettings(SslProtocols protocols)
345+
{
346+
_protocols = protocols;
347+
_clientCertificates = new X509CertificateCollection();
348+
_remoteCertificateValidationCallback = trustEverythingCertValidationCallback;
349+
_localCertificateSelectionCallback = null;
350+
}
351+
352+
public SslProtocols Protocols => _protocols;
353+
354+
public X509CertificateCollection ClientCertificates => _clientCertificates;
355+
356+
public bool CheckCertificateRevocation => _checkCertificateRevocation;
357+
358+
public RemoteCertificateValidationCallback? RemoteCertificateValidationCallback
359+
=> _remoteCertificateValidationCallback;
360+
361+
public LocalCertificateSelectionCallback? LocalCertificateSelectionCallback
362+
=> _localCertificateSelectionCallback;
363+
364+
private static bool trustEverythingCertValidationCallback(object sender, X509Certificate? certificate,
365+
X509Chain? chain, SslPolicyErrors sslPolicyErrors)
366+
{
367+
return true;
368+
}
369+
}

0 commit comments

Comments
 (0)