Skip to content

Commit 046595d

Browse files
authored
Do not load SSLService in plugin contructor (#49667)
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. Relates: #44536
1 parent a16702c commit 046595d

File tree

3 files changed

+39
-16
lines changed

3 files changed

+39
-16
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
@@ -134,10 +134,10 @@ public XPackPlugin(
134134
final Settings settings,
135135
final Path configPath) {
136136
super(settings);
137+
// FIXME: The settings might be changed after this (e.g. from "additionalSettings" method in other plugins)
138+
// We should only depend on the settings from the Environment object passed to createComponents
137139
this.settings = settings;
138-
Environment env = new Environment(settings, configPath);
139140

140-
setSslService(new SSLService(settings, env));
141141
setLicenseState(new XPackLicenseState(settings));
142142

143143
this.licensing = new Licensing(settings);
@@ -154,7 +154,14 @@ protected Clock getClock() {
154154
protected void setSslService(SSLService sslService) { XPackPlugin.sslService.set(sslService); }
155155
protected void setLicenseService(LicenseService licenseService) { XPackPlugin.licenseService.set(licenseService); }
156156
protected void setLicenseState(XPackLicenseState licenseState) { XPackPlugin.licenseState.set(licenseState); }
157-
public static SSLService getSharedSslService() { return sslService.get(); }
157+
158+
public static SSLService getSharedSslService() {
159+
final SSLService ssl = XPackPlugin.sslService.get();
160+
if (ssl == null) {
161+
throw new IllegalStateException("SSL Service is not constructed yet");
162+
}
163+
return ssl;
164+
}
158165
public static LicenseService getSharedLicenseService() { return licenseService.get(); }
159166
public static XPackLicenseState getSharedLicenseState() { return licenseState.get(); }
160167

@@ -225,14 +232,16 @@ public Collection<Object> createComponents(Client client, ClusterService cluster
225232
NodeEnvironment nodeEnvironment, NamedWriteableRegistry namedWriteableRegistry) {
226233
List<Object> components = new ArrayList<>();
227234

235+
final SSLService sslService = new SSLService(environment);
236+
setSslService(sslService);
228237
// just create the reloader as it will pull all of the loaded ssl configurations and start watching them
229-
new SSLConfigurationReloader(environment, getSslService(), resourceWatcherService);
238+
new SSLConfigurationReloader(environment, sslService, resourceWatcherService);
230239

231240
setLicenseService(new LicenseService(settings, clusterService, getClock(),
232241
environment, resourceWatcherService, getLicenseState()));
233242

234243
// It is useful to override these as they are what guice is injecting into actions
235-
components.add(getSslService());
244+
components.add(sslService);
236245
components.add(getLicenseService());
237246
components.add(getLicenseState());
238247

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

+8
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,14 @@ public class SSLService {
122122
private final SetOnce<SSLConfiguration> transportSSLConfiguration = new SetOnce<>();
123123
private final Environment env;
124124

125+
/**
126+
* Create a new SSLService using the {@code Settings} from {@link Environment#settings()}.
127+
* @see #SSLService(Settings, Environment)
128+
*/
129+
public SSLService(Environment environment) {
130+
this(environment.settings(), environment);
131+
}
132+
125133
/**
126134
* Create a new SSLService that parses the settings for the ssl contexts that need to be created, creates them, and then caches them
127135
* for use later

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

+17-11
Original file line numberDiff line numberDiff line change
@@ -293,32 +293,27 @@ public class Security extends Plugin implements ActionPlugin, IngestPlugin, Netw
293293
private final SetOnce<SecurityIndexManager> securityIndex = new SetOnce<>();
294294
private final SetOnce<NioGroupFactory> groupFactory = new SetOnce<>();
295295
private final SetOnce<DocumentSubsetBitsetCache> dlsBitsetCache = new SetOnce<>();
296-
private final List<BootstrapCheck> bootstrapChecks;
296+
private final SetOnce<List<BootstrapCheck>> bootstrapChecks = new SetOnce<>();
297297
private final List<SecurityExtension> securityExtensions = new ArrayList<>();
298298

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

303303
Security(Settings settings, final Path configPath, List<SecurityExtension> extensions) {
304+
// TODO This is wrong. Settings can change after this. We should use the settings from createComponents
304305
this.settings = settings;
306+
// TODO this is wrong, we should only use the environment that is provided to createComponents
305307
this.env = new Environment(settings, configPath);
306308
this.enabled = XPackSettings.SECURITY_ENABLED.get(settings);
307309
if (enabled) {
308310
runStartupChecks(settings);
309311
// we load them all here otherwise we can't access secure settings since they are closed once the checks are
310312
// fetched
311-
final List<BootstrapCheck> checks = new ArrayList<>();
312-
checks.addAll(Arrays.asList(
313-
new ApiKeySSLBootstrapCheck(),
314-
new TokenSSLBootstrapCheck(),
315-
new PkiRealmBootstrapCheck(getSslService()),
316-
new TLSLicenseBootstrapCheck()));
317-
checks.addAll(InternalRealms.getBootstrapChecks(settings, env));
318-
this.bootstrapChecks = Collections.unmodifiableList(checks);
313+
319314
Automatons.updateConfiguration(settings);
320315
} else {
321-
this.bootstrapChecks = Collections.emptyList();
316+
this.bootstrapChecks.set(Collections.emptyList());
322317
}
323318
this.securityExtensions.addAll(extensions);
324319

@@ -358,6 +353,17 @@ Collection<Object> createComponents(Client client, ThreadPool threadPool, Cluste
358353
return Collections.singletonList(new SecurityUsageServices(null, null, null, null));
359354
}
360355

356+
// We need to construct the checks here while the secure settings are still available.
357+
// If we wait until #getBoostrapChecks the secure settings will have been cleared/closed.
358+
final List<BootstrapCheck> checks = new ArrayList<>();
359+
checks.addAll(Arrays.asList(
360+
new ApiKeySSLBootstrapCheck(),
361+
new TokenSSLBootstrapCheck(),
362+
new PkiRealmBootstrapCheck(getSslService()),
363+
new TLSLicenseBootstrapCheck()));
364+
checks.addAll(InternalRealms.getBootstrapChecks(settings, env));
365+
this.bootstrapChecks.set(Collections.unmodifiableList(checks));
366+
361367
threadContext.set(threadPool.getThreadContext());
362368
List<Object> components = new ArrayList<>();
363369
securityContext.set(new SecurityContext(settings, threadPool.getThreadContext()));
@@ -646,7 +652,7 @@ public List<String> getSettingsFilter() {
646652

647653
@Override
648654
public List<BootstrapCheck> getBootstrapChecks() {
649-
return bootstrapChecks;
655+
return bootstrapChecks.get();
650656
}
651657

652658
@Override

0 commit comments

Comments
 (0)