Skip to content

Commit

Permalink
NCBC-1122: Add config flag to ignore TLS FQDN validation
Browse files Browse the repository at this point in the history
Motivation
----------
If you bootstrap with an IP (and not an FQDN) and are using TLS, the
client will fail with a RemoteCertificateNameMismatch because the
certificates name doesn't match the IP. As a work-around for test
environments, we can add a flag that ignores this error and allows the
client to not fail when establishing the TLS connection.

Modifications
-------------
Added static IgnoreRemoteCertificateNameMismatch config property to
ClientCOnfiguration and instance properties to CouchbaseClientDefinition and
CouchbaseClientSection. Added additional logic to ignore
RemoteCertificateNameMismatch during authentication of connections.

Results
-------
If you are using IP's and TLS/SSL, you can enable
IgnoreRemoteCertificateNameMismatch so that these validation errors are
ignored.

Change-Id: I5c0afc25c9a41814fbabc555101513a67dc254fb
Reviewed-on: http://review.couchbase.org/64503
Tested-by: Jeffry Morris <jeffrymorris@gmail.com>
Reviewed-by: Simon Baslé <simon@couchbase.com>
  • Loading branch information
jeffrymorris committed May 27, 2016
1 parent 9ece8b9 commit 94f56b2
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 2 deletions.
@@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Couchbase.Configuration.Client;
using Couchbase.Configuration.Client.Providers;
using NUnit.Framework;

namespace Couchbase.IntegrationTests.Configuration.Client
{
[TestFixture]
// ReSharper disable once InconsistentNaming
public class JsonConfiguration_Tests
{
[Test]
public void ClientConfiguration_IgnoreHostnameValidation_IsTrue()
{
//arrange/act
var clientConfig = Utils.TestConfiguration.GetJsonConfiguration("basic");

//assert
Assert.IsTrue(ClientConfiguration.IgnoreRemoteCertificateNameMismatch);
}

[Test]
public void ClientConfiguration_IgnoreHostnameValidation_IsFalse()
{
//arrange/act
var clientConfig = Utils.TestConfiguration.GetJsonConfiguration("multiplexio");

//assert
Assert.IsFalse(ClientConfiguration.IgnoreRemoteCertificateNameMismatch);
}
}
}

#region [ License information ]

/* ************************************************************
*
* @author Couchbase <info@couchbase.com>
* @copyright 2015 Couchbase, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ************************************************************/

#endregion
Expand Up @@ -98,6 +98,7 @@
<ItemGroup>
<Compile Include="Configuration\Client\JsonConfiguration_Multiplex_Tests.cs" />
<Compile Include="Configuration\Client\JsonConfiguration_KeyValue_Tests.cs" />
<Compile Include="Configuration\Client\JsonConfiguration_Tests.cs" />
<Compile Include="CouchbaseBucket_KeyValue_Tests.cs" />
<Compile Include="CouchbaseBucket_Search_Tests.cs" />
<Compile Include="CouchbaseBucket_SubDocument_Tests.cs" />
Expand Down
1 change: 1 addition & 0 deletions Src/Couchbase.IntegrationTests/config.json
@@ -1,6 +1,7 @@
{
"basic": {
"enableConfigHeartbeat": false,
"ignoreRemoteCertificateNameMismatch": true,
"servers": [
"http://127.0.0.1:8091/"
],
Expand Down
2 changes: 1 addition & 1 deletion Src/Couchbase.UnitTests/App.config
Expand Up @@ -10,7 +10,7 @@
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<couchbaseClients>
<couchbase enableConfigHeartBeat="false">
<couchbase enableConfigHeartBeat="false" ignoreRemoteCertificateNameMismatch="true">
<connectionPool name="custom" minSize="5" maxSize="10"></connectionPool>
<servers>
<add uri="http://localhost:8091"></add>
Expand Down
Expand Up @@ -172,5 +172,14 @@ public void BucketConfiguration_NoPoolConfigurationDefined_UsesDerivedPoolSettin
Assert.AreEqual(5, clientConfig.BucketConfigs["beer-sample"].PoolConfiguration.MinSize);
Assert.AreEqual(10, clientConfig.BucketConfigs["beer-sample"].PoolConfiguration.MaxSize);
}

[Test]
public void ClientConfiguration_IgnoreHostnameValidation()
{
//arrange/act
var clientConfig = new ClientConfiguration((CouchbaseClientSection)ConfigurationManager.GetSection("couchbaseClients/couchbase"));

Assert.IsTrue(ClientConfiguration.IgnoreRemoteCertificateNameMismatch);
}
}
}
15 changes: 15 additions & 0 deletions Src/Couchbase/Configuration/Client/ClientConfiguration.cs
Expand Up @@ -241,6 +241,9 @@ public ClientConfiguration(ICouchbaseClientDefinition definition)
//The default sasl mechanism creator
CreateSaslMechanism = SaslFactory.GetFactory();

//NOTE: this is a global setting and applies to all instances
IgnoreRemoteCertificateNameMismatch = definition.IgnoreRemoteCertificateNameMismatch;

foreach (var server in definition.Servers ?? new[] { Defaults.Server })
{
Servers.Add(server);
Expand Down Expand Up @@ -404,6 +407,18 @@ public ClientConfiguration(ICouchbaseClientDefinition definition)
/// <remarks>The default is 1 second.</remarks>
public uint TcpKeepAliveInterval { get; set; }

/// <summary>
/// If TLS/SSL is enabled via <see cref="UseSsl"/> setting this to <c>true</c> will disable hostname validation when authenticating
/// connections to Couchbase Server. This is typically done in test or development enviroments where a domain name (FQDN) has not been
/// specified for the bootstrap uri's <see cref="Servers"/> and the IP address is used to validate the certificate, which will fail with
/// a RemoteCertificateNameMismatch error.
/// </summary>
/// <value>
/// <c>true</c> to ignore hostname validation of the certificate if you are using IP's and not a FQDN to bootstrap; otherwise, <c>false</c>.
/// </value>
/// <remarks>Note: this is a global setting - it applies to all <see cref="ICluster"/> and <see cref="IBucket"/> references within a process.</remarks>
public static bool IgnoreRemoteCertificateNameMismatch { get; set; }

/// <summary>
/// Gets or sets the count of IO errors within a specific interval defined by the value of <see cref="IOErrorCheckInterval" />.
/// If the threshold is reached within the interval for a particular node, all keys mapped to that node the SDK will fail
Expand Down
13 changes: 13 additions & 0 deletions Src/Couchbase/Configuration/Client/CouchbaseClientDefinition.cs
Expand Up @@ -300,6 +300,19 @@ public class CouchbaseClientDefinition : ICouchbaseClientDefinition
/// </value>
public int QueryFailedThreshold { get; set; }

/// <summary>
/// If TLS/SSL is enabled via <see cref="UseSsl"/> setting this to <c>true</c> will disable hostname validation when authenticating
/// connections to Couchbase Server. This is typically done in test or development enviroments where a domain name (FQDN) has not been
/// specified for the bootstrap uri's <see cref="Servers"/> and the IP address is used to validate the certificate, which will fail with
/// a RemoteCertificateNameMismatch error.
/// </summary>
/// <value>
/// <c>true</c> to ignore hostname validation of the certificate if you are using IP's and not a FQDN to bootstrap; otherwise, <c>false</c>.
/// </value>
/// <remarks>Note: this is a global setting - it applies to all <see cref="ICluster"/> and <see cref="IBucket"/> references within a process.</remarks>
[JsonProperty("ignoreRemoteCertificateNameMismatch")]
public bool IgnoreRemoteCertificateNameMismatch { get; set; }

public CouchbaseClientDefinition()
{
UseSsl = ClientConfiguration.Defaults.UseSsl;
Expand Down
12 changes: 12 additions & 0 deletions Src/Couchbase/Configuration/Client/ICouchbaseClientDefinition.cs
Expand Up @@ -295,5 +295,17 @@ public interface ICouchbaseClientDefinition
/// The query failed threshold.
/// </value>
int QueryFailedThreshold { get; }

/// <summary>
/// If TLS/SSL is enabled via <see cref="UseSsl"/> setting this to <c>true</c> will disable hostname validation when authenticating
/// connections to Couchbase Server. This is typically done in test or development enviroments where a domain name (FQDN) has not been
/// specified for the bootstrap uri's <see cref="Servers"/> and the IP address is used to validate the certificate, which will fail with
/// a RemoteCertificateNameMismatch error.
/// </summary>
/// <value>
/// <c>true</c> to ignore hostname validation of the certificate if you are using IP's and not a FQDN to bootstrap; otherwise, <c>false</c>.
/// </value>
/// <remarks>Note: this is a global setting - it applies to all <see cref="ICluster"/> and <see cref="IBucket"/> references within a process.</remarks>
bool IgnoreRemoteCertificateNameMismatch { get; set; }
}
}
Expand Up @@ -463,6 +463,22 @@ public int QueryFailedThreshold
set { this["queryFailedThreshold"] = value; }
}

/// <summary>
/// If TLS/SSL is enabled via <see cref="UseSsl"/> setting this to <c>true</c> will disable hostname validation when authenticating
/// connections to Couchbase Server. This is typically done in test or development enviroments where a domain name (FQDN) has not been
/// specified for the bootstrap uri's <see cref="Servers"/> and the IP address is used to validate the certificate, which will fail with
/// a RemoteCertificateNameMismatch error.
/// </summary>
/// <value>
/// <c>true</c> to ignore hostname validation of the certificate if you are using IP's and not a FQDN to bootstrap; otherwise, <c>false</c>.
/// </value>
[ConfigurationProperty("ignoreRemoteCertificateNameMismatch", IsRequired = false, DefaultValue = false)]
public bool IgnoreRemoteCertificateNameMismatch
{
get { return (bool)this["ignoreRemoteCertificateNameMismatch"]; }
set { this["ignoreRemoteCertificateNameMismatch"] = value; }
}

#region Additional ICouchbaseClientDefinition implementations

IEnumerable<Uri> ICouchbaseClientDefinition.Servers
Expand Down
11 changes: 10 additions & 1 deletion Src/Couchbase/IO/SslConnection.cs
Expand Up @@ -7,6 +7,7 @@
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using Couchbase.Configuration.Client;
using Couchbase.IO.Converters;
using Couchbase.IO.Operations;
using Couchbase.IO.Utils;
Expand Down Expand Up @@ -35,7 +36,15 @@ public SslConnection(IConnectionPool connectionPool, Socket socket, SslStream ss

private static bool ServerCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
Log.Info(m => m("Validating certificate: {0}", sslPolicyErrors));
Log.Info(m => m("Validating certificate [IgnoreRemoteCertificateNameMismatch={0}]: {1}", ClientConfiguration.IgnoreRemoteCertificateNameMismatch, sslPolicyErrors));

if (ClientConfiguration.IgnoreRemoteCertificateNameMismatch)
{
if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateNameMismatch)
{
return true;
}
}
return sslPolicyErrors == SslPolicyErrors.None;
}

Expand Down

0 comments on commit 94f56b2

Please sign in to comment.