Skip to content

Commit cad0f6b

Browse files
authored
Do not load SSLService in plugin contructor (#50519)
XPackPlugin created an SSLService within the plugin contructor. This has 2 negative consequences: 1. The service may be constructed based on a partial view of settings. Other plugins are free to add setting values via the additionalSettings() method, but this (necessarily) happens after plugins have been constructed. 2. Any exceptions thrown during the plugin construction are handled differently than exceptions thrown during "createComponents". Since SSL configurations exceptions are relatively common, it is far preferable for them to be thrown and handled as part of the createComponents flow. This commit moves the creation of the SSLService to XPackPlugin.createComponents, and alters the sequence of some other steps to accommodate this change. Backport of: #49667
1 parent 72840c0 commit cad0f6b

File tree

3 files changed

+40
-17
lines changed

3 files changed

+40
-17
lines changed

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

+14-5
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,11 @@ public XPackPlugin(
135135
final Settings settings,
136136
final Path configPath) {
137137
super(settings);
138+
// FIXME: The settings might be changed after this (e.g. from "additionalSettings" method in other plugins)
139+
// We should only depend on the settings from the Environment object passed to createComponents
138140
this.settings = settings;
139141
this.transportClientMode = transportClientMode(settings);
140-
Environment env = transportClientMode ? null : new Environment(settings, configPath);
141142

142-
setSslService(new SSLService(settings, env));
143143
setLicenseState(new XPackLicenseState(settings));
144144

145145
this.licensing = new Licensing(settings);
@@ -156,7 +156,14 @@ protected Clock getClock() {
156156
protected void setSslService(SSLService sslService) { XPackPlugin.sslService.set(sslService); }
157157
protected void setLicenseService(LicenseService licenseService) { XPackPlugin.licenseService.set(licenseService); }
158158
protected void setLicenseState(XPackLicenseState licenseState) { XPackPlugin.licenseState.set(licenseState); }
159-
public static SSLService getSharedSslService() { return sslService.get(); }
159+
160+
public static SSLService getSharedSslService() {
161+
final SSLService ssl = XPackPlugin.sslService.get();
162+
if (ssl == null) {
163+
throw new IllegalStateException("SSL Service is not constructed yet");
164+
}
165+
return ssl;
166+
}
160167
public static LicenseService getSharedLicenseService() { return licenseService.get(); }
161168
public static XPackLicenseState getSharedLicenseState() { return licenseState.get(); }
162169

@@ -249,14 +256,16 @@ public Collection<Object> createComponents(Client client, ClusterService cluster
249256
NodeEnvironment nodeEnvironment, NamedWriteableRegistry namedWriteableRegistry) {
250257
List<Object> components = new ArrayList<>();
251258

259+
final SSLService sslService = new SSLService(environment);
260+
setSslService(sslService);
252261
// just create the reloader as it will pull all of the loaded ssl configurations and start watching them
253-
new SSLConfigurationReloader(environment, getSslService(), resourceWatcherService);
262+
new SSLConfigurationReloader(environment, sslService, resourceWatcherService);
254263

255264
setLicenseService(new LicenseService(settings, clusterService, getClock(),
256265
environment, resourceWatcherService, getLicenseState()));
257266

258267
// It is useful to override these as they are what guice is injecting into actions
259-
components.add(getSslService());
268+
components.add(sslService);
260269
components.add(getLicenseService());
261270
components.add(getLicenseState());
262271

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

+8
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,14 @@ public class SSLService {
128128
private final SetOnce<SSLConfiguration> transportSSLConfiguration = new SetOnce<>();
129129
private final Environment env;
130130

131+
/**
132+
* Create a new SSLService using the {@code Settings} from {@link Environment#settings()}.
133+
* @see #SSLService(Settings, Environment)
134+
*/
135+
public SSLService(Environment environment) {
136+
this(environment.settings(), environment);
137+
}
138+
131139
/**
132140
* Create a new SSLService that parses the settings for the ssl contexts that need to be created, creates them, and then caches them
133141
* for use later

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java

+18-12
Original file line numberDiff line numberDiff line change
@@ -294,33 +294,28 @@ public class Security extends Plugin implements ActionPlugin, IngestPlugin, Netw
294294
private final SetOnce<SecurityIndexManager> securityIndex = new SetOnce<>();
295295
private final SetOnce<NioGroupFactory> groupFactory = new SetOnce<>();
296296
private final SetOnce<DocumentSubsetBitsetCache> dlsBitsetCache = new SetOnce<>();
297-
private final List<BootstrapCheck> bootstrapChecks;
297+
private final SetOnce<List<BootstrapCheck>> bootstrapChecks = new SetOnce<>();
298298
private final List<SecurityExtension> securityExtensions = new ArrayList<>();
299299

300300
public Security(Settings settings, final Path configPath) {
301301
this(settings, configPath, Collections.emptyList());
302302
}
303303

304304
Security(Settings settings, final Path configPath, List<SecurityExtension> extensions) {
305+
// TODO This is wrong. Settings can change after this. We should use the settings from createComponents
305306
this.settings = settings;
306307
this.transportClientMode = XPackPlugin.transportClientMode(settings);
308+
// TODO this is wrong, we should only use the environment that is provided to createComponents
307309
this.env = transportClientMode ? null : new Environment(settings, configPath);
308310
this.enabled = XPackSettings.SECURITY_ENABLED.get(settings);
309311
if (enabled && transportClientMode == false) {
310312
runStartupChecks(settings);
311313
// we load them all here otherwise we can't access secure settings since they are closed once the checks are
312314
// fetched
313-
final List<BootstrapCheck> checks = new ArrayList<>();
314-
checks.addAll(Arrays.asList(
315-
new ApiKeySSLBootstrapCheck(),
316-
new TokenSSLBootstrapCheck(),
317-
new PkiRealmBootstrapCheck(getSslService()),
318-
new TLSLicenseBootstrapCheck()));
319-
checks.addAll(InternalRealms.getBootstrapChecks(settings, env));
320-
this.bootstrapChecks = Collections.unmodifiableList(checks);
315+
321316
Automatons.updateConfiguration(settings);
322317
} else {
323-
this.bootstrapChecks = Collections.emptyList();
318+
this.bootstrapChecks.set(Collections.emptyList());
324319
}
325320
this.securityExtensions.addAll(extensions);
326321

@@ -346,7 +341,7 @@ public Collection<Module> createGuiceModules() {
346341
}
347342
modules.add(b -> {
348343
// for transport client we still must inject these ssl classes with guice
349-
b.bind(SSLService.class).toInstance(getSslService());
344+
b.bind(SSLService.class).toProvider(this::getSslService);
350345
});
351346

352347
return modules;
@@ -403,6 +398,17 @@ Collection<Object> createComponents(Client client, ThreadPool threadPool, Cluste
403398
return Collections.emptyList();
404399
}
405400

401+
// We need to construct the checks here while the secure settings are still available.
402+
// If we wait until #getBoostrapChecks the secure settings will have been cleared/closed.
403+
final List<BootstrapCheck> checks = new ArrayList<>();
404+
checks.addAll(Arrays.asList(
405+
new ApiKeySSLBootstrapCheck(),
406+
new TokenSSLBootstrapCheck(),
407+
new PkiRealmBootstrapCheck(getSslService()),
408+
new TLSLicenseBootstrapCheck()));
409+
checks.addAll(InternalRealms.getBootstrapChecks(settings, env));
410+
this.bootstrapChecks.set(Collections.unmodifiableList(checks));
411+
406412
threadContext.set(threadPool.getThreadContext());
407413
List<Object> components = new ArrayList<>();
408414
securityContext.set(new SecurityContext(settings, threadPool.getThreadContext()));
@@ -698,7 +704,7 @@ public List<String> getSettingsFilter() {
698704

699705
@Override
700706
public List<BootstrapCheck> getBootstrapChecks() {
701-
return bootstrapChecks;
707+
return bootstrapChecks.get();
702708
}
703709

704710
@Override

0 commit comments

Comments
 (0)