diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/InitialNodeSecurityAutoConfiguration.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/InitialNodeSecurityAutoConfiguration.java index 2971e23984b8..5a2284ed2183 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/InitialNodeSecurityAutoConfiguration.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/InitialNodeSecurityAutoConfiguration.java @@ -29,7 +29,6 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import java.util.concurrent.CountDownLatch; import static org.elasticsearch.xpack.core.XPackSettings.ENROLLMENT_ENABLED; import static org.elasticsearch.xpack.security.authc.esnative.ReservedRealm.AUTOCONFIG_ELASTIC_PASSWORD_HASH; @@ -55,7 +54,7 @@ public static void maybeGenerateEnrollmentTokensAndElasticCredentialsOnNodeStart SSLService sslService, Client client, Environment environment, - CountDownLatch nodeStartedSignal, + OnNodeStartedListener onNodeStartedListener, ThreadPool threadPool ) { // Assume the following auto-configuration must NOT run if enrollment is disabled when the node starts, @@ -95,7 +94,7 @@ public static void maybeGenerateEnrollmentTokensAndElasticCredentialsOnNodeStart // TODO maybe we can improve the check that this is indeed the initial node // a lot of stuff runs when a node just started, and the autoconfiguration is not time-critical // and nothing else depends on it; be a good sport and wait a couple - threadPool.schedule(new AbstractRunnable() { + onNodeStartedListener.run(() -> threadPool.schedule(new AbstractRunnable() { @Override public void onFailure(Exception e) { @@ -103,9 +102,8 @@ public void onFailure(Exception e) { } @Override - protected void doRun() throws Exception { + protected void doRun() { // the HTTP address is guaranteed to be bound only after the node started - nodeStartedSignal.await(); String fingerprint; try { fingerprint = enrollmentTokenGenerator.getHttpsCaFingerprint(); @@ -136,7 +134,7 @@ protected void doRun() throws Exception { httpsCaFingerprint, out ); - }, e -> { LOGGER.error("Unexpected exception during security auto-configuration", e); }), + }, e -> LOGGER.error("Unexpected exception during security auto-configuration", e)), 3 ); // we only generate the elastic user password if the node has been auto-configured in a specific way, such that the @@ -188,7 +186,7 @@ protected void doRun() throws Exception { } }, backoff); } - }, TimeValue.timeValueSeconds(9), ThreadPool.Names.GENERIC); + }, TimeValue.timeValueSeconds(9), ThreadPool.Names.GENERIC)); } }); } @@ -279,4 +277,8 @@ private static void outputInformationToConsole( builder.append(System.lineSeparator()); out.println(builder); } + + interface OnNodeStartedListener { + void run(Runnable runnable); + } } diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java index 202c24b6a892..d565b08a6d6a 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java @@ -40,6 +40,7 @@ import org.elasticsearch.common.util.BigArrays; import org.elasticsearch.common.util.PageCacheRecycler; import org.elasticsearch.common.util.concurrent.EsExecutors; +import org.elasticsearch.common.util.concurrent.ListenableFuture; import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.core.Nullable; @@ -325,7 +326,6 @@ import java.util.Locale; import java.util.Map; import java.util.Set; -import java.util.concurrent.CountDownLatch; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.Predicate; @@ -441,8 +441,7 @@ public class Security extends Plugin private final Settings settings; private final boolean enabled; private final SecuritySystemIndices systemIndices; - - private final CountDownLatch nodeStartedSignal; + private final ListenableFuture nodeStartedListenable; /* what a PITA that we need an extra indirection to initialize this. Yet, once we got rid of guice we can thing about how * to fix this or make it simpler. Today we need several service that are created in createComponents but we need to register @@ -475,7 +474,7 @@ public Security(Settings settings, final Path configPath) { // TODO this is wrong, we should only use the environment that is provided to createComponents this.enabled = XPackSettings.SECURITY_ENABLED.get(settings); this.systemIndices = new SecuritySystemIndices(); - this.nodeStartedSignal = new CountDownLatch(1); + this.nodeStartedListenable = new ListenableFuture<>(); if (enabled) { runStartupChecks(settings); Automatons.updateConfiguration(settings); @@ -767,7 +766,7 @@ Collection createComponents( getSslService(), client, environment, - nodeStartedSignal, + (runnable -> nodeStartedListenable.addListener(ActionListener.wrap(runnable))), threadPool ); @@ -1290,7 +1289,7 @@ public Map getProcessors(Processor.Parameters paramet @Override public void onNodeStarted() { - this.nodeStartedSignal.countDown(); + this.nodeStartedListenable.onResponse(null); } /**