public void TestFixtureSetUp()
 {
     _options = new ClusterVNodeOptions {
         Cluster = new() {
             DiscoverViaDns = false
         }
     }.RunInMemory();
 public virtual void TestFixtureSetUp()
 {
     _options = WithOptions(
         new ClusterVNodeOptions()
         .RunInMemory()
         .Secure(new X509Certificate2Collection(ssl_connections.GetRootCertificate()),
                 ssl_connections.GetServerCertificate()));
     _node = new ClusterVNode(_options,
                              new AuthenticationProviderFactory(c => new InternalAuthenticationProviderFactory(c)),
                              new AuthorizationProviderFactory(c => new LegacyAuthorizationProviderFactory(c.MainQueue)));
     _node.Start();
 }
Exemple #3
0
        public virtual void TestFixtureSetUp()
        {
            _quorumSize = _clusterSize / 2 + 1;

            _options = WithOptions(new ClusterVNodeOptions()
                                   .InCluster(_clusterSize)
                                   .RunInMemory()
                                   .Secure(new X509Certificate2Collection(ssl_connections.GetRootCertificate()),
                                           ssl_connections.GetServerCertificate()));
            _node = new ClusterVNode <string>(_options, LogFormatAbstractor.V2,
                                              new AuthenticationProviderFactory(_ => new InternalAuthenticationProviderFactory(_)),
                                              new AuthorizationProviderFactory(c => new LegacyAuthorizationProviderFactory(c.MainQueue)));
            _node.Start();
        }
        public void SetUp()
        {
            var baseIpAddress  = IPAddress.Parse("127.0.1.15");
            var internalSecTcp = new IPEndPoint(baseIpAddress, 1114);
            var externalSecTcp = new IPEndPoint(baseIpAddress, 1115);

            _options = new ClusterVNodeOptions().RunInMemory()
                       .WithInternalSecureTcpOn(internalSecTcp)
                       .WithExternalSecureTcpOn(externalSecTcp);
            try {
                _ = new ClusterVNode <TStreamId>(_options, LogFormatHelper <TLogFormat, TStreamId> .LogFormat);
            } catch (Exception ex) {
                _caughtException = ex;
            }
        }
        public OptionStructure[] GetOptionsInfo(ClusterVNodeOptions options)
        {
            var optionsToSendToClient = new List <OptionStructure>();
            var optionGroups          = typeof(ClusterVNodeOptions).GetProperties()
                                        .Where(p => p.IsDefined(typeof(ClusterVNodeOptions.OptionGroupAttribute)));

            foreach (PropertyInfo sectionInfo in optionGroups)
            {
                var section = sectionInfo.GetValue(options, null);
                foreach (PropertyInfo property in sectionInfo.PropertyType.GetProperties())
                {
                    var      argumentDescriptionAttribute = property.GetCustomAttribute <DescriptionAttribute>();
                    var      configFileOptionValue        = property.GetValue(section, null);
                    string[] possibleValues = null;
                    if (property.PropertyType.IsEnum)
                    {
                        possibleValues = property.PropertyType.GetEnumNames();
                    }
                    else if (property.PropertyType.IsArray)
                    {
                        var array = configFileOptionValue as Array;
                        if (array == null)
                        {
                            continue;
                        }
                        var configFileOptionValueAsString = String.Empty;
                        for (var i = 0; i < array.Length; i++)
                        {
                            configFileOptionValueAsString += array.GetValue(i).ToString();
                        }

                        configFileOptionValue = configFileOptionValueAsString;
                    }

                    optionsToSendToClient.Add(new OptionStructure {
                        Name           = property.Name,
                        Description    = argumentDescriptionAttribute == null ? "" : argumentDescriptionAttribute.Description,
                        Group          = property.DeclaringType?.GetCustomAttribute <DescriptionAttribute>()?.Description,
                        Value          = configFileOptionValue == null ? "" : configFileOptionValue.ToString(),
                        PossibleValues = possibleValues
                    });
                }
            }

            return(optionsToSendToClient.ToArray());
        }
 protected override ClusterVNodeOptions WithOptions(ClusterVNodeOptions options) =>
 options with
 protected abstract ClusterVNodeOptions WithOptions(ClusterVNodeOptions options);
Exemple #8
0
        public static async Task <int> Main(string[] args)
        {
            ThreadPool.SetMaxThreads(1000, 1000);
            ClusterVNodeOptions options;
            var exitCodeSource = new TaskCompletionSource <int>();
            var cts            = new CancellationTokenSource();

            Log.Logger = EventStoreLoggerConfiguration.ConsoleLog;
            try {
                try {
                    options = ClusterVNodeOptions.FromConfiguration(args, Environment.GetEnvironmentVariables());
                } catch (Exception ex) {
                    Log.Fatal($"Error while parsing options: {ex.Message}");
                    Log.Information($"Options:{Environment.NewLine}{ClusterVNodeOptions.HelpText}");

                    return(1);
                }

                var logsDirectory = string.IsNullOrWhiteSpace(options.Log.Log)
                                        ? Locations.DefaultLogDirectory
                                        : options.Log.Log;
                EventStoreLoggerConfiguration.Initialize(logsDirectory, options.GetComponentName(),
                                                         options.Log.LogConsoleFormat,
                                                         options.Log.LogFileSize,
                                                         options.Log.LogFileInterval,
                                                         options.Log.LogFileRetentionCount,
                                                         options.Log.DisableLogFile,
                                                         options.Log.LogConfig);

                if (options.Application.Help)
                {
                    await Console.Out.WriteLineAsync(ClusterVNodeOptions.HelpText);

                    return(0);
                }

                if (options.Application.Version)
                {
                    await Console.Out.WriteLineAsync(VersionInfo.Text);

                    return(0);
                }

                Log.Information("\n{description,-25} {version} ({branch}/{hashtag}, {timestamp})", "ES VERSION:",
                                VersionInfo.Version, VersionInfo.Branch, VersionInfo.Hashtag, VersionInfo.Timestamp);
                Log.Information("{description,-25} {osFlavor} ({osVersion})", "OS:", OS.OsFlavor,
                                Environment.OSVersion);
                Log.Information("{description,-25} {osRuntimeVersion} ({architecture}-bit)", "RUNTIME:",
                                OS.GetRuntimeVersion(),
                                Marshal.SizeOf(typeof(IntPtr)) * 8);
                Log.Information("{description,-25} {maxGeneration}", "GC:",
                                GC.MaxGeneration == 0
                                                ? "NON-GENERATION (PROBABLY BOEHM)"
                                                : $"{GC.MaxGeneration + 1} GENERATIONS");
                Log.Information("{description,-25} {logsDirectory}", "LOGS:", logsDirectory);
                Log.Information(options.DumpOptions());

                var deprecationWarnings = options.GetDeprecationWarnings();
                if (deprecationWarnings != null)
                {
                    Log.Warning($"DEPRECATED{Environment.NewLine}{deprecationWarnings}");
                }

                if (options.Application.Insecure)
                {
                    Log.Warning(
                        "\n==============================================================================================================\n" +
                        "INSECURE MODE IS ON. THIS MODE IS *NOT* RECOMMENDED FOR PRODUCTION USE.\n" +
                        "INSECURE MODE WILL DISABLE ALL AUTHENTICATION, AUTHORIZATION AND TRANSPORT SECURITY FOR ALL CLIENTS AND NODES.\n" +
                        "==============================================================================================================\n");
                }

                if (!options.Cluster.DiscoverViaDns && options.Cluster.GossipSeed.Length == 0 &&
                    options.Cluster.ClusterSize == 1)
                {
                    Log.Information(
                        "DNS discovery is disabled, but no gossip seed endpoints have been specified. Since "
                        + "the cluster size is set to 1, this may be intentional. Gossip seeds can be specified "
                        + "using the `GossipSeed` option.");
                }

                if (options.Application.WhatIf)
                {
                    return(0);
                }

                Application.RegisterExitAction(code => {
                    cts.Cancel();
                    exitCodeSource.SetResult(code);
                });

                Console.CancelKeyPress += delegate {
                    Application.Exit(0, "Cancelled.");
                };
                using (var hostedService = new ClusterVNodeHostedService(options)) {
                    using var signal = new ManualResetEventSlim(false);
                    _ = Run(hostedService, signal);
                    // ReSharper disable MethodSupportsCancellation
                    signal.Wait();
                    // ReSharper restore MethodSupportsCancellation
                }

                return(await exitCodeSource.Task);

                async Task Run(ClusterVNodeHostedService hostedService, ManualResetEventSlim signal)
                {
                    try {
                        await new HostBuilder()
                        .ConfigureHostConfiguration(builder =>
                                                    builder.AddEnvironmentVariables("DOTNET_").AddCommandLine(args))
                        .ConfigureAppConfiguration(builder =>
                                                   builder.AddEnvironmentVariables().AddCommandLine(args))
                        .ConfigureServices(services => services.AddSingleton <IHostedService>(hostedService))
                        .ConfigureLogging(logging => logging.AddSerilog())
                        .ConfigureServices(services => services.Configure <KestrelServerOptions>(
                                               EventStoreKestrelConfiguration.GetConfiguration()))
                        .ConfigureWebHostDefaults(builder => builder
                                                  .UseKestrel(server => {
                            server.Limits.Http2.KeepAlivePingDelay =
                                TimeSpan.FromMilliseconds(options.Grpc.KeepAliveInterval);
                            server.Limits.Http2.KeepAlivePingTimeout =
                                TimeSpan.FromMilliseconds(options.Grpc.KeepAliveTimeout);
                            server.Listen(options.Interface.ExtIp, options.Interface.HttpPort,
                                          listenOptions => {
                                if (hostedService.Node.DisableHttps)
                                {
                                    listenOptions.Use(next =>
                                                      new ClearTextHttpMultiplexingMiddleware(next).OnConnectAsync);
                                }
                                else
                                {
                                    listenOptions.UseHttps(new HttpsConnectionAdapterOptions {
                                        ServerCertificateSelector = delegate {
                                            return(hostedService.Node.CertificateSelector());
                                        },
                                        ClientCertificateMode       = ClientCertificateMode.AllowCertificate,
                                        ClientCertificateValidation = (certificate, chain, sslPolicyErrors) => {
                                            var(isValid, error) =
                                                hostedService.Node.InternalClientCertificateValidator(
                                                    certificate,
                                                    chain,
                                                    sslPolicyErrors);
                                            if (!isValid && error != null)
                                            {
                                                Log.Error("Client certificate validation error: {e}", error);
                                            }

                                            return(isValid);
                                        }
                                    });
                                }
                            });
                        })
                                                  .ConfigureServices(services => hostedService.Node.Startup.ConfigureServices(services))
                                                  .Configure(hostedService.Node.Startup.Configure))
                        .RunConsoleAsync(options => options.SuppressStatusMessages = true, cts.Token);
                    } catch (Exception ex) {
                        Log.Fatal("Error occurred during setup: {e}", ex);
                        exitCodeSource.TrySetResult(1);
                    } finally {
                        signal.Set();
                    }
                }
            } catch (InvalidConfigurationException ex) {
                Log.Fatal("Invalid Configuration: " + ex.Message);
                return(1);
            }
            catch (Exception ex) {
                Log.Fatal(ex, "Host terminated unexpectedly.");
                return(1);
            } finally {
                Log.CloseAndFlush();
            }
        }
Exemple #9
0
        public ClusterVNodeHostedService(ClusterVNodeOptions options)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }
            _options = options.Projections.RunProjections >= ProjectionType.System
                                ? options.WithSubsystem(new ProjectionsSubsystem(
                                                            new ProjectionSubsystemOptions(
                                                                options.Projections.ProjectionThreads,
                                                                options.Projections.RunProjections,
                                                                options.Application.StartStandardProjections,
                                                                TimeSpan.FromMinutes(options.Projections.ProjectionsQueryExpiry),
                                                                options.Projections.FaultOutOfOrderProjections,
                                                                options.Projections.ProjectionCompilationTimeout,
                                                                options.Projections.ProjectionExecutionTimeout)))
                                : options;

            if (!_options.Database.MemDb)
            {
                var absolutePath = Path.GetFullPath(_options.Database.Db);
                if (Runtime.IsWindows)
                {
                    absolutePath = absolutePath.ToLower();
                }

                _dbLock = new ExclusiveDbLock(absolutePath);
                if (!_dbLock.Acquire())
                {
                    throw new InvalidConfigurationException($"Couldn't acquire exclusive lock on DB at '{_options.Database.Db}'.");
                }
            }

            _clusterNodeMutex = new ClusterNodeMutex();
            if (!_clusterNodeMutex.Acquire())
            {
                throw new InvalidConfigurationException($"Couldn't acquire exclusive Cluster Node mutex '{_clusterNodeMutex.MutexName}'.");
            }

            var authorizationConfig = string.IsNullOrEmpty(_options.Auth.AuthorizationConfig)
                                ? _options.Application.Config
                                : _options.Auth.AuthorizationConfig;

            var authenticationConfig = string.IsNullOrEmpty(_options.Auth.AuthenticationConfig)
                                ? _options.Application.Config
                                : _options.Auth.AuthenticationConfig;

            var pluginLoader = new PluginLoader(new DirectoryInfo(Locations.PluginsDirectory));

            var plugInContainer = FindPlugins();

            if (_options.Database.DbLogFormat == DbLogFormat.V2)
            {
                var logFormatFactory = new LogV2FormatAbstractorFactory();
                Node = ClusterVNode.Create(_options, logFormatFactory, GetAuthenticationProviderFactory(),
                                           GetAuthorizationProviderFactory(), GetPersistentSubscriptionConsumerStrategyFactories());
            }
            else if (_options.Database.DbLogFormat == DbLogFormat.ExperimentalV3)
            {
                var logFormatFactory = new LogV3FormatAbstractorFactory();
                Node = ClusterVNode.Create(_options, logFormatFactory, GetAuthenticationProviderFactory(),
                                           GetAuthorizationProviderFactory(), GetPersistentSubscriptionConsumerStrategyFactories());
            }
            else
            {
                throw new ArgumentOutOfRangeException("Unexpected log format specified.");
            }

            var runProjections        = _options.Projections.RunProjections;
            var enabledNodeSubsystems = runProjections >= ProjectionType.System
                                ? new[] { NodeSubsystems.Projections }
                                : Array.Empty <NodeSubsystems>();

            RegisterWebControllers(enabledNodeSubsystems);

            AuthorizationProviderFactory GetAuthorizationProviderFactory()
            {
                if (_options.Application.Insecure)
                {
                    return(new AuthorizationProviderFactory(_ => new PassthroughAuthorizationProviderFactory()));
                }
                var authorizationTypeToPlugin = new Dictionary <string, AuthorizationProviderFactory> {
                    {
                        "internal", new AuthorizationProviderFactory(components =>
                                                                     new LegacyAuthorizationProviderFactory(components.MainQueue))
                    }
                };

                foreach (var potentialPlugin in pluginLoader.Load <IAuthorizationPlugin>())
                {
                    try {
                        var commandLine = potentialPlugin.CommandLineName.ToLowerInvariant();
                        Log.Information(
                            "Loaded authorization plugin: {plugin} version {version} (Command Line: {commandLine})",
                            potentialPlugin.Name, potentialPlugin.Version, commandLine);
                        authorizationTypeToPlugin.Add(commandLine,
                                                      new AuthorizationProviderFactory(_ =>
                                                                                       potentialPlugin.GetAuthorizationProviderFactory(authorizationConfig)));
                    } catch (CompositionException ex) {
                        Log.Error(ex, "Error loading authentication plugin.");
                    }
                }

                if (!authorizationTypeToPlugin.TryGetValue(_options.Auth.AuthorizationType.ToLowerInvariant(),
                                                           out var factory))
                {
                    throw new ApplicationInitializationException(
                              $"The authorization type {_options.Auth.AuthorizationType} is not recognised. If this is supposed " +
                              $"to be provided by an authorization plugin, confirm the plugin DLL is located in {Locations.PluginsDirectory}." +
                              Environment.NewLine +
                              $"Valid options for authorization are: {string.Join(", ", authorizationTypeToPlugin.Keys)}.");
                }

                return(factory);
            }
 protected override ClusterVNodeOptions WithOptions(ClusterVNodeOptions options) =>
 options.Insecure();
 protected override ClusterVNodeOptions WithOptions(ClusterVNodeOptions options) =>
 options.RunInMemory();
 protected override ClusterVNodeOptions WithOptions(ClusterVNodeOptions options) => options.RunOnDisk(_dbPath);
 public InfoControllerBuilder WithOptions(ClusterVNodeOptions options)
 {
     _options = options;
     return(this);
 }
 public InfoController(ClusterVNodeOptions options, IDictionary <string, bool> features, IAuthenticationProvider authenticationProvider)
 {
     _options  = options;
     _features = features;
     _authenticationProvider = authenticationProvider;
 }
 public static ClusterVNodeOptions InCluster(this ClusterVNodeOptions options, int clusterSize) => options with