public void PruneNodes_Does_Not_Remove_Single_Service_Nodes()
        {
            //Arrange

            var config = ResourceHelper.ReadResource(@"Documents\Configs\rev-36310-service-per-node.json",
                                                     InternalSerializationContext.Default.BucketConfig);
            var context = new ClusterContext();

            var hosts = new List <string> {
                "10.143.194.101", "10.143.194.102", "10.143.194.103", "10.143.194.104"
            };

            hosts.ForEach(x => context.AddNode(CreateMockedNode(x, 11210)));

            //Act

            context.PruneNodes(config);

            //Assert

            foreach (var host in hosts)
            {
                var removed = new HostEndpointWithPort(host, 11210);

                Assert.Contains(context.Nodes, node => node.EndPoint.Equals(removed));
            }
        }
        public async Task <IClusterNode> CreateAndConnectAsync(HostEndpointWithPort endPoint, NodeAdapter?nodeAdapter, CancellationToken cancellationToken = default)
        {
            var clusterNode = new ClusterNode(_clusterContext, _connectionPoolFactory, _logger,
                                              _operationBuilderPool, _circuitBreaker, _saslMechanismFactory, _redactor, endPoint,
                                              nodeAdapter, _tracer);

            //ensure server calls are made to set the state
            await clusterNode.InitializeAsync().ConfigureAwait(false);

            return(clusterNode);
        }
Example #3
0
        public async Task Test_Filter_Removed_Nodes(string oldConfigPath, string newConfigPath)
        {
            var oldConfig = ResourceHelper.ReadResource(oldConfigPath, InternalSerializationContext.Default.BucketConfig);
            var newConfig = ResourceHelper.ReadResource(newConfigPath, InternalSerializationContext.Default.BucketConfig);

            var options     = new ClusterOptions();
            var bucketNodes = new ConcurrentDictionary <HostEndpointWithPort, IClusterNode>();
            var context     = new ClusterContext(new CancellationTokenSource(), options);

            var ipEndpointService = context.ServiceProvider.GetRequiredService <IIpEndPointService>();

            //load up the initial state after bootstrapping
            foreach (var server in oldConfig.GetNodes())
            {
                var endPoint    = HostEndpointWithPort.Create(server, options);
                var clusterNode = new ClusterNode(context, new Mock <IConnectionPoolFactory>().Object,
                                                  new Mock <ILogger <ClusterNode> >().Object,
                                                  new DefaultObjectPool <OperationBuilder>(new OperationBuilderPoolPolicy()),
                                                  new Mock <ICircuitBreaker>().Object,
                                                  new Mock <ISaslMechanismFactory>().Object,
                                                  new TypedRedactor(RedactionLevel.None),
                                                  endPoint,
                                                  server,
                                                  NoopRequestTracer.Instance);

                context.AddNode(clusterNode);
                bucketNodes.TryAdd(endPoint, clusterNode);
            }

            foreach (var nodesExt in newConfig.GetNodes())
            {
                var endPoint = HostEndpointWithPort.Create(nodesExt, options);
                if (bucketNodes.ContainsKey(endPoint))
                {
                    continue;
                }

                var clusterNode = new ClusterNode(context, new Mock <IConnectionPoolFactory>().Object,
                                                  new Mock <ILogger <ClusterNode> >().Object,
                                                  new DefaultObjectPool <OperationBuilder>(new OperationBuilderPoolPolicy()),
                                                  new Mock <ICircuitBreaker>().Object, new Mock <ISaslMechanismFactory>().Object,
                                                  new TypedRedactor(RedactionLevel.None), endPoint, nodesExt,
                                                  NoopRequestTracer.Instance);

                context.AddNode(clusterNode);
                bucketNodes.TryAdd(endPoint, clusterNode);
            }

            context.PruneNodes(newConfig);

            Assert.Equal(newConfig.NodesExt.Count, context.Nodes.Count);
        }
Example #4
0
        public void SpanFormattable_Redacts_Properly()
        {
            var options = new ClusterOptions
            {
                RedactionLevel = RedactionLevel.Full
            };

            var redactor        = new TypedRedactor(options);
            var spanFormattable = new HostEndpointWithPort("localhost", 8675309);
            var asString        = $"{redactor.UserData(spanFormattable)} is formatted";

            Assert.Contains("</ud>", asString);
        }
        private IList <HostEndpointWithPort> GetEndPoints(BucketConfig config)
        {
            var endPoints = new List <HostEndpointWithPort>();

            foreach (var node in config.GetNodes().Where(p => p.IsKvNode))
            {
                //log any alternate address mapping
                _logger.LogInformation(node.ToString());

                endPoints.Add(HostEndpointWithPort.Create(node, _clusterOptions));
            }

            return(endPoints);
        }
        public void PruneNodes_Removes_Rebalanced_Node()
        {
            //Arrange

            var config = ResourceHelper.ReadResource(@"Documents\Configs\config-error.json",
                                                     InternalSerializationContext.Default.BucketConfig);
            var context = new ClusterContext();

            var hosts = new List <string> {
                "10.143.194.101", "10.143.194.102", "10.143.194.103", "10.143.194.104"
            };

            hosts.ForEach(x => context.AddNode(CreateMockedNode(x, 11210)));

            //Act

            context.PruneNodes(config);

            //Assert

            var removed = new HostEndpointWithPort("10.143.194.102", 11210);

            Assert.DoesNotContain(context.Nodes, node => node.EndPoint.Equals(removed));
        }
 public Task <IClusterNode> CreateAndConnectAsync(HostEndpointWithPort endPoint, CancellationToken cancellationToken = default)
 {
     return(CreateAndConnectAsync(endPoint, null, cancellationToken));
 }
Example #8
0
        public async Task <IConnection> CreateAndConnectAsync(HostEndpointWithPort hostEndpoint,
                                                              CancellationToken cancellationToken = default)
        {
            if (_clusterOptions.IsCapella && !_clusterOptions.EffectiveEnableTls)
            {
                _multiplexLogger.LogWarning("TLS is required when connecting to Couchbase Capella. Please enable TLS by prefixing the connection string with \"couchbases://\" (note the final 's').");
            }

            var endPoint = await _ipEndPointService.GetIpEndPointAsync(hostEndpoint.Host, hostEndpoint.Port, cancellationToken)
                           .ConfigureAwait(false);

            if (endPoint is null)
            {
                throw new ConnectException($"Unable to resolve host '{hostEndpoint}'.");
            }

            var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            try
            {
                var connectTask = socket.ConnectAsync(endPoint);

                var whichTask = await Task
                                .WhenAny(connectTask, Task.Delay(_clusterOptions.KvConnectTimeout, cancellationToken))
                                .ConfigureAwait(false);

                if (whichTask != connectTask)
                {
                    // Was a timeout
                    const int connectionTimedOut = 10060;
                    throw new SocketException(connectionTimedOut);
                }
            }
            catch
            {
                socket.Dispose();
                throw;
            }

#if NETCOREAPP3_0_OR_GREATER
            _multiplexLogger.LogDebug("Setting TCP Keep-Alives using SocketOptions - enable keep-alives {EnableTcpKeepAlives}, time {TcpKeepAliveTime}, interval {TcpKeepAliveInterval}.",
                                      _clusterOptions.EnableTcpKeepAlives, _clusterOptions.TcpKeepAliveTime, _clusterOptions.TcpKeepAliveInterval);

            if (!socket.TryEnableKeepAlives(_clusterOptions.EnableTcpKeepAlives,
                                            (int)_clusterOptions.TcpKeepAliveTime.TotalSeconds,
                                            (int)_clusterOptions.TcpKeepAliveInterval.TotalSeconds, out string setKeepAliveMessage)
                )
            {
                _multiplexLogger.LogWarning(setKeepAliveMessage);
            }
#else
            _multiplexLogger.LogDebug(
                "Setting TCP Keep-Alives using Socket.IOControl on {endpoint} - enable tcp keep-alives {EnableTcpKeepAlives}, time {TcpKeepAliveTime}, interval {TcpKeepAliveInterval}",
                endPoint, _clusterOptions.EnableTcpKeepAlives, _clusterOptions.TcpKeepAliveTime,
                _clusterOptions.TcpKeepAliveInterval);

            if (!socket.TrySetKeepAlives(_clusterOptions.EnableTcpKeepAlives,
                                         (uint)_clusterOptions.TcpKeepAliveTime.TotalMilliseconds,
                                         (uint)_clusterOptions.TcpKeepAliveInterval.TotalMilliseconds, out var setKeepAliveMessage)
                )
            {
                _multiplexLogger.LogWarning(setKeepAliveMessage);
            }
#endif

            if (_clusterOptions.EffectiveEnableTls)
            {
                //Check if were using x509 auth, if so fetch the certificates
                X509Certificate2Collection?certs = null;
                if (_clusterOptions.X509CertificateFactory != null)
                {
                    certs = _clusterOptions.X509CertificateFactory.GetCertificates();
                    if (certs == null || certs.Count == 0)
                    {
                        throw new AuthenticationException(
                                  "No certificates matching the X509FindType and specified FindValue were found in the Certificate Store.");
                    }

                    if (_sslLogger.IsEnabled(LogLevel.Debug))
                    {
                        foreach (var cert in certs)
                        {
                            _sslLogger.LogDebug("Cert sent {cert.FriendlyName} - Thumbprint {cert.Thumbprint}",
                                                cert.FriendlyName, cert.Thumbprint);
                        }

                        _sslLogger.LogDebug("Sending {certs.Count} certificates to the server.", certs.Count);
                    }
                }

                //The endpoint we are connecting to
                var targetHost = _clusterOptions.ForceIpAsTargetHost
                    ? endPoint.Address.ToString()
                    : hostEndpoint.Host;

                //create the sslstream with appropriate authentication
                RemoteCertificateValidationCallback?certValidationCallback = _clusterOptions.KvCertificateCallbackValidation;
                if (certValidationCallback == null)
                {
                    certValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
                    {
                        if (_clusterOptions.KvIgnoreRemoteCertificateNameMismatch &&
                            CertificateFactory.ValidatorWithIgnoreNameMismatch(sender, certificate, chain, sslPolicyErrors))
                        {
                            return(true);
                        }

                        return(CertificateFactory.ValidateWithDefaultCertificates(sender, certificate, chain, sslPolicyErrors));
                    };
                }

                var sslStream = new SslStream(new NetworkStream(socket, true), false,
                                              certValidationCallback);

#if !NETCOREAPP3_1_OR_GREATER
                await sslStream.AuthenticateAsClientAsync(targetHost, certs,
                                                          _clusterOptions.EnabledSslProtocols,
                                                          _clusterOptions.EnableCertificateRevocation)
                .ConfigureAwait(false);
#else
                SslClientAuthenticationOptions sslOptions = new SslClientAuthenticationOptions()
                {
                    TargetHost                     = targetHost,
                    ClientCertificates             = certs,
                    EnabledSslProtocols            = _clusterOptions.EnabledSslProtocols,
                    CertificateRevocationCheckMode = _clusterOptions.EnableCertificateRevocation ? X509RevocationMode.Online : X509RevocationMode.NoCheck
                };
                if (_clusterOptions.EnabledTlsCipherSuites != null && _clusterOptions.EnabledTlsCipherSuites.Count > 0)
                {
                    sslOptions.CipherSuitesPolicy = new CipherSuitesPolicy(_clusterOptions.EnabledTlsCipherSuites);
                }

                await sslStream.AuthenticateAsClientAsync(sslOptions)
                .ConfigureAwait(false);
#endif

                var isSecure = sslStream.IsAuthenticated && sslStream.IsSigned && sslStream.IsEncrypted;
                _sslLogger.LogDebug("IsAuthenticated {0} on {1}", sslStream.IsAuthenticated, targetHost);
                _sslLogger.LogDebug("IsSigned {0} on {1}", sslStream.IsSigned, targetHost);
                _sslLogger.LogDebug("IsEncrypted {0} on {1}", sslStream.IsEncrypted, targetHost);

                //punt if we cannot successfully authenticate
                if (!isSecure)
                {
                    throw new AuthenticationException($"The SSL/TLS connection could not be authenticated on [{targetHost}].");
                }

                return(new SslConnection(sslStream, socket.LocalEndPoint !, socket.RemoteEndPoint !,
                                         _sslLogger, _multiplexLogger));
            }

            return(new MultiplexingConnection(socket, _multiplexLogger));
        }
 public Task <IConnection> CreateAndConnectAsync(HostEndpointWithPort hostEndpoint, CancellationToken cancellationToken = default)
 {
     return(Task.FromResult <IConnection>(new MockConnection()));
 }
Example #10
0
 public KetamaNode(HostEndpointWithPort server)
 {
     _server = server;
 }