Skip to content

Commit c662565

Browse files
authored
Access SSL contexts using names instead of Settings (#30953)
Historically we have loaded SSL objects (such as SSLContext, SSLIOSessionStrategy) by passing in the SSL settings, constructing a new SSL configuration from those settings and then looking for a cached object that matches those settings. The primary issue with this approach is that it requires a fully configured Settings object to be available any time the SSL context needs to be loaded. If the Settings include SecureSettings (such as passwords for keys or keystores) then this is not true, and the cached SSL object cannot be loaded at runtime. This commit introduces an alternative approach of naming every cached ssl configuration, so that it is possible to load the SSL context for a named configuration (such as "xpack.http.ssl"). This means that the calling code does not need to have ongoing access to the secure settings that were used to load the configuration. This change also allows monitoring exporters to use SSL passwords from secure settings, however an exporter that uses a secure SSL setting (e.g. truststore.secure_password) may not have its SSL settings updated dynamically (this is prevented by a settings validator). Exporters without secure settings can continue to be defined and updated dynamically.
1 parent 332c134 commit c662565

File tree

34 files changed

+844
-411
lines changed

34 files changed

+844
-411
lines changed

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/transport/netty4/SecurityNetty4Transport.java

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@
2828
import org.elasticsearch.xpack.core.ssl.SSLService;
2929

3030
import javax.net.ssl.SSLEngine;
31-
3231
import java.net.InetSocketAddress;
3332
import java.net.SocketAddress;
3433
import java.util.Collections;
3534
import java.util.HashMap;
3635
import java.util.Map;
36+
import java.util.Set;
3737

3838
import static org.elasticsearch.xpack.core.security.SecurityField.setting;
3939

@@ -58,29 +58,31 @@ public SecurityNetty4Transport(
5858
super(settings, threadPool, networkService, bigArrays, namedWriteableRegistry, circuitBreakerService);
5959
this.sslService = sslService;
6060
this.sslEnabled = XPackSettings.TRANSPORT_SSL_ENABLED.get(settings);
61-
final Settings transportSSLSettings = settings.getByPrefix(setting("transport.ssl."));
6261
if (sslEnabled) {
63-
this.sslConfiguration = sslService.sslConfiguration(transportSSLSettings, Settings.EMPTY);
64-
Map<String, Settings> profileSettingsMap = settings.getGroups("transport.profiles.", true);
65-
Map<String, SSLConfiguration> profileConfiguration = new HashMap<>(profileSettingsMap.size() + 1);
66-
for (Map.Entry<String, Settings> entry : profileSettingsMap.entrySet()) {
67-
Settings profileSettings = entry.getValue();
68-
final Settings profileSslSettings = profileSslSettings(profileSettings);
69-
SSLConfiguration configuration = sslService.sslConfiguration(profileSslSettings, transportSSLSettings);
70-
profileConfiguration.put(entry.getKey(), configuration);
71-
}
72-
73-
if (profileConfiguration.containsKey(TcpTransport.DEFAULT_PROFILE) == false) {
74-
profileConfiguration.put(TcpTransport.DEFAULT_PROFILE, sslConfiguration);
75-
}
76-
62+
this.sslConfiguration = sslService.getSSLConfiguration(setting("transport.ssl."));
63+
Map<String, SSLConfiguration> profileConfiguration = getTransportProfileConfigurations(settings, sslService, sslConfiguration);
7764
this.profileConfiguration = Collections.unmodifiableMap(profileConfiguration);
7865
} else {
7966
this.profileConfiguration = Collections.emptyMap();
8067
this.sslConfiguration = null;
8168
}
8269
}
8370

71+
public static Map<String, SSLConfiguration> getTransportProfileConfigurations(Settings settings, SSLService sslService,
72+
SSLConfiguration defaultConfiguration) {
73+
Set<String> profileNames = settings.getGroups("transport.profiles.", true).keySet();
74+
Map<String, SSLConfiguration> profileConfiguration = new HashMap<>(profileNames.size() + 1);
75+
for (String profileName : profileNames) {
76+
SSLConfiguration configuration = sslService.getSSLConfiguration("transport.profiles." + profileName + "." + setting("ssl"));
77+
profileConfiguration.put(profileName, configuration);
78+
}
79+
80+
if (profileConfiguration.containsKey(TcpTransport.DEFAULT_PROFILE) == false) {
81+
profileConfiguration.put(TcpTransport.DEFAULT_PROFILE, defaultConfiguration);
82+
}
83+
return profileConfiguration;
84+
}
85+
8486
@Override
8587
protected void doStart() {
8688
super.doStart();
@@ -209,8 +211,4 @@ public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress,
209211
super.connect(ctx, remoteAddress, localAddress, promise);
210212
}
211213
}
212-
213-
public static Settings profileSslSettings(Settings profileSettings) {
214-
return profileSettings.getByPrefix(setting("ssl."));
215-
}
216214
}

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationSettings.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import java.util.Locale;
2323
import java.util.Optional;
2424
import java.util.function.Function;
25+
import java.util.stream.Collectors;
26+
import java.util.stream.Stream;
2527

2628
/**
2729
* Bridges SSLConfiguration into the {@link Settings} framework, using {@link Setting} objects.
@@ -221,4 +223,10 @@ public static Collection<Setting<?>> getProfileSettings() {
221223
CLIENT_AUTH_SETTING_PROFILES, VERIFICATION_MODE_SETTING_PROFILES);
222224
}
223225

226+
public List<Setting<SecureString>> getSecureSettingsInUse(Settings settings) {
227+
return Stream.of(this.truststorePassword, this.x509KeyPair.keystorePassword,
228+
this.x509KeyPair.keystoreKeyPassword, this.x509KeyPair.keyPassword)
229+
.filter(s -> s.exists(settings))
230+
.collect(Collectors.toList());
231+
}
224232
}

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLService.java

Lines changed: 115 additions & 126 deletions
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
package org.elasticsearch.xpack.core.security.transport.netty4;
8+
9+
import org.elasticsearch.common.settings.Settings;
10+
import org.elasticsearch.env.Environment;
11+
import org.elasticsearch.env.TestEnvironment;
12+
import org.elasticsearch.test.ESTestCase;
13+
import org.elasticsearch.xpack.core.ssl.SSLConfiguration;
14+
import org.elasticsearch.xpack.core.ssl.SSLService;
15+
import org.elasticsearch.xpack.core.ssl.VerificationMode;
16+
import org.hamcrest.Matchers;
17+
18+
import java.util.Map;
19+
20+
import static org.elasticsearch.xpack.core.security.transport.netty4.SecurityNetty4Transport.getTransportProfileConfigurations;
21+
22+
public class SecurityNetty4TransportTests extends ESTestCase {
23+
24+
public void testGetTransportProfileConfigurations() {
25+
final Settings settings = Settings.builder()
26+
.put("path.home", createTempDir())
27+
.put("xpack.security.transport.ssl.verification_mode", VerificationMode.CERTIFICATE.name())
28+
.put("transport.profiles.full.xpack.security.ssl.verification_mode", VerificationMode.FULL.name())
29+
.put("transport.profiles.cert.xpack.security.ssl.verification_mode", VerificationMode.CERTIFICATE.name())
30+
.put("transport.profiles.none.xpack.security.ssl.verification_mode", VerificationMode.NONE.name())
31+
.build();
32+
final Environment env = TestEnvironment.newEnvironment(settings);
33+
SSLService sslService = new SSLService(settings, env);
34+
final SSLConfiguration defaultConfig = sslService.getSSLConfiguration("xpack.security.transport.ssl");
35+
final Map<String, SSLConfiguration> profileConfigurations = getTransportProfileConfigurations(settings, sslService, defaultConfig);
36+
assertThat(profileConfigurations.size(), Matchers.equalTo(4));
37+
assertThat(profileConfigurations.keySet(), Matchers.containsInAnyOrder("full", "cert", "none", "default"));
38+
assertThat(profileConfigurations.get("full").verificationMode(), Matchers.equalTo(VerificationMode.FULL));
39+
assertThat(profileConfigurations.get("cert").verificationMode(), Matchers.equalTo(VerificationMode.CERTIFICATE));
40+
assertThat(profileConfigurations.get("none").verificationMode(), Matchers.equalTo(VerificationMode.NONE));
41+
assertThat(profileConfigurations.get("default"), Matchers.sameInstance(defaultConfig));
42+
}
43+
}

x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationReloaderTests.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ public void testReloadingKeyStoreException() throws Exception {
303303
.build();
304304
Environment env = randomBoolean() ? null : TestEnvironment.newEnvironment(settings);
305305
final SSLService sslService = new SSLService(settings, env);
306-
final SSLConfiguration config = sslService.sslConfiguration(Settings.EMPTY);
306+
final SSLConfiguration config = sslService.getSSLConfiguration("xpack.ssl");
307307
new SSLConfigurationReloader(settings, env, sslService, resourceWatcherService) {
308308
@Override
309309
void reloadSSLContext(SSLConfiguration configuration) {
@@ -344,7 +344,7 @@ public void testReloadingPEMKeyConfigException() throws Exception {
344344
.build();
345345
Environment env = randomBoolean() ? null : TestEnvironment.newEnvironment(settings);
346346
final SSLService sslService = new SSLService(settings, env);
347-
final SSLConfiguration config = sslService.sslConfiguration(Settings.EMPTY);
347+
final SSLConfiguration config = sslService.getSSLConfiguration("xpack.ssl");
348348
new SSLConfigurationReloader(settings, env, sslService, resourceWatcherService) {
349349
@Override
350350
void reloadSSLContext(SSLConfiguration configuration) {
@@ -379,7 +379,7 @@ public void testTrustStoreReloadException() throws Exception {
379379
.build();
380380
Environment env = randomBoolean() ? null : TestEnvironment.newEnvironment(settings);
381381
final SSLService sslService = new SSLService(settings, env);
382-
final SSLConfiguration config = sslService.sslConfiguration(Settings.EMPTY);
382+
final SSLConfiguration config = sslService.getSSLConfiguration("xpack.ssl");
383383
new SSLConfigurationReloader(settings, env, sslService, resourceWatcherService) {
384384
@Override
385385
void reloadSSLContext(SSLConfiguration configuration) {
@@ -411,7 +411,7 @@ public void testPEMTrustReloadException() throws Exception {
411411
.build();
412412
Environment env = randomBoolean() ? null : TestEnvironment.newEnvironment(settings);
413413
final SSLService sslService = new SSLService(settings, env);
414-
final SSLConfiguration config = sslService.sslConfiguration(Settings.EMPTY);
414+
final SSLConfiguration config = sslService.getSSLConfiguration("xpack.ssl");
415415
new SSLConfigurationReloader(settings, env, sslService, resourceWatcherService) {
416416
@Override
417417
void reloadSSLContext(SSLConfiguration configuration) {
@@ -440,7 +440,7 @@ private void validateSSLConfigurationIsReloaded(Settings settings, Environment e
440440

441441
final CountDownLatch reloadLatch = new CountDownLatch(1);
442442
final SSLService sslService = new SSLService(settings, env);
443-
final SSLConfiguration config = sslService.sslConfiguration(Settings.EMPTY);
443+
final SSLConfiguration config = sslService.getSSLConfiguration("xpack.ssl");
444444
new SSLConfigurationReloader(settings, env, sslService, resourceWatcherService) {
445445
@Override
446446
void reloadSSLContext(SSLConfiguration configuration) {

0 commit comments

Comments
 (0)