From e5824d727c105798b4fd12ea0b99283ae40dac0e Mon Sep 17 00:00:00 2001 From: Ioannis Kakavas Date: Thu, 19 Jul 2018 14:18:47 +0300 Subject: [PATCH 1/8] Remove BouncyCastle dependency from runtime This commit introduces a new project that builds a Jar of the classes that have a dependency on BouncyCastle and puts it in a subdirectory of lib (/tools/security-cli) along with the BouncyCastle jars. This directory is then passed in the ES_ADDITIONAL_CLASSPATH_DIRECTORIES of the CLI tools that use these classes. BouncyCastle is removed as a runtime dependency (remains as a compileOnly one) from x-pack core and x-pack security. --- distribution/build.gradle | 4 ++++ x-pack/plugin/core/build.gradle | 6 ++--- x-pack/plugin/security/build.gradle | 5 ++--- x-pack/plugin/security/cli/build.gradle | 22 +++++++++++++++++++ .../licenses/bcpkix-jdk15on-1.59.jar.sha1 | 0 .../licenses/bcprov-jdk15on-1.59.jar.sha1 | 0 .../cli}/licenses/bouncycastle-LICENSE.txt | 0 .../cli}/licenses/bouncycastle-NOTICE.txt | 0 .../src/main/bin/elasticsearch-certgen | 1 + .../src/main/bin/elasticsearch-certgen.bat | 1 + .../src/main/bin/elasticsearch-certutil | 1 + .../src/main/bin/elasticsearch-certutil.bat | 1 + 12 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 x-pack/plugin/security/cli/build.gradle rename x-pack/plugin/{core => security/cli}/licenses/bcpkix-jdk15on-1.59.jar.sha1 (100%) rename x-pack/plugin/{core => security/cli}/licenses/bcprov-jdk15on-1.59.jar.sha1 (100%) rename x-pack/plugin/{core => security/cli}/licenses/bouncycastle-LICENSE.txt (100%) rename x-pack/plugin/{core => security/cli}/licenses/bouncycastle-NOTICE.txt (100%) diff --git a/distribution/build.gradle b/distribution/build.gradle index 6ffb678cb2ba8..f690cd1aabcea 100644 --- a/distribution/build.gradle +++ b/distribution/build.gradle @@ -238,6 +238,10 @@ configure(subprojects.findAll { ['archives', 'packages'].contains(it.name) }) { from { project(':distribution:tools:plugin-cli').jar } from { project(':distribution:tools:plugin-cli').configurations.runtime } } + into('tools/security-cli') { + from { project(':x-pack:plugin:security:cli').jar } + from { project(':x-pack:plugin:security:cli').configurations.compile } + } } modulesFiles = { oss -> diff --git a/x-pack/plugin/core/build.gradle b/x-pack/plugin/core/build.gradle index 5db149bc6774e..7430f403dbed5 100644 --- a/x-pack/plugin/core/build.gradle +++ b/x-pack/plugin/core/build.gradle @@ -18,7 +18,6 @@ esplugin { } dependencyLicenses { - mapping from: /bc.*/, to: 'bouncycastle' mapping from: /http.*/, to: 'httpclient' // pulled in by rest client mapping from: /commons-.*/, to: 'commons' // pulled in by rest client } @@ -36,8 +35,8 @@ dependencies { // security deps compile 'com.unboundid:unboundid-ldapsdk:3.2.0' - compile 'org.bouncycastle:bcprov-jdk15on:1.59' - compile 'org.bouncycastle:bcpkix-jdk15on:1.59' + compileOnly 'org.bouncycastle:bcprov-jdk15on:1.59' + compileOnly 'org.bouncycastle:bcpkix-jdk15on:1.59' compile project(path: ':modules:transport-netty4', configuration: 'runtime') testCompile 'org.elasticsearch:securemock:1.2' @@ -114,6 +113,7 @@ task testJar(type: Jar) { appendix 'test' from sourceSets.test.output } + artifacts { // normal es plugins do not publish the jar but we need to since users need it for Transport Clients and extensions archives jar diff --git a/x-pack/plugin/security/build.gradle b/x-pack/plugin/security/build.gradle index 5bdfdf65014f9..854b01659541a 100644 --- a/x-pack/plugin/security/build.gradle +++ b/x-pack/plugin/security/build.gradle @@ -22,8 +22,8 @@ dependencies { testCompile project(path: xpackModule('core'), configuration: 'testArtifacts') compile 'com.unboundid:unboundid-ldapsdk:3.2.0' - compile 'org.bouncycastle:bcprov-jdk15on:1.59' - compile 'org.bouncycastle:bcpkix-jdk15on:1.59' + compileOnly 'org.bouncycastle:bcprov-jdk15on:1.59' + compileOnly 'org.bouncycastle:bcpkix-jdk15on:1.59' // the following are all SAML dependencies - might as well download the whole internet compile "org.opensaml:opensaml-core:3.3.0" @@ -79,7 +79,6 @@ sourceSets.test.resources { srcDir '../core/src/test/resources' } dependencyLicenses { - mapping from: /bc.*/, to: 'bouncycastle' mapping from: /java-support|opensaml-.*/, to: 'shibboleth' mapping from: /http.*/, to: 'httpclient' } diff --git a/x-pack/plugin/security/cli/build.gradle b/x-pack/plugin/security/cli/build.gradle new file mode 100644 index 0000000000000..148c84f1c1fc1 --- /dev/null +++ b/x-pack/plugin/security/cli/build.gradle @@ -0,0 +1,22 @@ +apply plugin: 'elasticsearch.build' + +archivesBaseName = 'elasticsearch-security-cli' +dependencies { + compileOnly "org.elasticsearch:elasticsearch:${version}" + compile 'org.bouncycastle:bcprov-jdk15on:1.59' + compile 'org.bouncycastle:bcpkix-jdk15on:1.59' +} + +jar { + from(project(':x-pack:plugin:core').sourceSets.main.output.classesDirs) { + include 'org/elasticsearch/xpack/core/ssl/CertificateTool.class' + include 'org/elasticsearch/xpack/core/ssl/CertificateGenerateTool.class' + include 'org/elasticsearch/xpack/core/ssl/CertGenUtils.class' + } +} + +dependencyLicenses { + mapping from: /bc.*/, to: 'bouncycastle' +} + +licenseHeaders.enabled = false \ No newline at end of file diff --git a/x-pack/plugin/core/licenses/bcpkix-jdk15on-1.59.jar.sha1 b/x-pack/plugin/security/cli/licenses/bcpkix-jdk15on-1.59.jar.sha1 similarity index 100% rename from x-pack/plugin/core/licenses/bcpkix-jdk15on-1.59.jar.sha1 rename to x-pack/plugin/security/cli/licenses/bcpkix-jdk15on-1.59.jar.sha1 diff --git a/x-pack/plugin/core/licenses/bcprov-jdk15on-1.59.jar.sha1 b/x-pack/plugin/security/cli/licenses/bcprov-jdk15on-1.59.jar.sha1 similarity index 100% rename from x-pack/plugin/core/licenses/bcprov-jdk15on-1.59.jar.sha1 rename to x-pack/plugin/security/cli/licenses/bcprov-jdk15on-1.59.jar.sha1 diff --git a/x-pack/plugin/core/licenses/bouncycastle-LICENSE.txt b/x-pack/plugin/security/cli/licenses/bouncycastle-LICENSE.txt similarity index 100% rename from x-pack/plugin/core/licenses/bouncycastle-LICENSE.txt rename to x-pack/plugin/security/cli/licenses/bouncycastle-LICENSE.txt diff --git a/x-pack/plugin/core/licenses/bouncycastle-NOTICE.txt b/x-pack/plugin/security/cli/licenses/bouncycastle-NOTICE.txt similarity index 100% rename from x-pack/plugin/core/licenses/bouncycastle-NOTICE.txt rename to x-pack/plugin/security/cli/licenses/bouncycastle-NOTICE.txt diff --git a/x-pack/plugin/security/src/main/bin/elasticsearch-certgen b/x-pack/plugin/security/src/main/bin/elasticsearch-certgen index 4a192ac3b1633..b40cde75e38b1 100644 --- a/x-pack/plugin/security/src/main/bin/elasticsearch-certgen +++ b/x-pack/plugin/security/src/main/bin/elasticsearch-certgen @@ -6,5 +6,6 @@ ES_MAIN_CLASS=org.elasticsearch.xpack.core.ssl.CertificateGenerateTool \ ES_ADDITIONAL_SOURCES="x-pack-env;x-pack-security-env" \ + ES_ADDITIONAL_CLASSPATH_DIRECTORIES=lib/tools/security-cli \ "`dirname "$0"`"/elasticsearch-cli \ "$@" diff --git a/x-pack/plugin/security/src/main/bin/elasticsearch-certgen.bat b/x-pack/plugin/security/src/main/bin/elasticsearch-certgen.bat index b5842b57b168c..8ca62b8f54efe 100644 --- a/x-pack/plugin/security/src/main/bin/elasticsearch-certgen.bat +++ b/x-pack/plugin/security/src/main/bin/elasticsearch-certgen.bat @@ -9,6 +9,7 @@ setlocal enableextensions set ES_MAIN_CLASS=org.elasticsearch.xpack.core.ssl.CertificateGenerateTool set ES_ADDITIONAL_SOURCES=x-pack-env;x-pack-security-env +set ES_ADDITIONAL_CLASSPATH_DIRECTORIES=lib/tools/security-cli call "%~dp0elasticsearch-cli.bat" ^ %%* ^ || exit /b 1 diff --git a/x-pack/plugin/security/src/main/bin/elasticsearch-certutil b/x-pack/plugin/security/src/main/bin/elasticsearch-certutil index a13be812f0bc4..c351be40a80cf 100644 --- a/x-pack/plugin/security/src/main/bin/elasticsearch-certutil +++ b/x-pack/plugin/security/src/main/bin/elasticsearch-certutil @@ -6,5 +6,6 @@ ES_MAIN_CLASS=org.elasticsearch.xpack.core.ssl.CertificateTool \ ES_ADDITIONAL_SOURCES="x-pack-env;x-pack-security-env" \ + ES_ADDITIONAL_CLASSPATH_DIRECTORIES=lib/tools/security-cli \ "`dirname "$0"`"/elasticsearch-cli \ "$@" diff --git a/x-pack/plugin/security/src/main/bin/elasticsearch-certutil.bat b/x-pack/plugin/security/src/main/bin/elasticsearch-certutil.bat index 2e397190f23a9..83c6bc26cfdeb 100644 --- a/x-pack/plugin/security/src/main/bin/elasticsearch-certutil.bat +++ b/x-pack/plugin/security/src/main/bin/elasticsearch-certutil.bat @@ -9,6 +9,7 @@ setlocal enableextensions set ES_MAIN_CLASS=org.elasticsearch.xpack.core.ssl.CertificateTool set ES_ADDITIONAL_SOURCES=x-pack-env;x-pack-security-env +set ES_ADDITIONAL_CLASSPATH_DIRECTORIES=lib/tools/security-cli call "%~dp0elasticsearch-cli.bat" ^ %%* ^ || exit /b 1 From 15f8c15430525d851f90d69acce38520e452453e Mon Sep 17 00:00:00 2001 From: Ioannis Kakavas Date: Fri, 20 Jul 2018 00:55:21 +0300 Subject: [PATCH 2/8] Address feedback - Move source for CertificateTool, CertificateGenerateTool and CertGenUtils and associated tests to the new project - Ensure that the genrated jar and bc dependencies are not bundled in oss --- distribution/archives/build.gradle | 2 +- distribution/build.gradle | 32 +++-- distribution/packages/build.gradle | 2 +- x-pack/plugin/core/build.gradle | 2 - .../xpack/core/ssl/CertParsingUtils.java | 10 +- x-pack/plugin/security/build.gradle | 2 - x-pack/plugin/security/cli/build.gradle | 20 ++- .../xpack/security/cli}/CertGenUtils.java | 22 +-- .../cli}/CertificateGenerateTool.java | 128 ++++++++++-------- .../xpack/security/cli}/CertificateTool.java | 120 ++++++++-------- .../security/cli}/CertGenUtilsTests.java | 3 +- .../cli}/CertificateGenerateToolTests.java | 10 +- .../security/cli}/CertificateToolTests.java | 16 ++- 13 files changed, 192 insertions(+), 177 deletions(-) rename x-pack/plugin/{core/src/main/java/org/elasticsearch/xpack/core/ssl => security/cli/src/main/java/org/elasticsearch/xpack/security/cli}/CertGenUtils.java (93%) rename x-pack/plugin/{core/src/main/java/org/elasticsearch/xpack/core/ssl => security/cli/src/main/java/org/elasticsearch/xpack/security/cli}/CertificateGenerateTool.java (90%) rename x-pack/plugin/{core/src/main/java/org/elasticsearch/xpack/core/ssl => security/cli/src/main/java/org/elasticsearch/xpack/security/cli}/CertificateTool.java (92%) rename x-pack/plugin/{core/src/test/java/org/elasticsearch/xpack/core/ssl => security/cli/src/test/java/org/elasticsearch/xpack/security/cli}/CertGenUtilsTests.java (97%) rename x-pack/{qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/core/ssl => plugin/security/cli/src/test/java/org/elasticsearch/xpack/security/cli}/CertificateGenerateToolTests.java (98%) rename x-pack/{qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/core/ssl => plugin/security/cli/src/test/java/org/elasticsearch/xpack/security/cli}/CertificateToolTests.java (98%) diff --git a/distribution/archives/build.gradle b/distribution/archives/build.gradle index 3c6780cba84e9..0269e4399ce37 100644 --- a/distribution/archives/build.gradle +++ b/distribution/archives/build.gradle @@ -49,7 +49,7 @@ CopySpec archiveFiles(CopySpec modulesFiles, String distributionType, boolean os return copySpec { into("elasticsearch-${version}") { into('lib') { - with libFiles + with libFiles(oss) } into('config') { dirMode 0750 diff --git a/distribution/build.gradle b/distribution/build.gradle index f690cd1aabcea..675799c5b22de 100644 --- a/distribution/build.gradle +++ b/distribution/build.gradle @@ -227,20 +227,24 @@ configure(subprojects.findAll { ['archives', 'packages'].contains(it.name) }) { /***************************************************************************** * Common files in all distributions * *****************************************************************************/ - libFiles = copySpec { - // delay by using closures, since they have not yet been configured, so no jar task exists yet - from { project(':server').jar } - from { project(':server').configurations.runtime } - from { project(':libs:plugin-classloader').jar } - from { project(':distribution:tools:java-version-checker').jar } - from { project(':distribution:tools:launchers').jar } - into('tools/plugin-cli') { - from { project(':distribution:tools:plugin-cli').jar } - from { project(':distribution:tools:plugin-cli').configurations.runtime } - } - into('tools/security-cli') { - from { project(':x-pack:plugin:security:cli').jar } - from { project(':x-pack:plugin:security:cli').configurations.compile } + libFiles = { oss -> + copySpec { + // delay by using closures, since they have not yet been configured, so no jar task exists yet + from { project(':server').jar } + from { project(':server').configurations.runtime } + from { project(':libs:plugin-classloader').jar } + from { project(':distribution:tools:java-version-checker').jar } + from { project(':distribution:tools:launchers').jar } + into('tools/plugin-cli') { + from { project(':distribution:tools:plugin-cli').jar } + from { project(':distribution:tools:plugin-cli').configurations.runtime } + } + if (oss == false) { + into('tools/security-cli') { + from { project(':x-pack:plugin:security:cli').jar } + from { project(':x-pack:plugin:security:cli').configurations.compile } + } + } } } diff --git a/distribution/packages/build.gradle b/distribution/packages/build.gradle index 04fa6313c0a23..fcd69138da328 100644 --- a/distribution/packages/build.gradle +++ b/distribution/packages/build.gradle @@ -126,7 +126,7 @@ Closure commonPackageConfig(String type, boolean oss) { } into('lib') { with copySpec { - with libFiles + with libFiles(oss) // we need to specify every intermediate directory so we iterate through the parents; duplicate calls with the same part are fine eachFile { FileCopyDetails fcp -> String[] segments = fcp.relativePath.segments diff --git a/x-pack/plugin/core/build.gradle b/x-pack/plugin/core/build.gradle index 7430f403dbed5..9cf04dddc96eb 100644 --- a/x-pack/plugin/core/build.gradle +++ b/x-pack/plugin/core/build.gradle @@ -35,8 +35,6 @@ dependencies { // security deps compile 'com.unboundid:unboundid-ldapsdk:3.2.0' - compileOnly 'org.bouncycastle:bcprov-jdk15on:1.59' - compileOnly 'org.bouncycastle:bcpkix-jdk15on:1.59' compile project(path: ':modules:transport-netty4', configuration: 'runtime') testCompile 'org.elasticsearch:securemock:1.2' diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertParsingUtils.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertParsingUtils.java index 1617a92b550ac..6503f686b64f1 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertParsingUtils.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertParsingUtils.java @@ -63,7 +63,7 @@ static Path resolvePath(String path, @Nullable Environment environment) { return PathUtils.get(path).normalize(); } - static KeyStore readKeyStore(Path path, String type, char[] password) + public static KeyStore readKeyStore(Path path, String type, char[] password) throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException { try (InputStream in = Files.newInputStream(path)) { KeyStore store = KeyStore.getInstance(type); @@ -108,7 +108,7 @@ public static X509Certificate[] readX509Certificates(List certPaths) throw return certificates.toArray(new X509Certificate[0]); } - static List readCertificates(InputStream input) throws CertificateException, IOException { + public static List readCertificates(InputStream input) throws CertificateException, IOException { CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); Collection certificates = (Collection) certFactory.generateCertificates(input); return new ArrayList<>(certificates); @@ -140,7 +140,7 @@ public static Map readPkcs12KeyPairs(Path path, char[] passwor /** * Creates a {@link KeyStore} from a PEM encoded certificate and key file */ - static KeyStore getKeyStoreFromPEM(Path certificatePath, Path keyPath, char[] keyPassword) + public static KeyStore getKeyStoreFromPEM(Path certificatePath, Path keyPath, char[] keyPassword) throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException { final PrivateKey key = PemUtils.readPrivateKey(keyPath, () -> keyPassword); final Certificate[] certificates = readCertificates(Collections.singletonList(certificatePath)); @@ -168,7 +168,7 @@ private static KeyStore getKeyStore(Certificate[] certificateChain, PrivateKey p /** * Returns a {@link X509ExtendedKeyManager} that is built from the provided keystore */ - static X509ExtendedKeyManager keyManager(KeyStore keyStore, char[] password, String algorithm) + public static X509ExtendedKeyManager keyManager(KeyStore keyStore, char[] password, String algorithm) throws NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException { KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm); kmf.init(keyStore, password); @@ -271,7 +271,7 @@ public static X509ExtendedTrustManager trustManager(String trustStorePath, Strin /** * Creates a {@link X509ExtendedTrustManager} based on the trust material in the provided {@link KeyStore} */ - static X509ExtendedTrustManager trustManager(KeyStore keyStore, String algorithm) + public static X509ExtendedTrustManager trustManager(KeyStore keyStore, String algorithm) throws NoSuchAlgorithmException, KeyStoreException { TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm); tmf.init(keyStore); diff --git a/x-pack/plugin/security/build.gradle b/x-pack/plugin/security/build.gradle index 854b01659541a..3d646b72c88ab 100644 --- a/x-pack/plugin/security/build.gradle +++ b/x-pack/plugin/security/build.gradle @@ -22,8 +22,6 @@ dependencies { testCompile project(path: xpackModule('core'), configuration: 'testArtifacts') compile 'com.unboundid:unboundid-ldapsdk:3.2.0' - compileOnly 'org.bouncycastle:bcprov-jdk15on:1.59' - compileOnly 'org.bouncycastle:bcpkix-jdk15on:1.59' // the following are all SAML dependencies - might as well download the whole internet compile "org.opensaml:opensaml-core:3.3.0" diff --git a/x-pack/plugin/security/cli/build.gradle b/x-pack/plugin/security/cli/build.gradle index 148c84f1c1fc1..3a23712abe8a0 100644 --- a/x-pack/plugin/security/cli/build.gradle +++ b/x-pack/plugin/security/cli/build.gradle @@ -1,22 +1,20 @@ apply plugin: 'elasticsearch.build' archivesBaseName = 'elasticsearch-security-cli' + dependencies { compileOnly "org.elasticsearch:elasticsearch:${version}" + compileOnly xpackProject('plugin:core') compile 'org.bouncycastle:bcprov-jdk15on:1.59' compile 'org.bouncycastle:bcpkix-jdk15on:1.59' -} - -jar { - from(project(':x-pack:plugin:core').sourceSets.main.output.classesDirs) { - include 'org/elasticsearch/xpack/core/ssl/CertificateTool.class' - include 'org/elasticsearch/xpack/core/ssl/CertificateGenerateTool.class' - include 'org/elasticsearch/xpack/core/ssl/CertGenUtils.class' - } + testCompile 'com.google.jimfs:jimfs:1.1' + testCompile "junit:junit:${versions.junit}" + testCompile "org.hamcrest:hamcrest-all:${versions.hamcrest}" + testCompile 'org.elasticsearch:securemock:1.2' + testCompile("org.elasticsearch.test:framework:${version}") + testCompile project(path: xpackModule('core'), configuration: 'testArtifacts') } dependencyLicenses { mapping from: /bc.*/, to: 'bouncycastle' -} - -licenseHeaders.enabled = false \ No newline at end of file +} \ No newline at end of file diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertGenUtils.java b/x-pack/plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/CertGenUtils.java similarity index 93% rename from x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertGenUtils.java rename to x-pack/plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/CertGenUtils.java index 6273456aca2cd..0b88f3da40a14 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertGenUtils.java +++ b/x-pack/plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/CertGenUtils.java @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.core.ssl; +package org.elasticsearch.xpack.security.cli; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1ObjectIdentifier; @@ -78,7 +78,7 @@ private CertGenUtils() { * Generates a CA certificate */ public static X509Certificate generateCACertificate(X500Principal x500Principal, KeyPair keyPair, int days) - throws OperatorCreationException, CertificateException, CertIOException, NoSuchAlgorithmException { + throws OperatorCreationException, CertificateException, CertIOException, NoSuchAlgorithmException { return generateSignedCertificate(x500Principal, null, keyPair, null, null, true, days, null); } @@ -100,7 +100,7 @@ public static X509Certificate generateCACertificate(X500Principal x500Principal, */ public static X509Certificate generateSignedCertificate(X500Principal principal, GeneralNames subjectAltNames, KeyPair keyPair, X509Certificate caCert, PrivateKey caPrivKey, int days) - throws OperatorCreationException, CertificateException, CertIOException, NoSuchAlgorithmException { + throws OperatorCreationException, CertificateException, CertIOException, NoSuchAlgorithmException { return generateSignedCertificate(principal, subjectAltNames, keyPair, caCert, caPrivKey, false, days, null); } @@ -125,7 +125,7 @@ public static X509Certificate generateSignedCertificate(X500Principal principal, public static X509Certificate generateSignedCertificate(X500Principal principal, GeneralNames subjectAltNames, KeyPair keyPair, X509Certificate caCert, PrivateKey caPrivKey, int days, String signatureAlgorithm) - throws OperatorCreationException, CertificateException, CertIOException, NoSuchAlgorithmException { + throws OperatorCreationException, CertificateException, CertIOException, NoSuchAlgorithmException { return generateSignedCertificate(principal, subjectAltNames, keyPair, caCert, caPrivKey, false, days, signatureAlgorithm); } @@ -150,7 +150,7 @@ public static X509Certificate generateSignedCertificate(X500Principal principal, private static X509Certificate generateSignedCertificate(X500Principal principal, GeneralNames subjectAltNames, KeyPair keyPair, X509Certificate caCert, PrivateKey caPrivKey, boolean isCa, int days, String signatureAlgorithm) - throws NoSuchAlgorithmException, CertificateException, CertIOException, OperatorCreationException { + throws NoSuchAlgorithmException, CertificateException, CertIOException, OperatorCreationException { Objects.requireNonNull(keyPair, "Key-Pair must not be null"); final DateTime notBefore = new DateTime(DateTimeZone.UTC); if (days < 1) { @@ -175,8 +175,8 @@ private static X509Certificate generateSignedCertificate(X500Principal principal } JcaX509v3CertificateBuilder builder = - new JcaX509v3CertificateBuilder(issuer, serial, - new Time(notBefore.toDate(), Locale.ROOT), new Time(notAfter.toDate(), Locale.ROOT), subject, keyPair.getPublic()); + new JcaX509v3CertificateBuilder(issuer, serial, + new Time(notBefore.toDate(), Locale.ROOT), new Time(notAfter.toDate(), Locale.ROOT), subject, keyPair.getPublic()); builder.addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(keyPair.getPublic())); builder.addExtension(Extension.authorityKeyIdentifier, false, authorityKeyIdentifier); @@ -187,8 +187,8 @@ private static X509Certificate generateSignedCertificate(X500Principal principal PrivateKey signingKey = caPrivKey != null ? caPrivKey : keyPair.getPrivate(); ContentSigner signer = new JcaContentSignerBuilder( - (Strings.isNullOrEmpty(signatureAlgorithm)) ? getDefaultSignatureAlgorithm(signingKey) : signatureAlgorithm) - .setProvider(CertGenUtils.BC_PROV).build(signingKey); + (Strings.isNullOrEmpty(signatureAlgorithm)) ? getDefaultSignatureAlgorithm(signingKey) : signatureAlgorithm) + .setProvider(CertGenUtils.BC_PROV).build(signingKey); X509CertificateHolder certificateHolder = builder.build(signer); return new JcaX509CertificateConverter().getCertificate(certificateHolder); } @@ -214,7 +214,7 @@ private static String getDefaultSignatureAlgorithm(PrivateKey key) { break; default: throw new IllegalArgumentException("Unsupported algorithm : " + key.getAlgorithm() - + " for signature, allowed values for private key algorithm are [RSA, DSA, EC]"); + + " for signature, allowed values for private key algorithm are [RSA, DSA, EC]"); } return signatureAlgorithm; } @@ -229,7 +229,7 @@ private static String getDefaultSignatureAlgorithm(PrivateKey key) { * @return a certificate signing request */ static PKCS10CertificationRequest generateCSR(KeyPair keyPair, X500Principal principal, GeneralNames sanList) - throws IOException, OperatorCreationException { + throws IOException, OperatorCreationException { Objects.requireNonNull(keyPair, "Key-Pair must not be null"); Objects.requireNonNull(keyPair.getPublic(), "Public-Key must not be null"); Objects.requireNonNull(principal, "Principal must not be null"); diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertificateGenerateTool.java b/x-pack/plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/CertificateGenerateTool.java similarity index 90% rename from x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertificateGenerateTool.java rename to x-pack/plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/CertificateGenerateTool.java index 5515978c3cab1..809e4a6d30524 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertificateGenerateTool.java +++ b/x-pack/plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/CertificateGenerateTool.java @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.core.ssl; +package org.elasticsearch.xpack.security.cli; import joptsimple.ArgumentAcceptingOptionSpec; import joptsimple.OptionSet; @@ -34,6 +34,8 @@ import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.env.Environment; +import org.elasticsearch.xpack.core.ssl.CertParsingUtils; +import org.elasticsearch.xpack.core.ssl.PemUtils; import javax.security.auth.x500.X500Principal; @@ -68,6 +70,7 @@ /** * CLI tool to make generation of certificates or certificate requests easier for users + * * @deprecated Replaced by {@link CertificateTool} */ @Deprecated @@ -81,7 +84,7 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand { private static final int FILE_EXTENSION_LENGTH = 4; static final int MAX_FILENAME_LENGTH = 255 - FILE_EXTENSION_LENGTH; private static final Pattern ALLOWED_FILENAME_CHAR_PATTERN = - Pattern.compile("[a-zA-Z0-9!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1," + MAX_FILENAME_LENGTH + "}"); + Pattern.compile("[a-zA-Z0-9!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1," + MAX_FILENAME_LENGTH + "}"); private static final int DEFAULT_KEY_SIZE = 2048; private static final BouncyCastleProvider BC_PROV = new BouncyCastleProvider(); @@ -96,11 +99,11 @@ private static class InputFileParser { // of the parser in this class so that we can defer initialization until after logging has been initialized static { @SuppressWarnings("unchecked") final ConstructingObjectParser instanceParser = - new ConstructingObjectParser<>( - "instances", - a -> new CertificateInformation( - (String) a[0], (String) (a[1] == null ? a[0] : a[1]), - (List) a[2], (List) a[3], (List) a[4])); + new ConstructingObjectParser<>( + "instances", + a -> new CertificateInformation( + (String) a[0], (String) (a[1] == null ? a[0] : a[1]), + (List) a[2], (List) a[3], (List) a[4])); instanceParser.declareString(ConstructingObjectParser.constructorArg(), new ParseField("name")); instanceParser.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField("filename")); instanceParser.declareStringArray(ConstructingObjectParser.optionalConstructorArg(), new ParseField("ip")); @@ -125,29 +128,29 @@ private static class InputFileParser { CertificateGenerateTool() { super(DESCRIPTION); outputPathSpec = parser.accepts("out", "path of the zip file that the output should be written to") - .withRequiredArg(); + .withRequiredArg(); csrSpec = parser.accepts("csr", "only generate certificate signing requests"); caCertPathSpec = parser.accepts("cert", "path to an existing ca certificate").availableUnless(csrSpec).withRequiredArg(); caKeyPathSpec = parser.accepts("key", "path to an existing ca private key") - .availableIf(caCertPathSpec) - .requiredIf(caCertPathSpec) - .withRequiredArg(); + .availableIf(caCertPathSpec) + .requiredIf(caCertPathSpec) + .withRequiredArg(); caPasswordSpec = parser.accepts("pass", "password for an existing ca private key or the generated ca private key") - .availableUnless(csrSpec) - .withOptionalArg(); + .availableUnless(csrSpec) + .withOptionalArg(); caDnSpec = parser.accepts("dn", "distinguished name to use for the generated ca. defaults to " + AUTO_GEN_CA_DN) - .availableUnless(caCertPathSpec) - .availableUnless(csrSpec) - .withRequiredArg(); + .availableUnless(caCertPathSpec) + .availableUnless(csrSpec) + .withRequiredArg(); keysizeSpec = parser.accepts("keysize", "size in bits of RSA keys").withRequiredArg().ofType(Integer.class); inputFileSpec = parser.accepts("in", "file containing details of the instances in yaml format").withRequiredArg(); daysSpec = parser.accepts("days", "number of days that the generated certificates are valid") - .availableUnless(csrSpec) - .withRequiredArg() - .ofType(Integer.class); + .availableUnless(csrSpec) + .withRequiredArg() + .ofType(Integer.class); p12Spec = parser.accepts("p12", "output a p12 (PKCS#12) version for each certificate/key pair, with optional password") - .availableUnless(csrSpec) - .withOptionalArg(); + .availableUnless(csrSpec) + .withOptionalArg(); } public static void main(String[] args) throws Exception { @@ -178,7 +181,7 @@ protected void execute(Terminal terminal, OptionSet options, Environment env) th p12Password = null; } CAInfo caInfo = getCAInfo(terminal, dn, caCertPathSpec.value(options), caKeyPathSpec.value(options), keyPass, prompt, env, - keysize, days); + keysize, days); Collection certificateInformations = getCertificateInformationList(terminal, inputFile); generateAndWriteSignedCertificates(outputFile, certificateInformations, caInfo, keysize, days, p12Password); } @@ -197,7 +200,7 @@ protected void printAdditionalHelp(Terminal terminal) { /** * Checks for output file in the user specified options or prompts the user for the output file * - * @param terminal terminal to communicate with a user + * @param terminal terminal to communicate with a user * @param outputPath user specified output file, may be {@code null} * @return a {@link Path} to the output file */ @@ -223,12 +226,13 @@ private static Path resolvePath(String pathStr) { /** * This method handles the collection of information about each instance that is necessary to generate a certificate. The user may * be prompted or the information can be gathered from a file - * @param terminal the terminal to use for user interaction + * + * @param terminal the terminal to use for user interaction * @param inputFile an optional file that will be used to load the instance information * @return a {@link Collection} of {@link CertificateInformation} that represents each instance */ static Collection getCertificateInformationList(Terminal terminal, String inputFile) - throws Exception { + throws Exception { if (inputFile != null) { return parseAndValidateFile(terminal, resolvePath(inputFile).toAbsolutePath()); } @@ -239,7 +243,7 @@ static Collection getCertificateInformationList(Terminal if (name.isEmpty() == false) { final boolean isNameValidFilename = Name.isValidFilename(name); String filename = terminal.readText("Enter name for directories and files " + (isNameValidFilename ? "[" + name + "]" : "") - + ": " ); + + ": "); if (filename.isEmpty() && isNameValidFilename) { filename = name; } @@ -267,7 +271,7 @@ static Collection getCertificateInformationList(Terminal } String exit = terminal.readText("Would you like to specify another instance? Press 'y' to continue entering instance " + - "information: "); + "information: "); if ("y".equals(exit) == false) { done = true; } @@ -283,7 +287,7 @@ static Collection parseAndValidateFile(Terminal terminal if (errors.size() > 0) { hasError = true; terminal.println(Terminal.Verbosity.SILENT, "Configuration for instance " + certInfo.name.originalName - + " has invalid details"); + + " has invalid details"); for (String message : errors) { terminal.println(Terminal.Verbosity.SILENT, " * " + message); } @@ -298,6 +302,7 @@ static Collection parseAndValidateFile(Terminal terminal /** * Parses the input file to retrieve the certificate information + * * @param file the file to parse * @return a collection of certificate information */ @@ -305,22 +310,23 @@ static Collection parseFile(Path file) throws Exception try (Reader reader = Files.newBufferedReader(file)) { // EMPTY is safe here because we never use namedObject XContentParser xContentParser = XContentType.YAML.xContent() - .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, reader); + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, reader); return InputFileParser.PARSER.parse(xContentParser, new ArrayList<>(), null); } } /** * Generates certificate signing requests and writes them out to the specified file in zip format + * * @param outputFile the file to write the output to. This file must not already exist - * @param certInfo the details to use in the certificate signing requests + * @param certInfo the details to use in the certificate signing requests */ static void generateAndWriteCsrs(Path outputFile, Collection certInfo, int keysize) throws Exception { fullyWriteFile(outputFile, (outputStream, pemWriter) -> { for (CertificateInformation certificateInformation : certInfo) { KeyPair keyPair = CertGenUtils.generateKeyPair(keysize); GeneralNames sanList = getSubjectAlternativeNamesValue(certificateInformation.ipAddresses, certificateInformation.dnsNames, - certificateInformation.commonNames); + certificateInformation.commonNames); PKCS10CertificationRequest csr = CertGenUtils.generateCSR(keyPair, certificateInformation.name.x500Principal, sanList); final String dirName = certificateInformation.name.filename + "/"; @@ -347,15 +353,15 @@ static void generateAndWriteCsrs(Path outputFile, Collection certificateInformations, CAInfo caInfo, int keysize, int days, char[] pkcs12Password) throws Exception { @@ -403,9 +410,9 @@ static void generateAndWriteSignedCertificates(Path outputFile, Collection passwordReference = new AtomicReference<>(password); try { return PemUtils.readPrivateKey(resolvePath(path), () -> { @@ -682,7 +692,7 @@ static Name fromUserProvidedName(String name, String filename) { } } catch (IllegalArgumentException e) { String error = "[" + name + "] could not be converted to a valid DN\n" + e.getMessage() + "\n" - + ExceptionsHelper.stackTrace(e); + + ExceptionsHelper.stackTrace(e); return new Name(name, null, null, error); } @@ -695,15 +705,15 @@ static Name fromUserProvidedName(String name, String filename) { static boolean isValidFilename(String name) { return ALLOWED_FILENAME_CHAR_PATTERN.matcher(name).matches() - && ALLOWED_FILENAME_CHAR_PATTERN.matcher(resolvePath(name).toString()).matches() - && name.startsWith(".") == false; + && ALLOWED_FILENAME_CHAR_PATTERN.matcher(resolvePath(name).toString()).matches() + && name.startsWith(".") == false; } @Override public String toString() { return getClass().getSimpleName() - + "{original=[" + originalName + "] principal=[" + x500Principal - + "] file=[" + filename + "] err=[" + error + "]}"; + + "{original=[" + originalName + "] principal=[" + x500Principal + + "] file=[" + filename + "] err=[" + error + "]}"; } } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertificateTool.java b/x-pack/plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/CertificateTool.java similarity index 92% rename from x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertificateTool.java rename to x-pack/plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/CertificateTool.java index dd90df4dd6a38..a966cac9109d9 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertificateTool.java +++ b/x-pack/plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/CertificateTool.java @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.core.ssl; +package org.elasticsearch.xpack.security.cli; import joptsimple.OptionParser; import joptsimple.OptionSet; @@ -39,6 +39,8 @@ import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.env.Environment; +import org.elasticsearch.xpack.core.ssl.CertParsingUtils; +import org.elasticsearch.xpack.core.ssl.PemUtils; import javax.security.auth.x500.X500Principal; @@ -101,7 +103,7 @@ public class CertificateTool extends LoggingAwareMultiCommand { private static final int FILE_EXTENSION_LENGTH = 4; static final int MAX_FILENAME_LENGTH = 255 - FILE_EXTENSION_LENGTH; private static final Pattern ALLOWED_FILENAME_CHAR_PATTERN = - Pattern.compile("[a-zA-Z0-9!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1," + MAX_FILENAME_LENGTH + "}"); + Pattern.compile("[a-zA-Z0-9!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1," + MAX_FILENAME_LENGTH + "}"); private static final int DEFAULT_KEY_SIZE = 2048; /** @@ -115,11 +117,11 @@ private static class CertificateToolParser { // of the parser in this class so that we can defer initialization until after logging has been initialized static { @SuppressWarnings("unchecked") final ConstructingObjectParser instanceParser = - new ConstructingObjectParser<>( - "instances", - a -> new CertificateInformation( - (String) a[0], (String) (a[1] == null ? a[0] : a[1]), - (List) a[2], (List) a[3], (List) a[4])); + new ConstructingObjectParser<>( + "instances", + a -> new CertificateInformation( + (String) a[0], (String) (a[1] == null ? a[0] : a[1]), + (List) a[2], (List) a[3], (List) a[4])); instanceParser.declareString(ConstructingObjectParser.constructorArg(), new ParseField("name")); instanceParser.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField("filename")); instanceParser.declareStringArray(ConstructingObjectParser.optionalConstructorArg(), new ParseField("ip")); @@ -144,28 +146,28 @@ public static void main(String[] args) throws Exception { static final String INTRO_TEXT = "This tool assists you in the generation of X.509 certificates and certificate\n" + - "signing requests for use with SSL/TLS in the Elastic stack."; + "signing requests for use with SSL/TLS in the Elastic stack."; static final String INSTANCE_EXPLANATION = - " * An instance is any piece of the Elastic Stack that requires a SSL certificate.\n" + - " Depending on your configuration, Elasticsearch, Logstash, Kibana, and Beats\n" + - " may all require a certificate and private key.\n" + - " * The minimum required value for each instance is a name. This can simply be the\n" + - " hostname, which will be used as the Common Name of the certificate. A full\n" + - " distinguished name may also be used.\n" + - " * A filename value may be required for each instance. This is necessary when the\n" + - " name would result in an invalid file or directory name. The name provided here\n" + - " is used as the directory name (within the zip) and the prefix for the key and\n" + - " certificate files. The filename is required if you are prompted and the name\n" + - " is not displayed in the prompt.\n" + - " * IP addresses and DNS names are optional. Multiple values can be specified as a\n" + - " comma separated string. If no IP addresses or DNS names are provided, you may\n" + - " disable hostname verification in your SSL configuration."; + " * An instance is any piece of the Elastic Stack that requires a SSL certificate.\n" + + " Depending on your configuration, Elasticsearch, Logstash, Kibana, and Beats\n" + + " may all require a certificate and private key.\n" + + " * The minimum required value for each instance is a name. This can simply be the\n" + + " hostname, which will be used as the Common Name of the certificate. A full\n" + + " distinguished name may also be used.\n" + + " * A filename value may be required for each instance. This is necessary when the\n" + + " name would result in an invalid file or directory name. The name provided here\n" + + " is used as the directory name (within the zip) and the prefix for the key and\n" + + " certificate files. The filename is required if you are prompted and the name\n" + + " is not displayed in the prompt.\n" + + " * IP addresses and DNS names are optional. Multiple values can be specified as a\n" + + " comma separated string. If no IP addresses or DNS names are provided, you may\n" + + " disable hostname verification in your SSL configuration."; static final String CA_EXPLANATION = - " * All certificates generated by this tool will be signed by a certificate authority (CA).\n" + - " * The tool can automatically generate a new CA for you, or you can provide your own with the\n" + - " -ca or -ca-cert command line options."; + " * All certificates generated by this tool will be signed by a certificate authority (CA).\n" + + " * The tool can automatically generate a new CA for you, or you can provide your own with the\n" + + " -ca or -ca-cert command line options."; abstract static class CertificateCommand extends EnvironmentAwareCommand { @@ -202,32 +204,32 @@ abstract static class CertificateCommand extends EnvironmentAwareCommand { final void acceptCertificateGenerationOptions() { pemFormatSpec = parser.accepts("pem", "output certificates and keys in PEM format instead of PKCS#12"); daysSpec = parser.accepts("days", "number of days that the generated certificates are valid") - .withRequiredArg().ofType(Integer.class); + .withRequiredArg().ofType(Integer.class); } final void acceptsCertificateAuthority() { caPkcs12PathSpec = parser.accepts("ca", "path to an existing ca key pair (in PKCS#12 format)").withRequiredArg(); caCertPathSpec = parser.accepts("ca-cert", "path to an existing ca certificate") - .availableUnless(caPkcs12PathSpec) - .withRequiredArg(); + .availableUnless(caPkcs12PathSpec) + .withRequiredArg(); caKeyPathSpec = parser.accepts("ca-key", "path to an existing ca private key") - .availableIf(caCertPathSpec) - .requiredIf(caCertPathSpec) - .withRequiredArg(); + .availableIf(caCertPathSpec) + .requiredIf(caCertPathSpec) + .withRequiredArg(); keepCaKeySpec = parser.accepts("keep-ca-key", "retain the CA private key for future use") - .availableUnless(caPkcs12PathSpec) - .availableUnless(caCertPathSpec); + .availableUnless(caPkcs12PathSpec) + .availableUnless(caCertPathSpec); caPasswordSpec = parser.accepts("ca-pass", "password for an existing ca private key or the generated ca private key") - .withOptionalArg(); + .withOptionalArg(); acceptsCertificateAuthorityName(); } void acceptsCertificateAuthorityName() { OptionSpecBuilder builder = parser.accepts("ca-dn", - "distinguished name to use for the generated ca. defaults to " + AUTO_GEN_CA_DN); + "distinguished name to use for the generated ca. defaults to " + AUTO_GEN_CA_DN); if (caPkcs12PathSpec != null) { builder = builder.availableUnless(caPkcs12PathSpec); } @@ -336,11 +338,11 @@ private CAInfo loadPkcs12CA(Terminal terminal, OptionSet options, Environment en char[] passwordOption = getChars(caPasswordSpec.value(options)); Map keys = withPassword("CA (" + path + ")", passwordOption, - terminal, password -> CertParsingUtils.readPkcs12KeyPairs(path, password, a -> password)); + terminal, password -> CertParsingUtils.readPkcs12KeyPairs(path, password, a -> password)); if (keys.size() != 1) { throw new IllegalArgumentException("expected a single key in file [" + path.toAbsolutePath() + "] but found [" + - keys.size() + "]"); + keys.size() + "]"); } final Map.Entry pair = keys.entrySet().iterator().next(); return new CAInfo((X509Certificate) pair.getKey(), (PrivateKey) pair.getValue()); @@ -358,7 +360,7 @@ private CAInfo loadPemCA(Terminal terminal, OptionSet options, Environment env) Certificate[] certificates = CertParsingUtils.readCertificates(Collections.singletonList(resolvedCaCertPath), env); if (certificates.length != 1) { throw new IllegalArgumentException("expected a single certificate in file [" + resolvedCaCertPath + "] but found [" + - certificates.length + "]"); + certificates.length + "]"); } X509Certificate caCert = (X509Certificate) certificates[0]; PrivateKey privateKey = readPrivateKey(key, getChars(password), terminal); @@ -391,7 +393,7 @@ CAInfo generateCA(Terminal terminal, OptionSet options) throws Exception { * @return a {@link Collection} of {@link CertificateInformation} that represents each instance */ Collection getCertificateInformationList(Terminal terminal, OptionSet options) - throws Exception { + throws Exception { final Path input = resolvePath(options, inputFileSpec); if (input != null) { return parseAndValidateFile(terminal, input.toAbsolutePath()); @@ -456,7 +458,7 @@ static Collection readMultipleCertificateInformation(Ter } String exit = terminal.readText("Would you like to specify another instance? Press 'y' to continue entering instance " + - "information: "); + "information: "); if ("y".equals(exit) == false) { done = true; } @@ -468,7 +470,7 @@ private static String requestFileName(Terminal terminal, String certName) { final boolean isNameValidFilename = Name.isValidFilename(certName); while (true) { String filename = terminal.readText("Enter name for directories and files of " + certName + - (isNameValidFilename ? " [" + certName + "]" : "") + ": "); + (isNameValidFilename ? " [" + certName + "]" : "") + ": "); if (filename.isEmpty() && isNameValidFilename) { return certName; } @@ -490,7 +492,7 @@ private static String requestFileName(Terminal terminal, String certName) { * @param includeKey if true, write the CA key in PEM format */ static void writeCAInfo(ZipOutputStream outputStream, JcaPEMWriter pemWriter, CAInfo info, boolean includeKey) - throws Exception { + throws Exception { final String caDirName = createCaDirectory(outputStream); outputStream.putNextEntry(new ZipEntry(caDirName + "ca.crt")); pemWriter.writeObject(info.certAndKey.cert); @@ -546,7 +548,7 @@ static void writePkcs12(String fileName, OutputStream output, String alias, Cert pkcs12.load(null); withPassword(fileName, password, terminal, p12Password -> { if (isAscii(p12Password)) { - pkcs12.setKeyEntry(alias, pair.key, p12Password, new Certificate[] { pair.cert }); + pkcs12.setKeyEntry(alias, pair.key, p12Password, new Certificate[]{pair.cert}); if (caCert != null) { pkcs12.setCertificateEntry("ca", caCert); } @@ -574,7 +576,7 @@ protected void execute(Terminal terminal, OptionSet options, Environment env) th terminal.println("The 'csr' mode generates certificate signing requests that can be sent to"); terminal.println("a trusted certificate authority"); terminal.println(" * By default, this generates a single CSR for a single instance."); - terminal.println(" * You can use the '-multiple' option to generate CSRs for multiple" ); + terminal.println(" * You can use the '-multiple' option to generate CSRs for multiple"); terminal.println(" instances, each with their own private key."); terminal.println(" * The '-in' option allows for the CSR generation to be automated"); terminal.println(" by describing the details of each instance in a YAML file"); @@ -616,7 +618,7 @@ void generateAndWriteCsrs(Path output, int keySize, Collection certs, CAInfo caInfo, Terminal terminal) - throws Exception { + throws Exception { checkDirectory(output, terminal); @@ -805,7 +807,7 @@ void generateAndWriteSignedCertificates(Path output, boolean writeZipFile, Optio final String fileName = entryBase + ".p12"; outputStream.putNextEntry(new ZipEntry(fileName)); writePkcs12(fileName, outputStream, certificateInformation.name.originalName, pair, caInfo.certAndKey.cert, - outputPassword, terminal); + outputPassword, terminal); outputStream.closeEntry(); } } @@ -815,7 +817,7 @@ void generateAndWriteSignedCertificates(Path output, boolean writeZipFile, Optio CertificateInformation certificateInformation = certs.iterator().next(); CertificateAndKey pair = generateCertificateAndKey(certificateInformation, caInfo, keySize, days); fullyWriteFile(output, stream -> writePkcs12(output.getFileName().toString(), stream, - certificateInformation.name.originalName, pair, caInfo.certAndKey.cert, outputPassword, terminal)); + certificateInformation.name.originalName, pair, caInfo.certAndKey.cert, outputPassword, terminal)); } } @@ -823,9 +825,9 @@ private CertificateAndKey generateCertificateAndKey(CertificateInformation certi int keySize, int days) throws Exception { KeyPair keyPair = CertGenUtils.generateKeyPair(keySize); Certificate certificate = CertGenUtils.generateSignedCertificate(certificateInformation.name.x500Principal, - getSubjectAlternativeNamesValue(certificateInformation.ipAddresses, certificateInformation.dnsNames, - certificateInformation.commonNames), - keyPair, caInfo.certAndKey.cert, caInfo.certAndKey.key, days); + getSubjectAlternativeNamesValue(certificateInformation.ipAddresses, certificateInformation.dnsNames, + certificateInformation.commonNames), + keyPair, caInfo.certAndKey.cert, caInfo.certAndKey.key, days); return new CertificateAndKey((X509Certificate) certificate, keyPair.getPrivate()); } @@ -872,7 +874,7 @@ private void writeCertificateAuthority(Path output, CAInfo caInfo, boolean write } else { final String fileName = output.getFileName().toString(); fullyWriteFile(output, outputStream -> - writePkcs12(fileName, outputStream, "ca", caInfo.certAndKey, null, caInfo.password, terminal)); + writePkcs12(fileName, outputStream, "ca", caInfo.certAndKey, null, caInfo.password, terminal)); } } } @@ -912,7 +914,7 @@ static Collection parseFile(Path file) throws Exception try (Reader reader = Files.newBufferedReader(file)) { // EMPTY is safe here because we never use namedObject XContentParser xContentParser = XContentType.YAML.xContent() - .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, reader); + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, reader); return CertificateToolParser.PARSER.parse(xContentParser, new ArrayList<>(), null); } } @@ -1015,7 +1017,7 @@ private static void fullyWriteFile(Path file, CheckedConsumer passwordReference = new AtomicReference<>(password); try { return PemUtils.readPrivateKey(path, () -> { @@ -1125,7 +1127,7 @@ static Name fromUserProvidedName(String name, String filename) { } } catch (IllegalArgumentException e) { String error = "[" + name + "] could not be converted to a valid DN\n" + e.getMessage() + "\n" - + ExceptionsHelper.stackTrace(e); + + ExceptionsHelper.stackTrace(e); return new Name(name, null, null, error); } @@ -1138,15 +1140,15 @@ static Name fromUserProvidedName(String name, String filename) { static boolean isValidFilename(String name) { return ALLOWED_FILENAME_CHAR_PATTERN.matcher(name).matches() - && ALLOWED_FILENAME_CHAR_PATTERN.matcher(resolvePath(name).toString()).matches() - && name.startsWith(".") == false; + && ALLOWED_FILENAME_CHAR_PATTERN.matcher(resolvePath(name).toString()).matches() + && name.startsWith(".") == false; } @Override public String toString() { return getClass().getSimpleName() - + "{original=[" + originalName + "] principal=[" + x500Principal - + "] file=[" + filename + "] err=[" + error + "]}"; + + "{original=[" + originalName + "] principal=[" + x500Principal + + "] file=[" + filename + "] err=[" + error + "]}"; } } diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/CertGenUtilsTests.java b/x-pack/plugin/security/cli/src/test/java/org/elasticsearch/xpack/security/cli/CertGenUtilsTests.java similarity index 97% rename from x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/CertGenUtilsTests.java rename to x-pack/plugin/security/cli/src/test/java/org/elasticsearch/xpack/security/cli/CertGenUtilsTests.java index 20259144b420b..bb1ed014b9c17 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/CertGenUtilsTests.java +++ b/x-pack/plugin/security/cli/src/test/java/org/elasticsearch/xpack/security/cli/CertGenUtilsTests.java @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.core.ssl; +package org.elasticsearch.xpack.security.cli; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.asn1.x509.GeneralNames; @@ -12,6 +12,7 @@ import org.elasticsearch.common.network.InetAddresses; import org.elasticsearch.common.network.NetworkAddress; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.security.cli.CertGenUtils; import org.junit.BeforeClass; import java.math.BigInteger; diff --git a/x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/core/ssl/CertificateGenerateToolTests.java b/x-pack/plugin/security/cli/src/test/java/org/elasticsearch/xpack/security/cli/CertificateGenerateToolTests.java similarity index 98% rename from x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/core/ssl/CertificateGenerateToolTests.java rename to x-pack/plugin/security/cli/src/test/java/org/elasticsearch/xpack/security/cli/CertificateGenerateToolTests.java index dde0b7645df13..164249ed2db00 100644 --- a/x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/core/ssl/CertificateGenerateToolTests.java +++ b/x-pack/plugin/security/cli/src/test/java/org/elasticsearch/xpack/security/cli/CertificateGenerateToolTests.java @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.core.ssl; +package org.elasticsearch.xpack.security.cli; import com.google.common.jimfs.Configuration; import com.google.common.jimfs.Jimfs; @@ -33,9 +33,11 @@ import org.elasticsearch.env.TestEnvironment; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.SecuritySettingsSourceField; -import org.elasticsearch.xpack.core.ssl.CertificateGenerateTool.CAInfo; -import org.elasticsearch.xpack.core.ssl.CertificateGenerateTool.CertificateInformation; -import org.elasticsearch.xpack.core.ssl.CertificateGenerateTool.Name; +import org.elasticsearch.xpack.security.cli.CertificateGenerateTool.CAInfo; +import org.elasticsearch.xpack.security.cli.CertificateGenerateTool.CertificateInformation; +import org.elasticsearch.xpack.security.cli.CertificateGenerateTool.Name; +import org.elasticsearch.xpack.core.ssl.CertParsingUtils; +import org.elasticsearch.xpack.core.ssl.PemUtils; import org.hamcrest.Matchers; import org.junit.After; import org.junit.BeforeClass; diff --git a/x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/core/ssl/CertificateToolTests.java b/x-pack/plugin/security/cli/src/test/java/org/elasticsearch/xpack/security/cli/CertificateToolTests.java similarity index 98% rename from x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/core/ssl/CertificateToolTests.java rename to x-pack/plugin/security/cli/src/test/java/org/elasticsearch/xpack/security/cli/CertificateToolTests.java index 706d5dbab5f5a..2a5392a2befa2 100644 --- a/x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/core/ssl/CertificateToolTests.java +++ b/x-pack/plugin/security/cli/src/test/java/org/elasticsearch/xpack/security/cli/CertificateToolTests.java @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.core.ssl; +package org.elasticsearch.xpack.security.cli; import com.google.common.jimfs.Configuration; import com.google.common.jimfs.Jimfs; @@ -39,12 +39,14 @@ import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.SecuritySettingsSourceField; import org.elasticsearch.test.TestMatchers; -import org.elasticsearch.xpack.core.ssl.CertificateTool.CAInfo; -import org.elasticsearch.xpack.core.ssl.CertificateTool.CertificateAuthorityCommand; -import org.elasticsearch.xpack.core.ssl.CertificateTool.CertificateCommand; -import org.elasticsearch.xpack.core.ssl.CertificateTool.CertificateInformation; -import org.elasticsearch.xpack.core.ssl.CertificateTool.GenerateCertificateCommand; -import org.elasticsearch.xpack.core.ssl.CertificateTool.Name; +import org.elasticsearch.xpack.security.cli.CertificateTool.CAInfo; +import org.elasticsearch.xpack.security.cli.CertificateTool.CertificateAuthorityCommand; +import org.elasticsearch.xpack.security.cli.CertificateTool.CertificateCommand; +import org.elasticsearch.xpack.security.cli.CertificateTool.CertificateInformation; +import org.elasticsearch.xpack.security.cli.CertificateTool.GenerateCertificateCommand; +import org.elasticsearch.xpack.security.cli.CertificateTool.Name; +import org.elasticsearch.xpack.core.ssl.CertParsingUtils; +import org.elasticsearch.xpack.core.ssl.PemUtils; import org.hamcrest.Matchers; import org.junit.After; import org.junit.BeforeClass; From 27286ac498a30c22786f627c08438aaf75c59154 Mon Sep 17 00:00:00 2001 From: Ioannis Kakavas Date: Fri, 20 Jul 2018 01:42:46 +0300 Subject: [PATCH 3/8] Update class package in scripts --- x-pack/plugin/security/src/main/bin/elasticsearch-certgen | 2 +- x-pack/plugin/security/src/main/bin/elasticsearch-certgen.bat | 2 +- x-pack/plugin/security/src/main/bin/elasticsearch-certutil | 2 +- x-pack/plugin/security/src/main/bin/elasticsearch-certutil.bat | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugin/security/src/main/bin/elasticsearch-certgen b/x-pack/plugin/security/src/main/bin/elasticsearch-certgen index b40cde75e38b1..8e88e845e0242 100644 --- a/x-pack/plugin/security/src/main/bin/elasticsearch-certgen +++ b/x-pack/plugin/security/src/main/bin/elasticsearch-certgen @@ -4,7 +4,7 @@ # or more contributor license agreements. Licensed under the Elastic License; # you may not use this file except in compliance with the Elastic License. -ES_MAIN_CLASS=org.elasticsearch.xpack.core.ssl.CertificateGenerateTool \ +ES_MAIN_CLASS=org.elasticsearch.xpack.security.cli.CertificateGenerateTool \ ES_ADDITIONAL_SOURCES="x-pack-env;x-pack-security-env" \ ES_ADDITIONAL_CLASSPATH_DIRECTORIES=lib/tools/security-cli \ "`dirname "$0"`"/elasticsearch-cli \ diff --git a/x-pack/plugin/security/src/main/bin/elasticsearch-certgen.bat b/x-pack/plugin/security/src/main/bin/elasticsearch-certgen.bat index 8ca62b8f54efe..bb303f740e5c3 100644 --- a/x-pack/plugin/security/src/main/bin/elasticsearch-certgen.bat +++ b/x-pack/plugin/security/src/main/bin/elasticsearch-certgen.bat @@ -7,7 +7,7 @@ rem you may not use this file except in compliance with the Elastic License. setlocal enabledelayedexpansion setlocal enableextensions -set ES_MAIN_CLASS=org.elasticsearch.xpack.core.ssl.CertificateGenerateTool +set ES_MAIN_CLASS=org.elasticsearch.xpack.security.cli.CertificateGenerateTool set ES_ADDITIONAL_SOURCES=x-pack-env;x-pack-security-env set ES_ADDITIONAL_CLASSPATH_DIRECTORIES=lib/tools/security-cli call "%~dp0elasticsearch-cli.bat" ^ diff --git a/x-pack/plugin/security/src/main/bin/elasticsearch-certutil b/x-pack/plugin/security/src/main/bin/elasticsearch-certutil index c351be40a80cf..6d94344949b9b 100644 --- a/x-pack/plugin/security/src/main/bin/elasticsearch-certutil +++ b/x-pack/plugin/security/src/main/bin/elasticsearch-certutil @@ -4,7 +4,7 @@ # or more contributor license agreements. Licensed under the Elastic License; # you may not use this file except in compliance with the Elastic License. -ES_MAIN_CLASS=org.elasticsearch.xpack.core.ssl.CertificateTool \ +ES_MAIN_CLASS=org.elasticsearch.xpack.security.cli.CertificateTool \ ES_ADDITIONAL_SOURCES="x-pack-env;x-pack-security-env" \ ES_ADDITIONAL_CLASSPATH_DIRECTORIES=lib/tools/security-cli \ "`dirname "$0"`"/elasticsearch-cli \ diff --git a/x-pack/plugin/security/src/main/bin/elasticsearch-certutil.bat b/x-pack/plugin/security/src/main/bin/elasticsearch-certutil.bat index 83c6bc26cfdeb..34f595824f82d 100644 --- a/x-pack/plugin/security/src/main/bin/elasticsearch-certutil.bat +++ b/x-pack/plugin/security/src/main/bin/elasticsearch-certutil.bat @@ -7,7 +7,7 @@ rem you may not use this file except in compliance with the Elastic License. setlocal enabledelayedexpansion setlocal enableextensions -set ES_MAIN_CLASS=org.elasticsearch.xpack.core.ssl.CertificateTool +set ES_MAIN_CLASS=org.elasticsearch.xpack.security.cli.CertificateTool set ES_ADDITIONAL_SOURCES=x-pack-env;x-pack-security-env set ES_ADDITIONAL_CLASSPATH_DIRECTORIES=lib/tools/security-cli call "%~dp0elasticsearch-cli.bat" ^ From aca04e2f277343d9b893c35a80f52332322569ec Mon Sep 17 00:00:00 2001 From: Ioannis Kakavas Date: Fri, 20 Jul 2018 01:43:07 +0300 Subject: [PATCH 4/8] address feedback --- x-pack/plugin/security/cli/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/security/cli/build.gradle b/x-pack/plugin/security/cli/build.gradle index 3a23712abe8a0..b42759d559329 100644 --- a/x-pack/plugin/security/cli/build.gradle +++ b/x-pack/plugin/security/cli/build.gradle @@ -11,7 +11,7 @@ dependencies { testCompile "junit:junit:${versions.junit}" testCompile "org.hamcrest:hamcrest-all:${versions.hamcrest}" testCompile 'org.elasticsearch:securemock:1.2' - testCompile("org.elasticsearch.test:framework:${version}") + testCompile "org.elasticsearch.test:framework:${version}" testCompile project(path: xpackModule('core'), configuration: 'testArtifacts') } From c40137f0aeec9ecdc599fc4f68f6b56dabe90cbf Mon Sep 17 00:00:00 2001 From: Ioannis Kakavas Date: Fri, 20 Jul 2018 10:23:35 +0300 Subject: [PATCH 5/8] Add packaging test for security cli --- .../packaging/test/ArchiveTestCase.java | 22 +++++++++++++++++++ .../packaging/util/Installation.java | 1 + 2 files changed, 23 insertions(+) diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/ArchiveTestCase.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/ArchiveTestCase.java index 3aada7837d8ae..2056111554225 100644 --- a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/ArchiveTestCase.java +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/ArchiveTestCase.java @@ -57,6 +57,7 @@ import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.isEmptyString; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeThat; import static org.junit.Assume.assumeTrue; @@ -302,5 +303,26 @@ public void test80RelativePathConf() throws IOException { } } + public void test90SecurityCliPackaging() { + assumeThat(installation, is(notNullValue())); + + final Installation.Executables bin = installation.executables(); + final Shell sh = new Shell(); + + if (distribution().equals(Distribution.DEFAULT_TAR) || distribution().equals(Distribution.DEFAULT_ZIP)) { + assertTrue(Files.exists(installation.lib.resolve("tools").resolve("security-cli"))); + Platforms.onLinux(() -> { + final Result result = sh.run(bin.elasticsearchCertutil + " help"); + assertThat(result.stdout, containsString("Simplifies certificate creation for use with the Elastic Stack")); + }); + + Platforms.onWindows(() -> { + final Result result = sh.run(bin.elasticsearchCertutil + " help"); + assertThat(result.stdout, containsString("Simplifies certificate creation for use with the Elastic Stack")); + }); + } else if (distribution().equals(Distribution.OSS_TAR) || distribution().equals(Distribution.OSS_ZIP)) { + assertFalse(Files.exists(installation.lib.resolve("tools").resolve("security-cli"))); + } + } } diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Installation.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Installation.java index 68da440400a36..9dd4b264bd48c 100644 --- a/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Installation.java +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Installation.java @@ -79,6 +79,7 @@ public class Executables { public final Path elasticsearchPlugin = platformExecutable("elasticsearch-plugin"); public final Path elasticsearchKeystore = platformExecutable("elasticsearch-keystore"); public final Path elasticsearchTranslog = platformExecutable("elasticsearch-translog"); + public final Path elasticsearchCertutil = platformExecutable("elasticsearch-certutil"); private Path platformExecutable(String name) { final String platformExecutableName = Platforms.WINDOWS From af5745a76ac74a451b1649e8a93a888172396ad5 Mon Sep 17 00:00:00 2001 From: Ioannis Kakavas Date: Fri, 20 Jul 2018 10:24:21 +0300 Subject: [PATCH 6/8] Reintroduce compileOnly dependency for security --- x-pack/plugin/security/build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/plugin/security/build.gradle b/x-pack/plugin/security/build.gradle index 3d646b72c88ab..854b01659541a 100644 --- a/x-pack/plugin/security/build.gradle +++ b/x-pack/plugin/security/build.gradle @@ -22,6 +22,8 @@ dependencies { testCompile project(path: xpackModule('core'), configuration: 'testArtifacts') compile 'com.unboundid:unboundid-ldapsdk:3.2.0' + compileOnly 'org.bouncycastle:bcprov-jdk15on:1.59' + compileOnly 'org.bouncycastle:bcpkix-jdk15on:1.59' // the following are all SAML dependencies - might as well download the whole internet compile "org.opensaml:opensaml-core:3.3.0" From defa749fc543595fdd548d7823d4df9228f08818 Mon Sep 17 00:00:00 2001 From: Ioannis Kakavas Date: Fri, 20 Jul 2018 14:18:13 +0300 Subject: [PATCH 7/8] ensure jimfs is available in test runtime --- x-pack/plugin/security/cli/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/security/cli/build.gradle b/x-pack/plugin/security/cli/build.gradle index b42759d559329..1799a2c7b81e1 100644 --- a/x-pack/plugin/security/cli/build.gradle +++ b/x-pack/plugin/security/cli/build.gradle @@ -7,7 +7,7 @@ dependencies { compileOnly xpackProject('plugin:core') compile 'org.bouncycastle:bcprov-jdk15on:1.59' compile 'org.bouncycastle:bcpkix-jdk15on:1.59' - testCompile 'com.google.jimfs:jimfs:1.1' + testImplementation 'com.google.jimfs:jimfs:1.1' testCompile "junit:junit:${versions.junit}" testCompile "org.hamcrest:hamcrest-all:${versions.hamcrest}" testCompile 'org.elasticsearch:securemock:1.2' From c2e55c247121c57d21966feef92e3c5dd5423ea5 Mon Sep 17 00:00:00 2001 From: Ioannis Kakavas Date: Fri, 20 Jul 2018 14:19:10 +0300 Subject: [PATCH 8/8] Fix security-cli tests --- .../cli/CertificateGenerateToolTests.java | 4 +-- .../security/cli/CertificateToolTests.java | 4 +-- .../xpack/security/cli/testnode.crt | 23 ++++++++++++++ .../xpack/security/cli/testnode.pem | 30 +++++++++++++++++++ 4 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 x-pack/plugin/security/cli/src/test/resources/org/elasticsearch/xpack/security/cli/testnode.crt create mode 100644 x-pack/plugin/security/cli/src/test/resources/org/elasticsearch/xpack/security/cli/testnode.pem diff --git a/x-pack/plugin/security/cli/src/test/java/org/elasticsearch/xpack/security/cli/CertificateGenerateToolTests.java b/x-pack/plugin/security/cli/src/test/java/org/elasticsearch/xpack/security/cli/CertificateGenerateToolTests.java index 164249ed2db00..91fd55933c554 100644 --- a/x-pack/plugin/security/cli/src/test/java/org/elasticsearch/xpack/security/cli/CertificateGenerateToolTests.java +++ b/x-pack/plugin/security/cli/src/test/java/org/elasticsearch/xpack/security/cli/CertificateGenerateToolTests.java @@ -361,8 +361,8 @@ public void testGeneratingSignedCertificates() throws Exception { public void testGetCAInfo() throws Exception { Environment env = TestEnvironment.newEnvironment(Settings.builder().put("path.home", createTempDir()).build()); - Path testNodeCertPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt"); - Path testNodeKeyPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem"); + Path testNodeCertPath = getDataPath("/org/elasticsearch/xpack/security/cli/testnode.crt"); + Path testNodeKeyPath = getDataPath("/org/elasticsearch/xpack/security/cli/testnode.pem"); final boolean passwordPrompt = randomBoolean(); MockTerminal terminal = new MockTerminal(); if (passwordPrompt) { diff --git a/x-pack/plugin/security/cli/src/test/java/org/elasticsearch/xpack/security/cli/CertificateToolTests.java b/x-pack/plugin/security/cli/src/test/java/org/elasticsearch/xpack/security/cli/CertificateToolTests.java index 2a5392a2befa2..9e970ea559ad7 100644 --- a/x-pack/plugin/security/cli/src/test/java/org/elasticsearch/xpack/security/cli/CertificateToolTests.java +++ b/x-pack/plugin/security/cli/src/test/java/org/elasticsearch/xpack/security/cli/CertificateToolTests.java @@ -389,8 +389,8 @@ public void testGeneratingSignedPemCertificates() throws Exception { public void testGetCAInfo() throws Exception { Environment env = TestEnvironment.newEnvironment(Settings.builder().put("path.home", createTempDir()).build()); - Path testNodeCertPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt"); - Path testNodeKeyPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem"); + Path testNodeCertPath = getDataPath("/org/elasticsearch/xpack/security/cli/testnode.crt"); + Path testNodeKeyPath = getDataPath("/org/elasticsearch/xpack/security/cli/testnode.pem"); final boolean passwordPrompt = randomBoolean(); MockTerminal terminal = new MockTerminal(); if (passwordPrompt) { diff --git a/x-pack/plugin/security/cli/src/test/resources/org/elasticsearch/xpack/security/cli/testnode.crt b/x-pack/plugin/security/cli/src/test/resources/org/elasticsearch/xpack/security/cli/testnode.crt new file mode 100644 index 0000000000000..08c160bcea5ff --- /dev/null +++ b/x-pack/plugin/security/cli/src/test/resources/org/elasticsearch/xpack/security/cli/testnode.crt @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIID0zCCArugAwIBAgIJALi5bDfjMszLMA0GCSqGSIb3DQEBCwUAMEgxDDAKBgNV +BAoTA29yZzEWMBQGA1UECxMNZWxhc3RpY3NlYXJjaDEgMB4GA1UEAxMXRWxhc3Rp +Y3NlYXJjaCBUZXN0IE5vZGUwHhcNMTUwOTIzMTg1MjU3WhcNMTkwOTIyMTg1MjU3 +WjBIMQwwCgYDVQQKEwNvcmcxFjAUBgNVBAsTDWVsYXN0aWNzZWFyY2gxIDAeBgNV +BAMTF0VsYXN0aWNzZWFyY2ggVGVzdCBOb2RlMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA3rGZ1QbsW0+MuyrSLmMfDFKtLBkIFW8V0gRuurFg1PUKKNR1 +Mq2tMVwjjYETAU/UY0iKZOzjgvYPKhDTYBTte/WHR1ZK4CYVv7TQX/gtFQG/ge/c +7u0sLch9p7fbd+/HZiLS/rBEZDIohvgUvzvnA8+OIYnw4kuxKo/5iboAIS41klMg +/lATm8V71LMY68inht71/ZkQoAHKgcR9z4yNYvQ1WqKG8DG8KROXltll3sTrKbl5 +zJhn660es/1ZnR6nvwt6xnSTl/mNHMjkfv1bs4rJ/py3qPxicdoSIn/KyojUcgHV +F38fuAy2CQTdjVG5fWj9iz+mQvLm3+qsIYQdFwIDAQABo4G/MIG8MAkGA1UdEwQC +MAAwHQYDVR0OBBYEFEMMWLWQi/g83PzlHYqAVnty5L7HMIGPBgNVHREEgYcwgYSC +CWxvY2FsaG9zdIIVbG9jYWxob3N0LmxvY2FsZG9tYWluggpsb2NhbGhvc3Q0ghds +b2NhbGhvc3Q0LmxvY2FsZG9tYWluNIIKbG9jYWxob3N0NoIXbG9jYWxob3N0Ni5s +b2NhbGRvbWFpbjaHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEwDQYJKoZIhvcNAQEL +BQADggEBAMjGGXT8Nt1tbl2GkiKtmiuGE2Ej66YuZ37WSJViaRNDVHLlg87TCcHe +k2rdO+6sFqQbbzEfwQ05T7xGmVu7tm54HwKMRugoQ3wct0bQC5wEWYN+oMDvSyO6 +M28mZwWb4VtR2IRyWP+ve5DHwTM9mxWa6rBlGzsQqH6YkJpZojzqk/mQTug+Y8aE +mVoqRIPMHq9ob+S9qd5lp09+MtYpwPfTPx/NN+xMEooXWW/ARfpGhWPkg/FuCu4z +1tFmCqHgNcWirzMm3dQpF78muE9ng6OB2MXQwL4VgnVkxmlZNHbkR2v/t8MyZJxC +y4g6cTMM3S/UMt5/+aIB2JAuMKyuD+A= +-----END CERTIFICATE----- diff --git a/x-pack/plugin/security/cli/src/test/resources/org/elasticsearch/xpack/security/cli/testnode.pem b/x-pack/plugin/security/cli/src/test/resources/org/elasticsearch/xpack/security/cli/testnode.pem new file mode 100644 index 0000000000000..5a67e1033440d --- /dev/null +++ b/x-pack/plugin/security/cli/src/test/resources/org/elasticsearch/xpack/security/cli/testnode.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,9D867F7E0C94D013 + +dVoVCjPeg1wgS7rVtOvGfQcrZyLkx393aWRnFq45tbjKBVuITtJ9vI7o4QXOV/15 +Gnb6WhXGIdWrzsxEAd46K6hIuNSISd4Emsx6c2Q5hTqWXXfexbOZBNfTtXtdJPnJ +1jAaikhtztLo3JSLTKNY5sNxd+XbaQyYVUWvueK6zOaIIMETvB+VPVFd9i1ROibk +Sgdtyj01KjkoalifqK/tA0CIYNKL0S6/eoK3UhAlpIprlpV+cnXa940C6bjLeJPt +PMAGGp5RrplxSgrSerw3I9DOWkHGtpqzIka3XneNUXJP8k4HUJ+aZkGH2ZILKS8d +4KMIb+KZSpHEGn+6uGccWLtZZmAjWJrDw56JbQtSHdRYLBRSOjLbTvQoPu/2Hpli +7HOxbotlvjptMunncq5aqK57SHA1dh0cwF7J3LUmGFJ67eoz+VV3b5qMn4MopSeI +mS16Ydd3nGpjSrln/elM0CQxqWfcOAXRZpDpFUQoXcBrLVzvz2DBl/0CrTRLhgzi +CO+5/IVcBWRlYpRNGgjjP7q0j6URID3jk5J06fYQXmBiwQT5j+GZqqzpMCJ9mIy2 +1O9SN1hebJnIcEU+E0njn/MGjlYdPywhaCy8pqElp6Q8TUEJpwLRFO/owCoBet/n +ZmCXUjfCGhc1pWHufFcDEQ6xMgEWWY/tdwCZeSU7EhErTjCbfupg+55A5fpDml0m +3wH4CFcuRjlqyx6Ywixm1ATeitDtJl5HQTw6b8OtEXwSgRmZ0eSqSRVk9QbVS7gu +IpQe09/Zimb5HzjZqZ3fdqHlcW4xax8hyJeyIvF5ZJ57eY8CBvu/wP2GDn26QnvF +xQqdfDbq1H4JmpwUHpbFwBoQK4Q6WFd1z4EA9bRQeo3H9PoqoOwMDjzajwLRF7b7 +q6tYH/n9PyHwdf1c4fFwgSmL1toXGfKlA9hjIaLsRSDD6srT5EdUk78bsnddwI51 +tu7C7P4JG+h1VdRNMNTlqtileWsIE7Nn2A1OkcUxZdF5mamENpDpJcHePLto6c8q +FKiwyFMsxhgsj6HK2HqO+UA4sX5Ni4oHwiPmb//EZLn045M5i1AN26KosJmb8++D +sgR5reWRy+UqJCTYblVg+7Dx++ggUnfxVyQEsWmw5r5f4KU5wXBkvoVMGtPNa9DE +n/uLtObD1qkNL38pRsr2OGRchYCgEoKGqEISBP4knfGXLOlWiW/246j9QzI97r1u +tvy7fKg28G7AUz9l6bpewsPHefBUeRQeieP9eJINaEpxkF/w2RpKDLpQjWxwDDOM +s+D0mrBMJve17AmJ8rMw6dIQPZYNZ88/jz1uQuUwQ2YlbmtZbCG81k9YMFGEU9XS +cyhJxj8hvYnt2PR5Z9/cJPyWOs0m/ufOeeQQ8SnU/lzmrQnpzUd2Z6p5i/B7LdRP +n1kX+l1qynuPnjvBz4nJQE0p6nzW8RyCDSniC9mtYtZmhgC8icqxgbvS7uEOBIYJ +NbK+0bEETTO34iY/JVTIqLOw3iQZYMeUpxpj6Phgx/oooxMTquMecPKNgeVtaBst +qjTNPX0ti1/HYpZqzYi8SV8YjHSJWCVMsZjKPr3W/HIcCKqYoIfgzi83Ha2KMQx6 +-----END RSA PRIVATE KEY-----