Skip to content

Commit d540dc1

Browse files
Merge pull request #88 from xcomponent/rabbitmq-ssl-support
Adding SSL support for RabbitMq
2 parents 7ab9c10 + cadc84f commit d540dc1

File tree

8 files changed

+209
-15
lines changed

8 files changed

+209
-15
lines changed
Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11

2+
using System.Security.Authentication;
3+
24
namespace ReactiveXComponent.Configuration
35
{
46
public class BusDetails
@@ -8,34 +10,101 @@ public BusDetails()
810

911
}
1012

11-
public BusDetails(string username, string password, string host, string virtualHost, int port)
13+
public BusDetails(
14+
string username,
15+
string password,
16+
string host,
17+
string virtualHost,
18+
int port,
19+
bool sslEnabled = false,
20+
string sslServerName = "",
21+
string sslCertificatePath = "",
22+
string sslCertificatePassphrase = "",
23+
SslProtocols sslProtocol = SslProtocols.Default,
24+
bool sslAllowUntrustedServerCertificate = false)
1225
{
1326
Username = username;
1427
Password = password;
1528
Host = host;
1629
VirtualHost = virtualHost;
1730
Port = port;
18-
31+
SslEnabled = sslEnabled;
32+
SslServerName = sslServerName;
33+
SslCertificatePath = sslCertificatePath;
34+
SslCertificatePassphrase = sslCertificatePassphrase;
35+
SslProtocol = sslProtocol;
36+
SslAllowUntrustedServerCertificate = sslAllowUntrustedServerCertificate;
1937
}
2038

39+
/// <summary>
40+
/// Rabbit Mq user.
41+
/// </summary>
2142
public string Username { get; set; }
2243

44+
/// <summary>
45+
/// Rabbit Mq password for user.
46+
/// </summary>
2347
public string Password { get; set; }
2448

49+
/// <summary>
50+
/// Rabbit Mq server's address.
51+
/// </summary>
2552
public string Host { get; set; }
2653

54+
/// <summary>
55+
/// Rabbit Mq virtual host to connect to.
56+
/// </summary>
2757
public string VirtualHost { get; set; }
2858

59+
/// <summary>
60+
/// Rabbit Mq server's port.
61+
/// </summary>
2962
public int Port { get; set; }
3063

64+
/// <summary>
65+
/// To enable SSL.
66+
/// </summary>
67+
public bool SslEnabled { get; set; }
68+
69+
/// <summary>
70+
/// Server's Common Name. It's indicated in the CN field of the server's certificate.
71+
/// </summary>
72+
public string SslServerName { get; set; }
73+
74+
/// <summary>
75+
/// Path to the client's certificate.
76+
/// </summary>
77+
public string SslCertificatePath { get; set; }
78+
79+
/// <summary>
80+
/// Passphrase for the client's certificate if it has one.
81+
/// </summary>
82+
public string SslCertificatePassphrase { get; set; }
83+
84+
/// <summary>
85+
/// SSL protocol to use.
86+
/// </summary>
87+
public SslProtocols SslProtocol { get; set; }
88+
89+
/// <summary>
90+
/// To accept untrusted (e.g self-signed) server certificates. Only use this in Dev environment.
91+
/// </summary>
92+
public bool SslAllowUntrustedServerCertificate { get; set; }
93+
3194
public BusDetails Clone()
3295
{
3396
return new BusDetails(
3497
Username,
3598
Password,
3699
Host,
37100
VirtualHost,
38-
Port);
101+
Port,
102+
SslEnabled,
103+
SslServerName,
104+
SslCertificatePath,
105+
SslCertificatePassphrase,
106+
SslProtocol,
107+
SslAllowUntrustedServerCertificate);
39108
}
40109
}
41110
}

ReactiveXComponent/Configuration/ConfigurationOverrides.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using ReactiveXComponent.Common;
1+
using System.Security.Authentication;
2+
using ReactiveXComponent.Common;
23

34
namespace ReactiveXComponent.Configuration
45
{
@@ -15,5 +16,17 @@ public class ConfigurationOverrides
1516
public string Password { get; set; }
1617

1718
public WebSocketType? WebSocketType { get; set; }
19+
20+
public bool? SslEnabled { get; set; }
21+
22+
public string SslServerName { get; set; }
23+
24+
public string SslCertificatePath { get; set; }
25+
26+
public string SslCertificatePassphrase { get; set; }
27+
28+
public SslProtocols? SslProtocol { get; set; }
29+
30+
public bool? SslAllowUntrustedServerCertificate { get; set; }
1831
}
1932
}

ReactiveXComponent/Configuration/XCApiTags.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,13 @@ public static class XCApiTags
2929
public const string Json = "Json";
3030
public const string Bson = "Bson";
3131
public const string GzipJson = "GzipJson";
32+
public const string WebsocketType = "type";
33+
public const string VirtualHost = "virtualHost";
34+
public const string BusSslEnabled = "sslEnabled";
35+
public const string BusSslServerName = "sslServerName";
36+
public const string BusSslCertificatePath = "sslCertPath";
37+
public const string BusSslCertificatePassphrase = "sslCertPassphrase";
38+
public const string BusSslProtocol = "sslProtocol";
39+
public const string BusSslAllowUntrustedServerCertificate = "sslAllowUntrustedServerCertificate";
3240
}
3341
}

ReactiveXComponent/Parser/XCApiConfigParser.cs

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.IO;
44
using System.Linq;
5+
using System.Security.Authentication;
56
using System.Xml;
67
using System.Xml.Linq;
78
using ReactiveXComponent.Common;
@@ -182,12 +183,44 @@ public string GetSerializationType()
182183
public BusDetails GetBusDetails()
183184
{
184185
XElement busInfos = _xcApiDescription.GetBusNode()?.FirstOrDefault();
186+
187+
var sslEnabledString = busInfos?.Attribute(XCApiTags.BusSslEnabled)?.Value;
188+
var sslEnabled = false;
189+
if (!string.IsNullOrEmpty(sslEnabledString))
190+
{
191+
bool.TryParse(sslEnabledString, out sslEnabled);
192+
}
193+
194+
var sslServerName = busInfos?.Attribute(XCApiTags.BusSslServerName)?.Value;
195+
var sslCertificatePath = busInfos?.Attribute(XCApiTags.BusSslCertificatePath)?.Value;
196+
var sslCertificatePassphrase = busInfos?.Attribute(XCApiTags.BusSslCertificatePassphrase)?.Value;
197+
198+
var sslProtocolString = busInfos?.Attribute(XCApiTags.BusSslProtocol)?.Value;
199+
SslProtocols sslProtocol = SslProtocols.Default;
200+
if (!string.IsNullOrEmpty(sslProtocolString))
201+
{
202+
Enum.TryParse(sslProtocolString, out sslProtocol);
203+
}
204+
205+
var sslAllowUntrustedServerCertificateString = busInfos?.Attribute(XCApiTags.BusSslAllowUntrustedServerCertificate)?.Value;
206+
var sslAllowUntrustedServerCertificate = false;
207+
if (!string.IsNullOrEmpty(sslAllowUntrustedServerCertificateString))
208+
{
209+
bool.TryParse(sslAllowUntrustedServerCertificateString, out sslAllowUntrustedServerCertificate);
210+
}
211+
185212
var busDetails = new BusDetails(
186-
busInfos?.Attribute("user")?.Value,
187-
busInfos?.Attribute("password")?.Value,
188-
busInfos?.Attribute("host")?.Value,
189-
busInfos?.Attribute("virtualHost")?.Value,
190-
Convert.ToInt32(busInfos?.Attribute("port")?.Value));
213+
busInfos?.Attribute(XCApiTags.User)?.Value,
214+
busInfos?.Attribute(XCApiTags.Password)?.Value,
215+
busInfos?.Attribute(XCApiTags.Host)?.Value,
216+
busInfos?.Attribute(XCApiTags.VirtualHost)?.Value,
217+
Convert.ToInt32(busInfos?.Attribute(XCApiTags.Port)?.Value),
218+
sslEnabled,
219+
sslServerName,
220+
sslCertificatePath,
221+
sslCertificatePassphrase,
222+
sslProtocol,
223+
sslAllowUntrustedServerCertificate);
191224

192225
return busDetails;
193226
}
@@ -197,16 +230,16 @@ public WebSocketEndpoint GetWebSocketEndpoint()
197230
XElement websocketInfos = _xcApiDescription.GetWebSocketNode()?.FirstOrDefault();
198231

199232
WebSocketType webSocketType;
200-
var webSocketTypeString = websocketInfos?.Attribute("type")?.Value;
233+
var webSocketTypeString = websocketInfos?.Attribute(XCApiTags.WebsocketType)?.Value;
201234
if (!Enum.TryParse(webSocketTypeString, out webSocketType))
202235
{
203236
throw new ReactiveXComponentException($"Could not parse communication type: {webSocketTypeString}");
204237
}
205238

206239
var webSocketEndpoint = new WebSocketEndpoint(
207-
websocketInfos?.Attribute("name")?.Value,
208-
websocketInfos?.Attribute("host")?.Value,
209-
websocketInfos?.Attribute("port")?.Value,
240+
websocketInfos?.Attribute(XCApiTags.Name)?.Value,
241+
websocketInfos?.Attribute(XCApiTags.Host)?.Value,
242+
websocketInfos?.Attribute(XCApiTags.Port)?.Value,
210243
webSocketType);
211244

212245
return webSocketEndpoint;

ReactiveXComponent/RabbitMq/RabbitMqConnection.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,36 @@ public IXCSession CreateSession(ConfigurationOverrides configurationOverrides =
5050
busDetails.Password = configurationOverrides.Password;
5151
}
5252

53+
if (configurationOverrides.SslEnabled != null)
54+
{
55+
busDetails.SslEnabled = configurationOverrides.SslEnabled.Value;
56+
}
57+
58+
if (configurationOverrides.SslServerName != null)
59+
{
60+
busDetails.SslServerName = configurationOverrides.SslServerName;
61+
}
62+
63+
if (configurationOverrides.SslCertificatePath != null)
64+
{
65+
busDetails.SslCertificatePath = configurationOverrides.SslCertificatePath;
66+
}
67+
68+
if (configurationOverrides.SslCertificatePassphrase != null)
69+
{
70+
busDetails.SslCertificatePassphrase = configurationOverrides.SslCertificatePassphrase;
71+
}
72+
73+
if (configurationOverrides.SslProtocol != null)
74+
{
75+
busDetails.SslProtocol = configurationOverrides.SslProtocol.Value;
76+
}
77+
78+
if (configurationOverrides.SslAllowUntrustedServerCertificate != null)
79+
{
80+
busDetails.SslAllowUntrustedServerCertificate = configurationOverrides.SslAllowUntrustedServerCertificate.Value;
81+
}
82+
5383
return new RabbitMqSession(_xcConfiguration, busDetails, _privateCommunicationIdentifier);
5484
}
5585
}

ReactiveXComponent/RabbitMq/RabbitMqSession.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Net.Security;
34
using RabbitMQ.Client;
45
using RabbitMQ.Client.Exceptions;
56
using ReactiveXComponent.Common;
@@ -39,6 +40,39 @@ private void InitConnection(BusDetails busDetails)
3940
Protocol = Protocols.DefaultProtocol
4041
};
4142

43+
if (busDetails.SslEnabled)
44+
{
45+
_factory.Ssl.Enabled = true;
46+
47+
_factory.Ssl.ServerName = busDetails.SslServerName;
48+
49+
if (!string.IsNullOrEmpty(busDetails.SslCertificatePath))
50+
{
51+
_factory.Ssl.CertPath = busDetails.SslCertificatePath;
52+
}
53+
54+
if (!string.IsNullOrEmpty(busDetails.SslCertificatePassphrase))
55+
{
56+
_factory.Ssl.CertPassphrase = busDetails.SslCertificatePassphrase;
57+
}
58+
59+
_factory.Ssl.Version = busDetails.SslProtocol;
60+
61+
if (busDetails.SslAllowUntrustedServerCertificate)
62+
{
63+
_factory.Ssl.CertificateValidationCallback += (sender, certificate, chain, errors) =>
64+
{
65+
if ((errors & SslPolicyErrors.RemoteCertificateNameMismatch) == SslPolicyErrors.RemoteCertificateNameMismatch ||
66+
(errors & SslPolicyErrors.RemoteCertificateNotAvailable) == SslPolicyErrors.RemoteCertificateNotAvailable)
67+
{
68+
return false;
69+
}
70+
71+
return true;
72+
};
73+
}
74+
}
75+
4276
_connection = _factory?.CreateConnection();
4377

4478
_connection.ConnectionShutdown += ConnectionOnConnectionShutdown;

ReactiveXComponentTest/Configuration/ConfigurationTests.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.IO;
3+
using System.Security.Authentication;
34
using NFluent;
45
using NUnit.Framework;
56
using ReactiveXComponent.Common;
@@ -77,7 +78,13 @@ public void GetBusDetailsTest()
7778
Check.That(busDetails.VirtualHost).IsEqualTo("myVirtualHost");
7879
Check.That(busDetails.Username).IsEqualTo("guest");
7980
Check.That(busDetails.Password).IsEqualTo("guest");
80-
Check.That(busDetails.Port).IsEqualTo(5672);
81+
Check.That(busDetails.Port).IsEqualTo(5671);
82+
Check.That(busDetails.SslEnabled).IsTrue();
83+
Check.That(busDetails.SslServerName).IsEqualTo("XComponent RMq");
84+
Check.That(busDetails.SslCertificatePath).IsEqualTo("some_cert_path");
85+
Check.That(busDetails.SslCertificatePassphrase).IsEqualTo("some_cert_pass");
86+
Check.That(busDetails.SslProtocol).IsEqualTo(SslProtocols.Default);
87+
Check.That(busDetails.SslAllowUntrustedServerCertificate).IsTrue();
8188
}
8289

8390
[Test]

ReactiveXComponentTest/RabbitMqTestApi.xcApi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<threading />
44
<serialization>Binary</serialization>
55
<communication>
6-
<bus name="rabbitmq" host="127.0.0.1" virtualHost="myVirtualHost" port="5672" user="guest" password="guest" type="RABBIT_MQ" />
6+
<bus name="rabbitmq" host="127.0.0.1" virtualHost="myVirtualHost" port="5671" user="guest" password="guest" type="RABBIT_MQ" sslEnabled="True" sslServerName="XComponent RMq" sslCertPath="some_cert_path" sslCertPassphrase="some_cert_pass" sslProtocol="Default" sslAllowUntrustedServerCertificate="True" />
77
</communication>
88
<clientAPICommunication>
99
<publish componentCode="-69981087" stateMachineCode="-829536631" eventType="UPDATE" topicType="output" communicationType="BUS" stateCode="0" eventCode="9" event="XComponent.HelloWorld.UserObject.SayHello" communication="rabbitmq">

0 commit comments

Comments
 (0)