diff --git a/examples/Elastic.Ephemeral.Example/Program.cs b/examples/Elastic.Ephemeral.Example/Program.cs index f4cdb1c..5d03b9b 100644 --- a/examples/Elastic.Ephemeral.Example/Program.cs +++ b/examples/Elastic.Ephemeral.Example/Program.cs @@ -3,7 +3,17 @@ // See the LICENSE file in the project root for more information using Elastic.Elasticsearch.Ephemeral; +using static Elastic.Elasticsearch.Ephemeral.ClusterFeatures; -var config = new EphemeralClusterConfiguration("8.7.0"); -var cluster = new EphemeralCluster(config); + +var config = new EphemeralClusterConfiguration("8.7.0", XPack | Security | SSL); +using var cluster = new EphemeralCluster(config); + +var exitEvent = new ManualResetEvent(false); +Console.CancelKeyPress += (sender, eventArgs) => { + cluster.Dispose(); + eventArgs.Cancel = true; + exitEvent.Set(); +}; using var started = cluster.Start(); +exitEvent.WaitOne(); diff --git a/src/Elastic.Elasticsearch.Ephemeral/EphemeralFileSystem.cs b/src/Elastic.Elasticsearch.Ephemeral/EphemeralFileSystem.cs index 6551fee..15acaa7 100644 --- a/src/Elastic.Elasticsearch.Ephemeral/EphemeralFileSystem.cs +++ b/src/Elastic.Elasticsearch.Ephemeral/EphemeralFileSystem.cs @@ -32,6 +32,7 @@ public EphemeralFileSystem(ElasticVersion version, string clusterName) : base(ve public string CertificatesPath => Path.Combine(ConfigPath, CertificateFolderName); public string CaCertificate => Path.Combine(CertificatesPath, "ca", "ca") + ".crt"; + public string CaPrivateKey => Path.Combine(CertificatesPath, "ca", "ca") + ".key"; public string NodePrivateKey => Path.Combine(CertificatesPath, CertificateNodeName, CertificateNodeName) + ".key"; diff --git a/src/Elastic.Elasticsearch.Ephemeral/Tasks/BeforeStartNodeTasks/XPack/GenerateCertificatesTask.cs b/src/Elastic.Elasticsearch.Ephemeral/Tasks/BeforeStartNodeTasks/XPack/GenerateCertificatesTask.cs index da7a0c2..c8a6b0a 100644 --- a/src/Elastic.Elasticsearch.Ephemeral/Tasks/BeforeStartNodeTasks/XPack/GenerateCertificatesTask.cs +++ b/src/Elastic.Elasticsearch.Ephemeral/Tasks/BeforeStartNodeTasks/XPack/GenerateCertificatesTask.cs @@ -2,6 +2,7 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information +using System; using System.IO; using System.IO.Compression; using System.Linq; @@ -39,6 +40,12 @@ public override void Run(IEphemeralCluster cluste if (!cluster.ClusterConfiguration.EnableSsl) return; var config = cluster.ClusterConfiguration; + + if (Directory.Exists(config.FileSystem.CertificatesPath)) + { + cluster.Writer.WriteDiagnostic($"{{{nameof(GenerateCertificatesTask)}}} Skipping certificate generation as ${{{config.FileSystem.CertificatesPath}}} already exists"); + return; + } var fileSystem = cluster.FileSystem; //due to a bug in certgen this file needs to live in two places @@ -80,7 +87,12 @@ private static void GenerateCertificates(IEphemeralCluster GenerateCaCertificate(config, zipLocation, writer), + "8.0.0"); + NewOrCachedCertificates(cluster, name, path, writer, + zipLocation => GenerateCertificate(config, name, path, zipLocation, silentModeConfigFile, writer) + ); } private static void GenerateUnusedCertificates(IEphemeralCluster cluster, @@ -89,16 +101,23 @@ private static void GenerateUnusedCertificates(IEphemeralCluster GenerateCaCertificate(config, zipLocation, writer), + "8.0.0"); + NewOrCachedCertificates(cluster, name, path, writer, + zipLocation => GenerateCertificate(config, name, path, zipLocation, silentModeConfigFile, writer) + ); } private static void NewOrCachedCertificates(IEphemeralCluster cluster, - string name, string path, string silentModeConfigFile, IConsoleLineHandler writer) + string name, string path, IConsoleLineHandler writer, Action generateCertificateAction, string minVersion = null) { var config = cluster.ClusterConfiguration; var cachedEsHomeFolder = Path.Combine(config.FileSystem.LocalFolder, cluster.GetCacheFolderName()); var zipLocationCache = Path.Combine(cachedEsHomeFolder, name) + ".zip"; + if (minVersion != null && config.Version < minVersion) return; + if (File.Exists(zipLocationCache)) { writer.WriteDiagnostic( @@ -110,7 +129,7 @@ private static void NewOrCachedCertificates(IEphemeralCluster= "6.3.0" ? Path.Combine(config.FileSystem.ConfigPath, name) + ".zip" : Path.Combine(config.FileSystem.ConfigPath, "x-pack", name) + ".zip"; - GenerateCertificate(config, name, path, zipLocation, silentModeConfigFile, writer); + generateCertificateAction(zipLocation); if (!File.Exists(zipLocationCache)) { @@ -133,17 +152,17 @@ private static void GenerateCertificate(EphemeralClusterConfiguration config, st : Path.Combine(fs.ElasticsearchHome, "bin", "elasticsearch-certutil") + BinarySuffix : Path.Combine(fs.ElasticsearchHome, "bin", "x-pack", "certgen") + BinarySuffix; - - if (!Directory.Exists(path)) - { - if (config.Version < "7.0.0") - ExecuteBinary(config, writer, binary, "generating ssl certificates for this session", - "-in", silentModeConfigFile, "-out", @out); - else - ExecuteBinary(config, writer, binary, "generating ssl certificates for this session", - "cert", - "-in", silentModeConfigFile, "-out", @out); - } + if (config.Version < "7.0.0") + ExecuteBinary(config, writer, binary, "generating ssl certificates for this session", + "-in", silentModeConfigFile, "-out", @out); + else if (config.Version < "8.0.0") + ExecuteBinary(config, writer, binary, "generating ssl certificates for this session", + "cert", + "--in", silentModeConfigFile, "--out", @out); + else + ExecuteBinary(config, writer, binary, "generating ssl certificates for this session", + "cert", "--pem", + "--in", silentModeConfigFile, "--out", @out, "--ca-cert", fs.CaCertificate, "--ca-key", fs.CaPrivateKey); var badLocation = Path.Combine(config.FileSystem.ElasticsearchHome, "config", "x-pack", @out); //not necessary anymore now that we patch .in.bat i think @@ -154,14 +173,25 @@ private static void GenerateCertificate(EphemeralClusterConfiguration config, st } } + private static void GenerateCaCertificate(EphemeralClusterConfiguration config, + string zipLocation, IConsoleLineHandler writer) + { + if (config.Version < "8.0.0") return; + + var binary = Path.Combine(config.FileSystem.ElasticsearchHome, "bin", "elasticsearch-certutil") + BinarySuffix; + + ExecuteBinary(config, writer, binary, "generating CA certificate for this session", + "ca", "--pem", "--out", zipLocation); + } + private static void UnpackCertificatesZip(string zipLocation, string outFolder, IConsoleLineHandler writer) { - if (Directory.Exists(outFolder)) return; - writer.WriteDiagnostic($"{{{nameof(GenerateCertificatesTask)}}} unzipping certificates to {outFolder}"); Directory.CreateDirectory(outFolder); + ZipFile.ExtractToDirectory(zipLocation, outFolder); + } } } diff --git a/src/Elastic.Elasticsearch.Ephemeral/Tasks/IClusterComposeTask.cs b/src/Elastic.Elasticsearch.Ephemeral/Tasks/IClusterComposeTask.cs index 52c39c0..ebfdbf6 100644 --- a/src/Elastic.Elasticsearch.Ephemeral/Tasks/IClusterComposeTask.cs +++ b/src/Elastic.Elasticsearch.Ephemeral/Tasks/IClusterComposeTask.cs @@ -187,6 +187,7 @@ private static void ExecuteBinaryInternal(EphemeralClusterConfiguration config, errorOut = errorOut .Where(e => !string.IsNullOrWhiteSpace(e.Line)) .Where(e => !e.Line.Contains("usage of JAVA_HOME is deprecated")) + .Where(e => !e.Line.Contains("using ES_JAVA_HOME")) .Where(e => !e.Line.Trim().StartsWith("warning:")) .ToList();