[Security] Support PKCSelastic/x-pack-elasticsearch#12 keystores (elastic/x-pack-elasticsearch#2066)
Adds support for reading PKCSelastic/x-pack-elasticsearch#12 files as SSL keystores/truststores. Original commit: elastic/x-pack-elasticsearch@1855ad6173
This commit is contained in:
parent
15f5c5a632
commit
9ab6d3cbc3
|
@ -298,6 +298,10 @@ List of paths to PEM encoded certificate files that should be trusted.
|
|||
The path to the Java Keystore file that contains a private key and certificate.
|
||||
`ssl.key` and `ssl.keystore.path` may not be used at the same time.
|
||||
|
||||
`ssl.keystore.type`::
|
||||
The format of the keystore file. Should be either `jks` to use the Java
|
||||
Keystore format, or `PKCS12` to use PKCS#12 files. The default is `jks`.
|
||||
|
||||
`ssl.keystore.password`::
|
||||
The password to the keystore.
|
||||
|
||||
|
@ -308,6 +312,10 @@ The password for the key in the keystore. Defaults to the keystore password.
|
|||
The path to the Java Keystore file that contains the certificates to trust.
|
||||
`ssl.certificate_authorities` and `ssl.truststore.path` may not be used at the same time.
|
||||
|
||||
`ssl.truststore.type`::
|
||||
The format of the keystore file. Should be either `jks` to use the Java
|
||||
Keystore format, or `PKCS12` to use PKCS#12 files. The default is `jks`.
|
||||
|
||||
`ssl.truststore.password`::
|
||||
The password to the truststore.
|
||||
|
||||
|
@ -482,6 +490,10 @@ List of paths to PEM encoded certificate files that should be trusted.
|
|||
`ssl.keystore.path`::
|
||||
The path to the Java Keystore file that contains a private key and certificate.
|
||||
|
||||
`ssl.keystore.type`::
|
||||
The format of the keystore file. Should be either `jks` to use the Java
|
||||
Keystore format, or `PKCS12` to use PKCS#12 files. The default is `jks`.
|
||||
|
||||
`ssl.keystore.password`::
|
||||
The password to the keystore.
|
||||
|
||||
|
@ -491,6 +503,10 @@ The password for the key in the keystore. Defaults to the keystore password.
|
|||
`ssl.truststore.path`::
|
||||
The path to the Java Keystore file that contains the certificates to trust.
|
||||
|
||||
`ssl.truststore.type`::
|
||||
The format of the truststore file. Should be either `jks` to use the Java
|
||||
Keystore format, or `PKCS12` to use PKCS#12 files. The default is `jks`.
|
||||
|
||||
`ssl.truststore.password`::
|
||||
The password to the truststore.
|
||||
|
||||
|
@ -636,6 +652,35 @@ Path to the truststore file.
|
|||
`xpack.ssl.truststore.password`::
|
||||
Password to the truststore.
|
||||
|
||||
[float]
|
||||
===== PKCS#12 Files
|
||||
|
||||
When using PKCS#12 container files (`.p12` or `.pfx`), which contain the
|
||||
private key, certificate, and certificates that should be trusted, use
|
||||
the following settings:
|
||||
|
||||
`xpack.ssl.keystore.path`::
|
||||
Path to the PKCS#12 file that holds the private key and certificate.
|
||||
|
||||
`xpack.ssl.keystore.type`::
|
||||
Set this to `PKCS12`.
|
||||
|
||||
`xpack.ssl.keystore.password`::
|
||||
Password to the PKCS#12 file.
|
||||
|
||||
`xpack.ssl.keystore.key_password`::
|
||||
Password for the private key in the PKCS12 file.
|
||||
Defaults to the same value as `xpack.ssl.keystore.password`.
|
||||
|
||||
`xpack.ssl.truststore.path`::
|
||||
Path to the truststore file.
|
||||
|
||||
`xpack.ssl.truststore.type`::
|
||||
Set this to `PKCS12`.
|
||||
|
||||
`xpack.ssl.truststore.password`::
|
||||
Password to the truststore.
|
||||
|
||||
[[http-tls-ssl-settings]]
|
||||
:ssl-prefix: xpack.security.http
|
||||
:component: HTTP
|
||||
|
|
|
@ -93,3 +93,32 @@ Path to the truststore file.
|
|||
|
||||
+{ssl-prefix}.ssl.truststore.password+::
|
||||
Password to the truststore.
|
||||
|
||||
===== PKCS#12 Files
|
||||
|
||||
{security} can be configured to use PKCS#12 container files (`.p12` or `.pfx` files)
|
||||
that contain the private key, certificate and certificates that should be trusted.
|
||||
|
||||
PKCS#12 files are configured in the same way as Java Keystore Files:
|
||||
|
||||
+{ssl-prefix}.ssl.keystore.path+::
|
||||
Path to the PKCS#12 file that holds the private key and certificate.
|
||||
|
||||
+{ssl-prefix}.ssl.keystore.type+::
|
||||
Set this to `PKCS12` to indicate that the keystore is a PKCS#12 file.
|
||||
|
||||
+{ssl-prefix}.ssl.keystore.password+::
|
||||
Password to the PKCS#12 file.
|
||||
|
||||
+{ssl-prefix}.ssl.keystore.key_password+::
|
||||
Password for the private key stored in the PKCS#12 file.
|
||||
Defaults to the same value as +{ssl-prefix}.ssl.keystore.password+.
|
||||
|
||||
+{ssl-prefix}.ssl.truststore.path+::
|
||||
Path to the PKCS#12 file that holds the certificates to be trusted.
|
||||
|
||||
+{ssl-prefix}.ssl.truststore.type+::
|
||||
Set this to `PKCS12` to indicate that the truststore is a PKCS#12 file.
|
||||
|
||||
+{ssl-prefix}.ssl.truststore.password+::
|
||||
Password to the PKCS#12 file.
|
|
@ -180,8 +180,9 @@ public class PkiRealm extends Realm {
|
|||
}
|
||||
try (SecureString password = SSL_SETTINGS.truststorePassword.get(settings)) {
|
||||
String trustStoreAlgorithm = SSL_SETTINGS.truststoreAlgorithm.get(settings);
|
||||
String trustStoreType = SSL_SETTINGS.truststoreType.get(settings);
|
||||
try {
|
||||
return CertUtils.trustManager(truststorePath, password.getChars(), trustStoreAlgorithm, realmConfig.env());
|
||||
return CertUtils.trustManager(truststorePath, trustStoreType, password.getChars(), trustStoreAlgorithm, realmConfig.env());
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("failed to load specified truststore", e);
|
||||
}
|
||||
|
|
|
@ -160,12 +160,11 @@ public class CertUtils {
|
|||
* @param env the environment to use for file resolution. May be {@code null}
|
||||
* @return a trust manager with the trust material from the store
|
||||
*/
|
||||
public static X509ExtendedTrustManager trustManager(String trustStorePath, char[] trustStorePassword, String trustStoreAlgorithm,
|
||||
@Nullable Environment env)
|
||||
public static X509ExtendedTrustManager trustManager(String trustStorePath, String trustStoreType, char[] trustStorePassword,
|
||||
String trustStoreAlgorithm, @Nullable Environment env)
|
||||
throws NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException, IOException, CertificateException {
|
||||
try (InputStream in = Files.newInputStream(resolvePath(trustStorePath, env))) {
|
||||
// TODO remove reliance on JKS since we can PKCS12 stores...
|
||||
KeyStore trustStore = KeyStore.getInstance("jks");
|
||||
KeyStore trustStore = KeyStore.getInstance(trustStoreType);
|
||||
assert trustStorePassword != null;
|
||||
trustStore.load(in, trustStorePassword);
|
||||
return trustManager(trustStore, trustStoreAlgorithm);
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.elasticsearch.xpack.XPackSettings;
|
|||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import java.nio.file.Path;
|
||||
import java.security.KeyStore;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
@ -186,8 +187,7 @@ public final class SSLConfiguration {
|
|||
} else if (System.getProperty("javax.net.ssl.keyStore") != null) {
|
||||
// TODO: we should not support loading a keystore from sysprops...
|
||||
try (SecureString keystorePassword = new SecureString(System.getProperty("javax.net.ssl.keyStorePassword", ""))) {
|
||||
return new StoreKeyConfig(System.getProperty("javax.net.ssl.keyStore"),
|
||||
keystorePassword, keystorePassword,
|
||||
return new StoreKeyConfig(System.getProperty("javax.net.ssl.keyStore"), "jks", keystorePassword, keystorePassword,
|
||||
System.getProperty("ssl.KeyManagerFactory.algorithm", KeyManagerFactory.getDefaultAlgorithm()),
|
||||
System.getProperty("ssl.TrustManagerFactory.algorithm", TrustManagerFactory.getDefaultAlgorithm()));
|
||||
}
|
||||
|
@ -205,12 +205,14 @@ public final class SSLConfiguration {
|
|||
} else {
|
||||
SecureString keyStorePassword = SETTINGS_PARSER.keystorePassword.get(settings);
|
||||
String keyStoreAlgorithm = SETTINGS_PARSER.keystoreAlgorithm.get(settings);
|
||||
String keyStoreType = SETTINGS_PARSER.keystoreType.get(settings);
|
||||
SecureString keyStoreKeyPassword = SETTINGS_PARSER.keystoreKeyPassword.get(settings);;
|
||||
if (keyStoreKeyPassword.length() == 0) {
|
||||
keyStoreKeyPassword = keyStorePassword;
|
||||
}
|
||||
String trustStoreAlgorithm = SETTINGS_PARSER.truststoreAlgorithm.get(settings);
|
||||
return new StoreKeyConfig(keyStorePath, keyStorePassword, keyStoreKeyPassword, keyStoreAlgorithm, trustStoreAlgorithm);
|
||||
return new StoreKeyConfig(keyStorePath, keyStoreType, keyStorePassword, keyStoreKeyPassword, keyStoreAlgorithm,
|
||||
trustStoreAlgorithm);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,10 +244,11 @@ public final class SSLConfiguration {
|
|||
} else if (trustStorePath != null) {
|
||||
SecureString trustStorePassword = SETTINGS_PARSER.truststorePassword.get(settings);
|
||||
String trustStoreAlgorithm = SETTINGS_PARSER.truststoreAlgorithm.get(settings);
|
||||
return new StoreTrustConfig(trustStorePath, trustStorePassword, trustStoreAlgorithm);
|
||||
String trustStoreType = SETTINGS_PARSER.truststoreType.get(settings);
|
||||
return new StoreTrustConfig(trustStorePath, trustStoreType, trustStorePassword, trustStoreAlgorithm);
|
||||
} else if (global == null && System.getProperty("javax.net.ssl.trustStore") != null) {
|
||||
try (SecureString truststorePassword = new SecureString(System.getProperty("javax.net.ssl.trustStorePassword", ""))) {
|
||||
return new StoreTrustConfig(System.getProperty("javax.net.ssl.trustStore"), truststorePassword,
|
||||
return new StoreTrustConfig(System.getProperty("javax.net.ssl.trustStore"), "jks", truststorePassword,
|
||||
System.getProperty("ssl.TrustManagerFactory.algorithm", TrustManagerFactory.getDefaultAlgorithm()));
|
||||
}
|
||||
} else if (global != null && keyConfig == global.keyConfig()) {
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.elasticsearch.xpack.ssl;
|
|||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
|
||||
import java.security.KeyStore;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
@ -32,10 +33,12 @@ public class SSLConfigurationSettings {
|
|||
public final Setting<Optional<String>> keystorePath;
|
||||
public final Setting<SecureString> keystorePassword;
|
||||
public final Setting<String> keystoreAlgorithm;
|
||||
public final Setting<String> keystoreType;
|
||||
public final Setting<SecureString> keystoreKeyPassword;
|
||||
public final Setting<Optional<String>> truststorePath;
|
||||
public final Setting<SecureString> truststorePassword;
|
||||
public final Setting<String> truststoreAlgorithm;
|
||||
public final Setting<String> truststoreType;
|
||||
public final Setting<Optional<String>> trustRestrictionsPath;
|
||||
public final Setting<Optional<String>> keyPath;
|
||||
public final Setting<SecureString> keyPassword;
|
||||
|
@ -52,6 +55,12 @@ public class SSLConfigurationSettings {
|
|||
|
||||
private final List<Setting<?>> allSettings;
|
||||
|
||||
/**
|
||||
* We explicitly default to "jks" here (rather than {@link KeyStore#getDefaultType()}) for backwards compatibility.
|
||||
* Older versions of X-Pack only supported JKS and never looked at the JVM's configured default.
|
||||
*/
|
||||
private static final String DEFAULT_KEYSTORE_TYPE = "jks";
|
||||
|
||||
private static final Function<String, Setting<List<String>>> CIPHERS_SETTING_TEMPLATE = key -> Setting.listSetting(key, Collections
|
||||
.emptyList(), Function.identity(), Property.NodeScope, Property.Filtered);
|
||||
public static final Setting<List<String>> CIPHERS_SETTING_PROFILES = Setting.affixKeySetting("transport.profiles.",
|
||||
|
@ -121,6 +130,16 @@ public class SSLConfigurationSettings {
|
|||
public static final Setting<String> TRUST_STORE_ALGORITHM_PROFILES = Setting.affixKeySetting("transport.profiles.",
|
||||
"xpack.security.ssl.truststore.algorithm", TRUST_STORE_ALGORITHM_TEMPLATE);
|
||||
|
||||
private static final Function<String, Setting<String>> KEY_STORE_TYPE_TEMPLATE = key ->
|
||||
new Setting<>(key, DEFAULT_KEYSTORE_TYPE, Function.identity(), Property.NodeScope, Property.Filtered);
|
||||
public static final Setting<String> KEY_STORE_TYPE_PROFILES = Setting.affixKeySetting("transport.profiles.",
|
||||
"xpack.security.ssl.keystore.type", KEY_STORE_TYPE_TEMPLATE);
|
||||
|
||||
private static final Function<String, Setting<String>> TRUST_STORE_TYPE_TEMPLATE = key ->
|
||||
new Setting<>(key, DEFAULT_KEYSTORE_TYPE, Function.identity(), Property.NodeScope, Property.Filtered);
|
||||
public static final Setting<String> TRUST_STORE_TYPE_PROFILES = Setting.affixKeySetting("transport.profiles.",
|
||||
"xpack.security.ssl.truststore.type", TRUST_STORE_TYPE_TEMPLATE);
|
||||
|
||||
private static final Function<String, Setting<Optional<String>>> TRUST_RESTRICTIONS_TEMPLATE = key -> new Setting<>(key, s -> null,
|
||||
Optional::ofNullable, Property.NodeScope, Property.Filtered);
|
||||
public static final Setting<Optional<String>> TRUST_RESTRICTIONS_PROFILES = Setting.affixKeySetting("transport.profiles.",
|
||||
|
@ -179,6 +198,8 @@ public class SSLConfigurationSettings {
|
|||
truststorePassword = TRUSTSTORE_PASSWORD_TEMPLATE.apply(prefix + "truststore.secure_password");
|
||||
keystoreAlgorithm = KEY_STORE_ALGORITHM_TEMPLATE.apply(prefix + "keystore.algorithm");
|
||||
truststoreAlgorithm = TRUST_STORE_ALGORITHM_TEMPLATE.apply(prefix + "truststore.algorithm");
|
||||
keystoreType = KEY_STORE_TYPE_TEMPLATE.apply(prefix + "keystore.type");
|
||||
truststoreType = KEY_STORE_TYPE_TEMPLATE.apply(prefix + "truststore.type");
|
||||
trustRestrictionsPath = TRUST_RESTRICTIONS_TEMPLATE.apply(prefix + "trust_restrictions.path");
|
||||
keyPath = KEY_PATH_TEMPLATE.apply(prefix + "key");
|
||||
legacyKeyPassword = LEGACY_KEY_PASSWORD_TEMPLATE.apply(prefix + "key_passphrase");
|
||||
|
@ -189,8 +210,8 @@ public class SSLConfigurationSettings {
|
|||
verificationMode = VERIFICATION_MODE_SETTING_TEMPLATE.apply(prefix + "verification_mode");
|
||||
|
||||
this.allSettings = Arrays.asList(ciphers, supportedProtocols,
|
||||
keystorePath, keystorePassword, keystoreAlgorithm, keystoreKeyPassword,
|
||||
truststorePath, truststorePassword, truststoreAlgorithm, trustRestrictionsPath,
|
||||
keystorePath, keystorePassword, keystoreAlgorithm, keystoreType, keystoreKeyPassword,
|
||||
truststorePath, truststorePassword, truststoreAlgorithm, truststoreType, trustRestrictionsPath,
|
||||
keyPath, keyPassword, cert, caPaths, clientAuth, verificationMode,
|
||||
legacyKeystorePassword, legacyKeystoreKeyPassword, legacyKeyPassword, legacyTruststorePassword);
|
||||
}
|
||||
|
@ -222,7 +243,8 @@ public class SSLConfigurationSettings {
|
|||
return Arrays.asList(CIPHERS_SETTING_PROFILES, SUPPORTED_PROTOCOLS_PROFILES, KEYSTORE_PATH_PROFILES,
|
||||
LEGACY_KEYSTORE_PASSWORD_PROFILES, KEYSTORE_PASSWORD_PROFILES, LEGACY_KEYSTORE_KEY_PASSWORD_PROFILES,
|
||||
KEYSTORE_KEY_PASSWORD_PROFILES, TRUST_STORE_PATH_PROFILES, LEGACY_TRUSTSTORE_PASSWORD_PROFILES,
|
||||
TRUSTSTORE_PASSWORD_PROFILES, KEY_STORE_ALGORITHM_PROFILES, TRUST_STORE_ALGORITHM_PROFILES, TRUST_RESTRICTIONS_PROFILES,
|
||||
TRUSTSTORE_PASSWORD_PROFILES, KEY_STORE_ALGORITHM_PROFILES, TRUST_STORE_ALGORITHM_PROFILES,
|
||||
KEY_STORE_TYPE_PROFILES, TRUST_STORE_TYPE_PROFILES, TRUST_RESTRICTIONS_PROFILES,
|
||||
KEY_PATH_PROFILES, LEGACY_KEY_PASSWORD_PROFILES, KEY_PASSWORD_PROFILES,CERT_PROFILES,CAPATH_SETTING_PROFILES,
|
||||
CLIENT_AUTH_SETTING_PROFILES, VERIFICATION_MODE_SETTING_PROFILES);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ import java.util.Objects;
|
|||
class StoreKeyConfig extends KeyConfig {
|
||||
|
||||
final String keyStorePath;
|
||||
final String keyStoreType;
|
||||
final SecureString keyStorePassword;
|
||||
final String keyStoreAlgorithm;
|
||||
final SecureString keyPassword;
|
||||
|
@ -43,14 +44,16 @@ class StoreKeyConfig extends KeyConfig {
|
|||
/**
|
||||
* Creates a new configuration that can be used to load key and trust material from a {@link KeyStore}
|
||||
* @param keyStorePath the path to the keystore file
|
||||
* @param keyStoreType the type of the keystore file
|
||||
* @param keyStorePassword the password for the keystore
|
||||
* @param keyPassword the password for the private key in the keystore
|
||||
* @param keyStoreAlgorithm the algorithm for the keystore
|
||||
* @param trustStoreAlgorithm the algorithm to use when loading as a truststore
|
||||
*/
|
||||
StoreKeyConfig(String keyStorePath, SecureString keyStorePassword, SecureString keyPassword, String keyStoreAlgorithm,
|
||||
String trustStoreAlgorithm) {
|
||||
StoreKeyConfig(String keyStorePath, String keyStoreType, SecureString keyStorePassword, SecureString keyPassword,
|
||||
String keyStoreAlgorithm, String trustStoreAlgorithm) {
|
||||
this.keyStorePath = Objects.requireNonNull(keyStorePath, "keystore path must be specified");
|
||||
this.keyStoreType = Objects.requireNonNull(keyStoreType, "keystore type must be specified");
|
||||
// since we support reloading the keystore, we must store the passphrase in memory for the life of the node, so we
|
||||
// clone the password and never close it during our uses below
|
||||
this.keyStorePassword = Objects.requireNonNull(keyStorePassword, "keystore password must be specified").clone();
|
||||
|
@ -73,7 +76,7 @@ class StoreKeyConfig extends KeyConfig {
|
|||
@Override
|
||||
X509ExtendedTrustManager createTrustManager(@Nullable Environment environment) {
|
||||
try {
|
||||
return CertUtils.trustManager(keyStorePath, keyStorePassword.getChars(), trustStoreAlgorithm, environment);
|
||||
return CertUtils.trustManager(keyStorePath, keyStoreType, keyStorePassword.getChars(), trustStoreAlgorithm, environment);
|
||||
} catch (Exception e) {
|
||||
throw new ElasticsearchException("failed to initialize a TrustManagerFactory", e);
|
||||
}
|
||||
|
@ -107,8 +110,7 @@ class StoreKeyConfig extends KeyConfig {
|
|||
private KeyStore getKeyStore(@Nullable Environment environment)
|
||||
throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
|
||||
try (InputStream in = Files.newInputStream(CertUtils.resolvePath(keyStorePath, environment))) {
|
||||
// TODO remove reliance on JKS since we can use PKCS12 stores in JDK8+...
|
||||
KeyStore ks = KeyStore.getInstance("jks");
|
||||
KeyStore ks = KeyStore.getInstance(keyStoreType);
|
||||
ks.load(in, keyStorePassword.getChars());
|
||||
return ks;
|
||||
}
|
||||
|
@ -154,6 +156,7 @@ class StoreKeyConfig extends KeyConfig {
|
|||
@Override
|
||||
public String toString() {
|
||||
return "keyStorePath=[" + keyStorePath +
|
||||
"], keyStoreType=[" + keyStoreType +
|
||||
"], keyStoreAlgorithm=[" + keyStoreAlgorithm +
|
||||
"], trustStoreAlgorithm=[" + trustStoreAlgorithm +
|
||||
"]";
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.util.Objects;
|
|||
class StoreTrustConfig extends TrustConfig {
|
||||
|
||||
final String trustStorePath;
|
||||
final String trustStoreType;
|
||||
final SecureString trustStorePassword;
|
||||
final String trustStoreAlgorithm;
|
||||
|
||||
|
@ -31,8 +32,9 @@ class StoreTrustConfig extends TrustConfig {
|
|||
* @param trustStorePassword the password for the truststore
|
||||
* @param trustStoreAlgorithm the algorithm to use for reading the truststore
|
||||
*/
|
||||
StoreTrustConfig(String trustStorePath, SecureString trustStorePassword, String trustStoreAlgorithm) {
|
||||
StoreTrustConfig(String trustStorePath, String trustStoreType, SecureString trustStorePassword, String trustStoreAlgorithm) {
|
||||
this.trustStorePath = trustStorePath;
|
||||
this.trustStoreType = trustStoreType;
|
||||
// since we support reloading the truststore, we must store the passphrase in memory for the life of the node, so we
|
||||
// clone the password and never close it during our uses below
|
||||
this.trustStorePassword = Objects.requireNonNull(trustStorePassword, "truststore password must be specified").clone();
|
||||
|
@ -42,7 +44,7 @@ class StoreTrustConfig extends TrustConfig {
|
|||
@Override
|
||||
X509ExtendedTrustManager createTrustManager(@Nullable Environment environment) {
|
||||
try {
|
||||
return CertUtils.trustManager(trustStorePath, trustStorePassword.getChars(), trustStoreAlgorithm, environment);
|
||||
return CertUtils.trustManager(trustStorePath, trustStoreType, trustStorePassword.getChars(), trustStoreAlgorithm, environment);
|
||||
} catch (Exception e) {
|
||||
throw new ElasticsearchException("failed to initialize a TrustManagerFactory", e);
|
||||
}
|
||||
|
|
|
@ -75,13 +75,16 @@ public class SSLConfigurationSettingsTests extends ESTestCase {
|
|||
assertThat(ssl.keyPassword.exists(settings), is(false));
|
||||
assertThat(ssl.keyPath.get(settings).isPresent(), is(false));
|
||||
assertThat(ssl.keystoreAlgorithm.get(settings), is(KeyManagerFactory.getDefaultAlgorithm()));
|
||||
assertThat(ssl.keystoreType.get(settings), is("jks"));
|
||||
assertThat(ssl.keystoreKeyPassword.exists(settings), is(false));
|
||||
assertThat(ssl.keystorePassword.exists(settings), is(false));
|
||||
assertThat(ssl.keystorePath.get(settings).isPresent(), is(false));
|
||||
assertThat(ssl.supportedProtocols.get(settings).size(), is(0));
|
||||
assertThat(ssl.truststoreAlgorithm.get(settings), is(TrustManagerFactory.getDefaultAlgorithm()));
|
||||
assertThat(ssl.truststoreType.get(settings), is("jks"));
|
||||
assertThat(ssl.truststorePassword.exists(settings), is(false));
|
||||
assertThat(ssl.truststorePath.get(settings).isPresent(), is(false));
|
||||
assertThat(ssl.trustRestrictionsPath.get(settings).isPresent(), is(false));
|
||||
assertThat(ssl.verificationMode.get(settings).isPresent(), is(false));
|
||||
}
|
||||
|
||||
|
|
|
@ -5,29 +5,6 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.ssl;
|
||||
|
||||
import org.elasticsearch.client.http.HttpHost;
|
||||
import org.elasticsearch.client.http.HttpResponse;
|
||||
import org.elasticsearch.client.http.client.methods.HttpGet;
|
||||
import org.elasticsearch.client.http.concurrent.FutureCallback;
|
||||
import org.elasticsearch.client.http.conn.ssl.DefaultHostnameVerifier;
|
||||
import org.elasticsearch.client.http.conn.ssl.NoopHostnameVerifier;
|
||||
import org.elasticsearch.client.http.impl.client.CloseableHttpClient;
|
||||
import org.elasticsearch.client.http.impl.client.HttpClients;
|
||||
import org.elasticsearch.client.http.impl.nio.client.CloseableHttpAsyncClient;
|
||||
import org.elasticsearch.client.http.impl.nio.client.HttpAsyncClientBuilder;
|
||||
import org.elasticsearch.client.http.nio.conn.ssl.SSLIOSessionStrategy;
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.CheckedRunnable;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.settings.MockSecureSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.junit.annotations.Network;
|
||||
import org.elasticsearch.xpack.XPackSettings;
|
||||
import org.junit.Before;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
|
@ -45,6 +22,29 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.client.http.HttpHost;
|
||||
import org.elasticsearch.client.http.HttpResponse;
|
||||
import org.elasticsearch.client.http.client.methods.HttpGet;
|
||||
import org.elasticsearch.client.http.concurrent.FutureCallback;
|
||||
import org.elasticsearch.client.http.conn.ssl.DefaultHostnameVerifier;
|
||||
import org.elasticsearch.client.http.conn.ssl.NoopHostnameVerifier;
|
||||
import org.elasticsearch.client.http.impl.client.CloseableHttpClient;
|
||||
import org.elasticsearch.client.http.impl.client.HttpClients;
|
||||
import org.elasticsearch.client.http.impl.nio.client.CloseableHttpAsyncClient;
|
||||
import org.elasticsearch.client.http.impl.nio.client.HttpAsyncClientBuilder;
|
||||
import org.elasticsearch.client.http.nio.conn.ssl.SSLIOSessionStrategy;
|
||||
import org.elasticsearch.common.CheckedRunnable;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.settings.MockSecureSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.junit.annotations.Network;
|
||||
import org.elasticsearch.xpack.XPackSettings;
|
||||
import org.junit.Before;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import static org.hamcrest.Matchers.arrayContainingInAnyOrder;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
@ -64,12 +64,22 @@ import static org.mockito.Mockito.when;
|
|||
public class SSLServiceTests extends ESTestCase {
|
||||
|
||||
private Path testnodeStore;
|
||||
private String testnodeStoreType;
|
||||
private Path testclientStore;
|
||||
private Environment env;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
testnodeStore = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks");
|
||||
// Randomise the keystore type (jks/PKCS#12)
|
||||
if (randomBoolean()) {
|
||||
testnodeStore = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks");
|
||||
// The default is to use JKS. Randomly test with explicit and with the default value.
|
||||
testnodeStoreType = randomBoolean() ? "jks" : null;
|
||||
} else {
|
||||
testnodeStore = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.p12");
|
||||
testnodeStoreType = "PKCS12";
|
||||
}
|
||||
logger.info("Using [{}] key/truststore [{}]", testnodeStoreType, testnodeStore);
|
||||
testclientStore = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.jks");
|
||||
env = new Environment(Settings.builder().put("path.home", createTempDir()).build());
|
||||
}
|
||||
|
@ -81,6 +91,7 @@ public class SSLServiceTests extends ESTestCase {
|
|||
secureSettings.setString("transport.profiles.foo.xpack.security.ssl.truststore.secure_password", "testclient");
|
||||
Settings settings = Settings.builder()
|
||||
.put("xpack.ssl.truststore.path", testnodeStore)
|
||||
.put("xpack.ssl.truststore.type", testnodeStoreType)
|
||||
.setSecureSettings(secureSettings)
|
||||
.put("transport.profiles.foo.xpack.security.ssl.truststore.path", testClientStore)
|
||||
.build();
|
||||
|
@ -105,6 +116,7 @@ public class SSLServiceTests extends ESTestCase {
|
|||
secureSettings.setString("xpack.ssl.keystore.secure_password", "testnode");
|
||||
Settings settings = Settings.builder()
|
||||
.put("xpack.ssl.keystore.path", testnodeStore)
|
||||
.put("xpack.ssl.keystore.type", testnodeStoreType)
|
||||
.setSecureSettings(secureSettings)
|
||||
.build();
|
||||
SSLService sslService = new SSLService(settings, env);
|
||||
|
@ -150,6 +162,7 @@ public class SSLServiceTests extends ESTestCase {
|
|||
secureSettings.setString("xpack.ssl.keystore.secure_password", "testnode");
|
||||
Settings settings = Settings.builder()
|
||||
.put("xpack.ssl.keystore.path", testnodeStore)
|
||||
.put("xpack.ssl.keystore.type", testnodeStoreType)
|
||||
.setSecureSettings(secureSettings)
|
||||
.build();
|
||||
SSLService sslService = new SSLService(settings, env);
|
||||
|
@ -181,6 +194,7 @@ public class SSLServiceTests extends ESTestCase {
|
|||
secureSettings.setString("xpack.ssl.keystore.secure_password", "testnode");
|
||||
Settings settings = Settings.builder()
|
||||
.put("xpack.ssl.keystore.path", testnodeStore)
|
||||
.put("xpack.ssl.keystore.type", testnodeStoreType)
|
||||
.setSecureSettings(secureSettings)
|
||||
.build();
|
||||
SSLService sslService = new SSLService(settings, env);
|
||||
|
@ -193,6 +207,7 @@ public class SSLServiceTests extends ESTestCase {
|
|||
secureSettings.setString("xpack.ssl.truststore.secure_password", "testnode");
|
||||
Settings settings = Settings.builder()
|
||||
.put("xpack.ssl.truststore.path", testnodeStore)
|
||||
.put("xpack.ssl.truststore.type", testnodeStoreType)
|
||||
.setSecureSettings(secureSettings)
|
||||
.build();
|
||||
SSLService sslService = new SSLService(settings, env);
|
||||
|
@ -201,8 +216,10 @@ public class SSLServiceTests extends ESTestCase {
|
|||
secureSettings.setString("xpack.security.transport.ssl.keystore.secure_password", "testnode");
|
||||
settings = Settings.builder()
|
||||
.put("xpack.ssl.truststore.path", testnodeStore)
|
||||
.put("xpack.ssl.truststore.type", testnodeStoreType)
|
||||
.setSecureSettings(secureSettings)
|
||||
.put("xpack.security.transport.ssl.keystore.path", testnodeStore)
|
||||
.put("xpack.security.transport.ssl.keystore.type", testnodeStoreType)
|
||||
.build();
|
||||
sslService = new SSLService(settings, env);
|
||||
assertFalse(sslService.isConfigurationValidForServerUsage(sslService.sslConfiguration(Settings.EMPTY)));
|
||||
|
@ -268,8 +285,10 @@ public class SSLServiceTests extends ESTestCase {
|
|||
secureSettings.setString("xpack.ssl.keystore.secure_password", "testnode");
|
||||
Settings settings = Settings.builder()
|
||||
.put("xpack.ssl.keystore.path", testnodeStore)
|
||||
.put("xpack.ssl.keystore.type", testnodeStoreType)
|
||||
.setSecureSettings(secureSettings)
|
||||
.put("xpack.ssl.truststore.path", testnodeStore)
|
||||
.put("xpack.ssl.truststore.type", testnodeStoreType)
|
||||
.build();
|
||||
ElasticsearchException e =
|
||||
expectThrows(ElasticsearchException.class, () -> new SSLService(settings, env));
|
||||
|
@ -279,6 +298,7 @@ public class SSLServiceTests extends ESTestCase {
|
|||
public void testThatKeystorePasswordIsRequired() throws Exception {
|
||||
Settings settings = Settings.builder()
|
||||
.put("xpack.ssl.keystore.path", testnodeStore)
|
||||
.put("xpack.ssl.keystore.type", testnodeStoreType)
|
||||
.build();
|
||||
ElasticsearchException e =
|
||||
expectThrows(ElasticsearchException.class, () -> new SSLService(settings, env));
|
||||
|
@ -293,6 +313,7 @@ public class SSLServiceTests extends ESTestCase {
|
|||
secureSettings.setString("xpack.ssl.keystore.secure_password", "testnode");
|
||||
Settings settings = Settings.builder()
|
||||
.put("xpack.ssl.keystore.path", testnodeStore)
|
||||
.put("xpack.ssl.keystore.type", testnodeStoreType)
|
||||
.setSecureSettings(secureSettings)
|
||||
.putArray("xpack.ssl.ciphers", ciphers.toArray(new String[ciphers.size()]))
|
||||
.build();
|
||||
|
@ -309,6 +330,7 @@ public class SSLServiceTests extends ESTestCase {
|
|||
|
||||
Settings settings = Settings.builder()
|
||||
.put("xpack.ssl.keystore.path", testnodeStore)
|
||||
.put("xpack.ssl.keystore.type", testnodeStoreType)
|
||||
.setSecureSettings(secureSettings)
|
||||
.putArray("xpack.ssl.cipher_suites", new String[]{"foo", "bar"})
|
||||
.build();
|
||||
|
@ -322,6 +344,7 @@ public class SSLServiceTests extends ESTestCase {
|
|||
secureSettings.setString("xpack.ssl.keystore.secure_password", "testnode");
|
||||
Settings settings = Settings.builder()
|
||||
.put("xpack.ssl.keystore.path", testnodeStore)
|
||||
.put("xpack.ssl.keystore.type", testnodeStoreType)
|
||||
.setSecureSettings(secureSettings)
|
||||
.build();
|
||||
SSLService sslService = new SSLService(settings, env);
|
||||
|
@ -335,6 +358,7 @@ public class SSLServiceTests extends ESTestCase {
|
|||
secureSettings.setString("xpack.ssl.keystore.secure_password", "testnode");
|
||||
Settings settings = Settings.builder()
|
||||
.put("xpack.ssl.keystore.path", testnodeStore)
|
||||
.put("xpack.ssl.keystore.type", testnodeStoreType)
|
||||
.setSecureSettings(secureSettings)
|
||||
.build();
|
||||
SSLService sslService = new SSLService(settings, env);
|
||||
|
@ -359,6 +383,7 @@ public class SSLServiceTests extends ESTestCase {
|
|||
secureSettings.setString("xpack.ssl.keystore.secure_password", "testnode");
|
||||
Settings settings = Settings.builder()
|
||||
.put("xpack.ssl.keystore.path", testnodeStore)
|
||||
.put("xpack.ssl.keystore.type", testnodeStoreType)
|
||||
.setSecureSettings(secureSettings)
|
||||
.build();
|
||||
SSLService sslService = new SSLService(settings, env);
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* 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.ssl;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509ExtendedKeyManager;
|
||||
import java.security.PrivateKey;
|
||||
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
|
||||
public class StoreKeyConfigTests extends ESTestCase {
|
||||
|
||||
public void testCreateKeyManagerUsingJKS() throws Exception {
|
||||
tryReadPrivateKeyFromKeyStore("jks", ".jks");
|
||||
}
|
||||
|
||||
public void testCreateKeyManagerUsingPKCS12() throws Exception {
|
||||
tryReadPrivateKeyFromKeyStore("PKCS12", ".p12");
|
||||
}
|
||||
|
||||
private void tryReadPrivateKeyFromKeyStore(String type, String extension) {
|
||||
final Settings settings = Settings.builder().put("path.home", createTempDir()).build();
|
||||
final String path = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode" + extension).toString();
|
||||
final SecureString keyStorePassword = new SecureString("testnode".toCharArray());
|
||||
final StoreKeyConfig keyConfig = new StoreKeyConfig(path, type, keyStorePassword, keyStorePassword,
|
||||
KeyManagerFactory.getDefaultAlgorithm(), TrustManagerFactory.getDefaultAlgorithm());
|
||||
final X509ExtendedKeyManager keyManager = keyConfig.createKeyManager(new Environment(settings));
|
||||
final PrivateKey key = keyManager.getPrivateKey("testnode");
|
||||
assertThat(key, notNullValue());
|
||||
assertThat(key.getAlgorithm(), equalTo("RSA"));
|
||||
assertThat(key.getFormat(), equalTo("PKCS#8"));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue