Remove BouncyCastle dependency from runtime (#32193)
* Remove BouncyCastle dependency from runtime This commit introduces a new gradle project that contains the classes that have a dependency on BouncyCastle. For the default distribution, It builds a jar from those and in 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.
This commit is contained in:
parent
7aa8a0a927
commit
aaa8f842d6
|
@ -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
|
||||
|
|
|
@ -227,16 +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 }
|
||||
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 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -57,6 +57,7 @@ import static org.hamcrest.CoreMatchers.is;
|
|||
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 abstract class ArchiveTestCase extends PackagingTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
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")));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -101,6 +101,7 @@ public class Installation {
|
|||
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
|
||||
|
|
|
@ -20,7 +20,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
|
||||
}
|
||||
|
@ -38,8 +37,6 @@ 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'
|
||||
compile project(path: ':modules:transport-netty4', configuration: 'runtime')
|
||||
|
||||
testCompile 'org.elasticsearch:securemock:1.2'
|
||||
|
@ -116,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
|
||||
|
|
|
@ -63,7 +63,7 @@ public class CertParsingUtils {
|
|||
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 class CertParsingUtils {
|
|||
return certificates.toArray(new X509Certificate[0]);
|
||||
}
|
||||
|
||||
static List<Certificate> readCertificates(InputStream input) throws CertificateException, IOException {
|
||||
public static List<Certificate> readCertificates(InputStream input) throws CertificateException, IOException {
|
||||
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
|
||||
Collection<Certificate> certificates = (Collection<Certificate>) certFactory.generateCertificates(input);
|
||||
return new ArrayList<>(certificates);
|
||||
|
@ -140,7 +140,7 @@ public class CertParsingUtils {
|
|||
/**
|
||||
* 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 @@ public class CertParsingUtils {
|
|||
/**
|
||||
* 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 class CertParsingUtils {
|
|||
/**
|
||||
* 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);
|
||||
|
|
|
@ -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'
|
||||
}
|
||||
|
|
|
@ -0,0 +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'
|
||||
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'
|
||||
testCompile "org.elasticsearch.test:framework:${version}"
|
||||
testCompile project(path: xpackModule('core'), configuration: 'testArtifacts')
|
||||
}
|
||||
|
||||
dependencyLicenses {
|
||||
mapping from: /bc.*/, to: 'bouncycastle'
|
||||
}
|
|
@ -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 @@ public class 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 class CertGenUtils {
|
|||
*/
|
||||
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 class CertGenUtils {
|
|||
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 class CertGenUtils {
|
|||
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 @@ public class CertGenUtils {
|
|||
}
|
||||
|
||||
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 @@ public class CertGenUtils {
|
|||
|
||||
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 @@ public class CertGenUtils {
|
|||
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 @@ public class CertGenUtils {
|
|||
* @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");
|
|
@ -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.ObjectParser;
|
|||
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 @@ import java.util.zip.ZipOutputStream;
|
|||
|
||||
/**
|
||||
* 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 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
|
|||
// of the parser in this class so that we can defer initialization until after logging has been initialized
|
||||
static {
|
||||
@SuppressWarnings("unchecked") final ConstructingObjectParser<CertificateInformation, Void> instanceParser =
|
||||
new ConstructingObjectParser<>(
|
||||
"instances",
|
||||
a -> new CertificateInformation(
|
||||
(String) a[0], (String) (a[1] == null ? a[0] : a[1]),
|
||||
(List<String>) a[2], (List<String>) a[3], (List<String>) a[4]));
|
||||
new ConstructingObjectParser<>(
|
||||
"instances",
|
||||
a -> new CertificateInformation(
|
||||
(String) a[0], (String) (a[1] == null ? a[0] : a[1]),
|
||||
(List<String>) a[2], (List<String>) a[3], (List<String>) 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 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
|
|||
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 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
|
|||
p12Password = null;
|
||||
}
|
||||
CAInfo caInfo = getCAInfo(terminal, dn, caCertPathSpec.value(options), caKeyPathSpec.value(options), keyPass, prompt, env,
|
||||
keysize, days);
|
||||
keysize, days);
|
||||
Collection<CertificateInformation> certificateInformations = getCertificateInformationList(terminal, inputFile);
|
||||
generateAndWriteSignedCertificates(outputFile, certificateInformations, caInfo, keysize, days, p12Password);
|
||||
}
|
||||
|
@ -197,7 +200,7 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
|
|||
/**
|
||||
* 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 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
|
|||
/**
|
||||
* 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<CertificateInformation> getCertificateInformationList(Terminal terminal, String inputFile)
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
if (inputFile != null) {
|
||||
return parseAndValidateFile(terminal, resolvePath(inputFile).toAbsolutePath());
|
||||
}
|
||||
|
@ -239,7 +243,7 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
|
|||
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 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
|
|||
}
|
||||
|
||||
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 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
|
|||
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 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
|
|||
|
||||
/**
|
||||
* 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 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
|
|||
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<CertificateInformation> 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 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
|
|||
* Returns the CA certificate and private key that will be used to sign certificates. These may be specified by the user or
|
||||
* automatically generated
|
||||
*
|
||||
* @param terminal the terminal to use for prompting the user
|
||||
* @param dn the distinguished name to use for the CA
|
||||
* @param terminal the terminal to use for prompting the user
|
||||
* @param dn the distinguished name to use for the CA
|
||||
* @param caCertPath the path to the CA certificate or {@code null} if not provided
|
||||
* @param caKeyPath the path to the CA private key or {@code null} if not provided
|
||||
* @param prompt whether we should prompt the user for a password
|
||||
* @param keyPass the password to the private key. If not present and the key is encrypted the user will be prompted
|
||||
* @param env the environment for this tool to resolve files with
|
||||
* @param keysize the size of the key in bits
|
||||
* @param days the number of days that the certificate should be valid for
|
||||
* @param caKeyPath the path to the CA private key or {@code null} if not provided
|
||||
* @param prompt whether we should prompt the user for a password
|
||||
* @param keyPass the password to the private key. If not present and the key is encrypted the user will be prompted
|
||||
* @param env the environment for this tool to resolve files with
|
||||
* @param keysize the size of the key in bits
|
||||
* @param days the number of days that the certificate should be valid for
|
||||
* @return CA cert and private key
|
||||
*/
|
||||
static CAInfo getCAInfo(Terminal terminal, String dn, String caCertPath, String caKeyPath, char[] keyPass, boolean prompt,
|
||||
|
@ -366,7 +372,7 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
|
|||
Certificate[] certificates = CertParsingUtils.readCertificates(Collections.singletonList(resolvedCaCertPath), env);
|
||||
if (certificates.length != 1) {
|
||||
throw new IllegalArgumentException("expected a single certificate in file [" + caCertPath + "] but found [" +
|
||||
certificates.length + "]");
|
||||
certificates.length + "]");
|
||||
}
|
||||
Certificate caCert = certificates[0];
|
||||
PrivateKey privateKey = readPrivateKey(caKeyPath, keyPass, terminal, prompt);
|
||||
|
@ -388,11 +394,12 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
|
|||
|
||||
/**
|
||||
* Generates signed certificates in PEM format stored in a zip file
|
||||
* @param outputFile the file that the certificates will be written to. This file must not exist
|
||||
*
|
||||
* @param outputFile the file that the certificates will be written to. This file must not exist
|
||||
* @param certificateInformations details for creation of the certificates
|
||||
* @param caInfo the CA information to sign the certificates with
|
||||
* @param keysize the size of the key in bits
|
||||
* @param days the number of days that the certificate should be valid for
|
||||
* @param caInfo the CA information to sign the certificates with
|
||||
* @param keysize the size of the key in bits
|
||||
* @param days the number of days that the certificate should be valid for
|
||||
*/
|
||||
static void generateAndWriteSignedCertificates(Path outputFile, Collection<CertificateInformation> certificateInformations,
|
||||
CAInfo caInfo, int keysize, int days, char[] pkcs12Password) throws Exception {
|
||||
|
@ -403,9 +410,9 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
|
|||
for (CertificateInformation certificateInformation : certificateInformations) {
|
||||
KeyPair keyPair = CertGenUtils.generateKeyPair(keysize);
|
||||
Certificate certificate = CertGenUtils.generateSignedCertificate(certificateInformation.name.x500Principal,
|
||||
getSubjectAlternativeNamesValue(certificateInformation.ipAddresses, certificateInformation.dnsNames,
|
||||
certificateInformation.commonNames),
|
||||
keyPair, caInfo.caCert, caInfo.privateKey, days);
|
||||
getSubjectAlternativeNamesValue(certificateInformation.ipAddresses, certificateInformation.dnsNames,
|
||||
certificateInformation.commonNames),
|
||||
keyPair, caInfo.caCert, caInfo.privateKey, days);
|
||||
|
||||
final String dirName = certificateInformation.name.filename + "/";
|
||||
ZipEntry zipEntry = new ZipEntry(dirName);
|
||||
|
@ -429,7 +436,7 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
|
|||
final KeyStore pkcs12 = KeyStore.getInstance("PKCS12");
|
||||
pkcs12.load(null);
|
||||
pkcs12.setKeyEntry(certificateInformation.name.originalName, keyPair.getPrivate(), pkcs12Password,
|
||||
new Certificate[]{certificate});
|
||||
new Certificate[]{certificate});
|
||||
|
||||
outputStream.putNextEntry(new ZipEntry(entryBase + ".p12"));
|
||||
pkcs12.store(outputStream, pkcs12Password);
|
||||
|
@ -441,7 +448,8 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
|
|||
|
||||
/**
|
||||
* This method handles the deletion of a file in the case of a partial write
|
||||
* @param file the file that is being written to
|
||||
*
|
||||
* @param file the file that is being written to
|
||||
* @param writer writes the contents of the file
|
||||
*/
|
||||
private static void fullyWriteFile(Path file, Writer writer) throws Exception {
|
||||
|
@ -468,9 +476,10 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
|
|||
/**
|
||||
* This method handles writing out the certificate authority cert and private key if the certificate authority was generated by
|
||||
* this invocation of the tool
|
||||
*
|
||||
* @param outputStream the output stream to write to
|
||||
* @param pemWriter the writer for PEM objects
|
||||
* @param info the certificate authority information
|
||||
* @param pemWriter the writer for PEM objects
|
||||
* @param info the certificate authority information
|
||||
*/
|
||||
private static void writeCAInfoIfGenerated(ZipOutputStream outputStream, JcaPEMWriter pemWriter, CAInfo info) throws Exception {
|
||||
if (info.generated) {
|
||||
|
@ -577,14 +586,15 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
|
|||
/**
|
||||
* Helper method to read a private key and support prompting of user for a key. To avoid passwords being placed as an argument we
|
||||
* can prompt the user for their password if we encounter an encrypted key.
|
||||
* @param path the path to the private key
|
||||
*
|
||||
* @param path the path to the private key
|
||||
* @param password the password provided by the user or {@code null}
|
||||
* @param terminal the terminal to use for user interaction
|
||||
* @param prompt whether to prompt the user or not
|
||||
* @param prompt whether to prompt the user or not
|
||||
* @return the {@link PrivateKey} that was read from the file
|
||||
*/
|
||||
private static PrivateKey readPrivateKey(String path, char[] password, Terminal terminal, boolean prompt)
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
AtomicReference<char[]> passwordReference = new AtomicReference<>(password);
|
||||
try {
|
||||
return PemUtils.readPrivateKey(resolvePath(path), () -> {
|
||||
|
@ -682,7 +692,7 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
|
|||
}
|
||||
} 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 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
|
|||
|
||||
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 + "]}";
|
||||
}
|
||||
}
|
||||
|
|
@ -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.ObjectParser;
|
|||
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 @@ public class CertificateTool extends LoggingAwareMultiCommand {
|
|||
// of the parser in this class so that we can defer initialization until after logging has been initialized
|
||||
static {
|
||||
@SuppressWarnings("unchecked") final ConstructingObjectParser<CertificateInformation, Void> instanceParser =
|
||||
new ConstructingObjectParser<>(
|
||||
"instances",
|
||||
a -> new CertificateInformation(
|
||||
(String) a[0], (String) (a[1] == null ? a[0] : a[1]),
|
||||
(List<String>) a[2], (List<String>) a[3], (List<String>) a[4]));
|
||||
new ConstructingObjectParser<>(
|
||||
"instances",
|
||||
a -> new CertificateInformation(
|
||||
(String) a[0], (String) (a[1] == null ? a[0] : a[1]),
|
||||
(List<String>) a[2], (List<String>) a[3], (List<String>) 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 class CertificateTool extends LoggingAwareMultiCommand {
|
|||
|
||||
|
||||
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 @@ public class CertificateTool extends LoggingAwareMultiCommand {
|
|||
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 @@ public class CertificateTool extends LoggingAwareMultiCommand {
|
|||
char[] passwordOption = getChars(caPasswordSpec.value(options));
|
||||
|
||||
Map<Certificate, Key> 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<Certificate, Key> pair = keys.entrySet().iterator().next();
|
||||
return new CAInfo((X509Certificate) pair.getKey(), (PrivateKey) pair.getValue());
|
||||
|
@ -358,7 +360,7 @@ public class CertificateTool extends LoggingAwareMultiCommand {
|
|||
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 @@ public class CertificateTool extends LoggingAwareMultiCommand {
|
|||
* @return a {@link Collection} of {@link CertificateInformation} that represents each instance
|
||||
*/
|
||||
Collection<CertificateInformation> 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 @@ public class CertificateTool extends LoggingAwareMultiCommand {
|
|||
}
|
||||
|
||||
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 @@ public class CertificateTool extends LoggingAwareMultiCommand {
|
|||
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 @@ public class CertificateTool extends LoggingAwareMultiCommand {
|
|||
* @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 @@ public class CertificateTool extends LoggingAwareMultiCommand {
|
|||
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 @@ public class CertificateTool extends LoggingAwareMultiCommand {
|
|||
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 @@ public class CertificateTool extends LoggingAwareMultiCommand {
|
|||
for (CertificateInformation certificateInformation : certInfo) {
|
||||
KeyPair keyPair = CertGenUtils.generateKeyPair(keySize);
|
||||
GeneralNames sanList = getSubjectAlternativeNamesValue(certificateInformation.ipAddresses,
|
||||
certificateInformation.dnsNames, certificateInformation.commonNames);
|
||||
certificateInformation.dnsNames, certificateInformation.commonNames);
|
||||
PKCS10CertificationRequest csr = CertGenUtils.generateCSR(keyPair, certificateInformation.name.x500Principal, sanList);
|
||||
|
||||
final String dirName = certificateInformation.name.filename + "/";
|
||||
|
@ -750,7 +752,7 @@ public class CertificateTool extends LoggingAwareMultiCommand {
|
|||
*/
|
||||
void generateAndWriteSignedCertificates(Path output, boolean writeZipFile, OptionSet options,
|
||||
Collection<CertificateInformation> certs, CAInfo caInfo, Terminal terminal)
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
|
||||
checkDirectory(output, terminal);
|
||||
|
||||
|
@ -805,7 +807,7 @@ public class CertificateTool extends LoggingAwareMultiCommand {
|
|||
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 @@ public class CertificateTool extends LoggingAwareMultiCommand {
|
|||
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 @@ public class CertificateTool extends LoggingAwareMultiCommand {
|
|||
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 @@ public class CertificateTool extends LoggingAwareMultiCommand {
|
|||
} 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 @@ public class CertificateTool extends LoggingAwareMultiCommand {
|
|||
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 @@ public class CertificateTool extends LoggingAwareMultiCommand {
|
|||
* @return the {@link PrivateKey} that was read from the file
|
||||
*/
|
||||
private static PrivateKey readPrivateKey(Path path, char[] password, Terminal terminal)
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
AtomicReference<char[]> passwordReference = new AtomicReference<>(password);
|
||||
try {
|
||||
return PemUtils.readPrivateKey(path, () -> {
|
||||
|
@ -1125,7 +1127,7 @@ public class CertificateTool extends LoggingAwareMultiCommand {
|
|||
}
|
||||
} 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 @@ public class CertificateTool extends LoggingAwareMultiCommand {
|
|||
|
||||
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 + "]}";
|
||||
}
|
||||
}
|
||||
|
|
@ -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.SuppressForbidden;
|
|||
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;
|
|
@ -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.Environment;
|
|||
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;
|
||||
|
@ -359,8 +361,8 @@ public class CertificateGenerateToolTests extends ESTestCase {
|
|||
|
||||
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) {
|
|
@ -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.env.TestEnvironment;
|
|||
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;
|
||||
|
@ -387,8 +389,8 @@ public class CertificateToolTests extends ESTestCase {
|
|||
|
||||
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) {
|
|
@ -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-----
|
|
@ -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-----
|
|
@ -4,7 +4,8 @@
|
|||
# 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 \
|
||||
"$@"
|
||||
|
|
|
@ -7,8 +7,9 @@ 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" ^
|
||||
%%* ^
|
||||
|| exit /b 1
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
# 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 \
|
||||
"$@"
|
||||
|
|
|
@ -7,8 +7,9 @@ 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" ^
|
||||
%%* ^
|
||||
|| exit /b 1
|
||||
|
|
Loading…
Reference in New Issue