Skip to content

Commit

Permalink
Allow to configure ssl in vanilla connection string (#1672)
Browse files Browse the repository at this point in the history
* Allow to enable ssl in vanilla connection string

* Remove irrelevant comments

* Support other ssl options

* Ssl server name should be taken from the hostname

* Stop setting a default version

* Defensively copy Ssl, set hostname to servername

* Remain only ssl flag

* Remove useless comments

* Do not copy endpoint ssl

* Simplify code
  • Loading branch information
Pliner committed May 14, 2023
1 parent 9699613 commit 3f6ba69
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ public ConnectionStringParserTests()

private readonly ConnectionStringParser connectionStringParser;

private const string connectionString =
private const string ConnectionString =
"virtualHost=Copa;username=Copa;host=192.168.1.1;password=abc_xyz;port=12345;" +
"requestedHeartbeat=3;prefetchcount=2;timeout=12;publisherConfirms=true;" +
"name=unit-test;mandatoryPublish=true;consumerDispatcherConcurrency=1";
"name=unit-test;mandatoryPublish=true;consumerDispatcherConcurrency=1;ssl=true";

[Fact]
public void Should_correctly_parse_connection_string()
{
var configuration = connectionStringParser.Parse(connectionString);
var configuration = connectionStringParser.Parse(ConnectionString);

configuration.Hosts.First().Host.Should().Be("192.168.1.1");
configuration.VirtualHost.Should().Be("Copa");
Expand All @@ -39,15 +39,7 @@ public void Should_correctly_parse_connection_string()
configuration.Name.Should().Be("unit-test");
configuration.MandatoryPublish.Should().BeTrue();
configuration.ConsumerDispatcherConcurrency.Should().Be(1);
}

[Fact]
public void Should_parse_global_timeout()
{
const string connectionStringWithTimeout = "host=localhost;timeout=13";
var connectionConfiguration = connectionStringParser.Parse(connectionStringWithTimeout);

connectionConfiguration.Timeout.Should().Be(TimeSpan.FromSeconds(13));
configuration.Ssl.Enabled.Should().BeTrue();
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ public ConnectionConfiguration Parse(string connectionString)
if (secured)
{
host.Ssl.Enabled = true;
host.Ssl.Version = SslProtocols.None;
host.Ssl.ServerName = host.Host;
}

Expand Down
35 changes: 13 additions & 22 deletions Source/EasyNetQ/ConnectionString/ConnectionStringGrammar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ internal static class ConnectionStringGrammar
BuildKeyValueParser("product", Text, c => c.Product),
BuildKeyValueParser("platform", Text, c => c.Platform),
BuildKeyValueParser("name", Text, c => c.Name),
BuildKeyValueParser("mandatoryPublish", Bool, c => c.MandatoryPublish)
BuildKeyValueParser("mandatoryPublish", Bool, c => c.MandatoryPublish),
BuildKeyValueParser("ssl", Bool, c => c.Ssl.Enabled)
}.Aggregate((a, b) => a.Or(b));

internal static readonly Parser<IEnumerable<UpdateConfiguration>> ConnectionStringBuilder = Part.ListDelimitedBy(';');
Expand Down Expand Up @@ -80,29 +81,19 @@ public static IEnumerable<UpdateConfiguration> ParseConnectionString(string conn
Expression<Func<ConnectionConfiguration, T>> getter
) => CreateSetter<ConnectionConfiguration, T>(getter);

/// <summary>
/// Stolen from SO:
/// http://stackoverflow.com/questions/4596453/create-an-actiont-to-set-a-property-when-i-am-provided-with-the-linq-expres
/// </summary>
/// <typeparam name="TContaining"></typeparam>
/// <typeparam name="TProperty"></typeparam>
/// <param name="getter"></param>
/// <returns></returns>
private static Action<TContaining, TProperty> CreateSetter<TContaining, TProperty>(Expression<Func<TContaining, TProperty>> getter)
{
Preconditions.CheckNotNull(getter, nameof(getter));

var memberEx = getter.Body as MemberExpression;

Preconditions.CheckNotNull(memberEx, nameof(getter), "Body is not a member-expression.");

var property = memberEx.Member as PropertyInfo;

Preconditions.CheckNotNull(property, nameof(getter), "Member is not a property.");

if (!property.CanWrite) throw new ArgumentOutOfRangeException(nameof(getter), null, "Member is not a writeable property.");

return (Action<TContaining, TProperty>)property.GetSetMethod().CreateDelegate(typeof(Action<TContaining, TProperty>));
if (getter.Body is not MemberExpression memberExpr)
throw new ArgumentOutOfRangeException(nameof(getter), "Body is not a member-expression");
if (memberExpr.Member is not PropertyInfo propertyInfo)
throw new ArgumentOutOfRangeException(nameof(getter), "Member is not a property");
if (!propertyInfo.CanWrite)
throw new ArgumentOutOfRangeException(nameof(getter), "Property is not writeable");

var valueParameterExpr = Expression.Parameter(typeof(TProperty), "value");
var setter = propertyInfo.GetSetMethod() ?? throw new ArgumentOutOfRangeException(nameof(getter), "No set method");
var expr = Expression.Call(memberExpr.Expression, setter, valueParameterExpr);
return Expression.Lambda<Action<TContaining, TProperty>>(expr, getter.Parameters.Single(), valueParameterExpr).Compile();
}

private static IEnumerable<T> Cons<T>(this T head, IEnumerable<T> rest)
Expand Down
26 changes: 20 additions & 6 deletions Source/EasyNetQ/Persistent/PersistentConnection.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Threading;
using System.Security.Cryptography.X509Certificates;
using EasyNetQ.Events;
using EasyNetQ.Logging;
using RabbitMQ.Client;
Expand Down Expand Up @@ -109,12 +110,10 @@ private IAutorecoveringConnection CreateConnection()
{
var endpoints = configuration.Hosts.Select(x =>
{
var endpoint = new AmqpTcpEndpoint(x.Host, x.Port);
if (x.Ssl.Enabled)
endpoint.Ssl = x.Ssl;
else if (configuration.Ssl.Enabled)
endpoint.Ssl = configuration.Ssl;
return endpoint;
var ssl = !x.Ssl.Enabled && configuration.Ssl.Enabled
? NewSslForHost(configuration.Ssl, x.Host)
: x.Ssl;
return new AmqpTcpEndpoint(x.Host, x.Port, ssl);
}).ToList();

if (connectionFactory.CreateConnection(endpoints) is not IAutorecoveringConnection connection)
Expand Down Expand Up @@ -178,4 +177,19 @@ private void OnConnectionUnblocked(object sender, EventArgs e)
logger.InfoFormat("Connection {type} unblocked", type);
eventBus.Publish(new ConnectionUnblockedEvent(type));
}

private static SslOption NewSslForHost(SslOption option, string host) =>
new()
{
Certs = option.Certs,
AcceptablePolicyErrors = option.AcceptablePolicyErrors,
CertPassphrase = option.CertPassphrase,
CertPath = option.CertPath,
CertificateSelectionCallback = option.CertificateSelectionCallback,
CertificateValidationCallback = option.CertificateValidationCallback,
CheckCertificateRevocation = option.CheckCertificateRevocation,
Enabled = option.Enabled,
ServerName = host,
Version = option.Version,
};
}

0 comments on commit 3f6ba69

Please sign in to comment.