Skip to content

Commit 7245c05

Browse files
[8.x] Enable queryable built-in roles feature by default (elastic#120323) (elastic#120886)
* Enable queryable built-in roles feature by default (elastic#120323) Making the `es.queryable_built_in_roles_enabled` feature flag enabled by default. This feature makes the built-in roles automatically indexed in `.security` index and available for querying via Query Role API. The consequence of this is that `.security` index is now created eagerly (if it's not existing) on cluster formation. In order to keep the scope of this PR small, the feature is disabled for some of the tests, because they are either non-trivial to adjust or the gain is not worthy the effort to do it now. The tests will be adjusted in a follow-up PR and later the flag will be removed completely. Relates to elastic#117581 (cherry picked from commit 52e0f21) # Conflicts: # modules/dot-prefix-validation/build.gradle # test/framework/src/main/java/org/elasticsearch/test/InternalTestCluster.java # x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmElasticAutoconfigIntegTests.java * Update InternalTestCluster.java remove line snuck after resolving merge confilcs * Update build.gradle fix build.gradle * Update build.gradle fix build.gradle by removing invalid task * remove non-existing timeout parameter on 8.x branch
1 parent 90569c6 commit 7245c05

File tree

26 files changed

+237
-66
lines changed

26 files changed

+237
-66
lines changed

docs/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ testClusters.matching { it.name == "yamlRestTest"}.configureEach {
120120
// TODO: remove this once cname is prepended to transport.publish_address by default in 8.0
121121
systemProperty 'es.transport.cname_in_publish_address', 'true'
122122

123+
systemProperty 'es.queryable_built_in_roles_enabled', 'false'
124+
123125
requiresFeature 'es.index_mode_feature_flag_registered', Version.fromString("8.0.0")
124126
requiresFeature 'es.failure_store_feature_flag_enabled', Version.fromString("8.12.0")
125127

modules/data-streams/src/yamlRestTest/resources/rest-api-spec/test/data_stream/140_data_stream_aliases.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,8 @@
240240
test: {}
241241

242242
- do:
243-
indices.get_alias: { }
243+
indices.get_alias:
244+
index: test*
244245
- match: { test1.aliases.test: { } }
245246
- match: { test2.aliases.test: { } }
246247
- match: { test3.aliases.test: { } }
@@ -255,7 +256,8 @@
255256
- is_true: acknowledged
256257

257258
- do:
258-
indices.get_alias: {}
259+
indices.get_alias:
260+
index: test*
259261
- match: {test1.aliases: {}}
260262
- match: {test2.aliases: {}}
261263
- match: {test3.aliases: {}}

modules/dot-prefix-validation/src/yamlRestTest/java/org/elasticsearch/validation/DotPrefixClientYamlTestSuiteIT.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
2222
import org.junit.ClassRule;
2323

24+
import java.util.Objects;
25+
2426
import static org.elasticsearch.test.cluster.FeatureFlag.FAILURE_STORE_ENABLED;
2527

2628
public class DotPrefixClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
@@ -55,6 +57,10 @@ private static ElasticsearchCluster createCluster() {
5557
if (setNodes) {
5658
clusterBuilder.nodes(2);
5759
}
60+
clusterBuilder.systemProperty("es.queryable_built_in_roles_enabled", () -> {
61+
final String enabled = System.getProperty("es.queryable_built_in_roles_enabled");
62+
return Objects.requireNonNullElse(enabled, "");
63+
});
5864
return clusterBuilder.build();
5965
}
6066

modules/dot-prefix-validation/src/yamlRestTest/resources/rest-api-spec/test/dot_prefix/10_basic.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
teardown:
33
- do:
44
indices.delete:
5-
index: .*
5+
index: .*,-.security-*
66

77
---
88
"Index creation with a dot-prefix is deprecated unless x-elastic-product-origin set":

qa/packaging/src/test/java/org/elasticsearch/packaging/test/PasswordToolsTests.java

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.nio.file.Path;
2121
import java.util.HashMap;
2222
import java.util.Map;
23+
import java.util.concurrent.Callable;
2324
import java.util.regex.Matcher;
2425
import java.util.regex.Pattern;
2526
import java.util.stream.Stream;
@@ -47,7 +48,9 @@ public void test010Install() throws Exception {
4748
public void test20GeneratePasswords() throws Exception {
4849
assertWhileRunning(() -> {
4950
ServerUtils.waitForElasticsearch(installation);
50-
Shell.Result result = installation.executables().setupPasswordsTool.run("auto --batch", null);
51+
Shell.Result result = retryOnAuthenticationErrors(
52+
() -> installation.executables().setupPasswordsTool.run("auto --batch", null)
53+
);
5154
Map<String, String> userpasses = parseUsersAndPasswords(result.stdout());
5255
for (Map.Entry<String, String> userpass : userpasses.entrySet()) {
5356
String response = ServerUtils.makeRequest(
@@ -102,20 +105,26 @@ public void test30AddBootstrapPassword() throws Exception {
102105
installation.executables().keystoreTool.run("add --stdin bootstrap.password", BOOTSTRAP_PASSWORD);
103106

104107
assertWhileRunning(() -> {
105-
String response = ServerUtils.makeRequest(
106-
Request.Get("http://localhost:9200/_cluster/health?wait_for_status=green&timeout=180s"),
107-
"elastic",
108-
BOOTSTRAP_PASSWORD,
109-
null
108+
ServerUtils.waitForElasticsearch("green", null, installation, "elastic", BOOTSTRAP_PASSWORD, null);
109+
final String response = retryOnAuthenticationErrors(
110+
() -> ServerUtils.makeRequest(
111+
Request.Get("http://localhost:9200/_cluster/health?wait_for_status=green&timeout=180s"),
112+
"elastic",
113+
BOOTSTRAP_PASSWORD,
114+
null
115+
)
110116
);
111117
assertThat(response, containsString("\"status\":\"green\""));
112118
});
119+
113120
}
114121

115122
public void test40GeneratePasswordsBootstrapAlreadySet() throws Exception {
116123
assertWhileRunning(() -> {
117-
118-
Shell.Result result = installation.executables().setupPasswordsTool.run("auto --batch", null);
124+
ServerUtils.waitForElasticsearch("green", null, installation, "elastic", BOOTSTRAP_PASSWORD, null);
125+
Shell.Result result = retryOnAuthenticationErrors(
126+
() -> installation.executables().setupPasswordsTool.run("auto --batch", null)
127+
);
119128
Map<String, String> userpasses = parseUsersAndPasswords(result.stdout());
120129
assertThat(userpasses, hasKey("elastic"));
121130
for (Map.Entry<String, String> userpass : userpasses.entrySet()) {
@@ -130,6 +139,48 @@ public void test40GeneratePasswordsBootstrapAlreadySet() throws Exception {
130139
});
131140
}
132141

142+
/**
143+
* The security index is created on startup.
144+
* It can happen that even when the security index exists, we get an authentication failure as `elastic`
145+
* user because the reserved realm checks the security index first.
146+
* This is because we check the security index too early (just after the creation) when all shards did not get allocated yet.
147+
* Hence, the call can result in an `UnavailableShardsException` and cause the authentication to fail.
148+
* We retry here on authentication errors for a couple of seconds just to verify that this is not the case.
149+
*/
150+
private <R> R retryOnAuthenticationErrors(final Callable<R> callable) throws Exception {
151+
Exception failure = null;
152+
int retries = 5;
153+
while (retries-- > 0) {
154+
try {
155+
return callable.call();
156+
} catch (Exception e) {
157+
if (e.getMessage() != null
158+
&& (e.getMessage().contains("401 Unauthorized") || e.getMessage().contains("Failed to authenticate user"))) {
159+
logger.info(
160+
"Authentication failed (possibly due to UnavailableShardsException for the security index), retrying [{}].",
161+
retries,
162+
e
163+
);
164+
if (failure == null) {
165+
failure = e;
166+
} else {
167+
failure.addSuppressed(e);
168+
}
169+
try {
170+
Thread.sleep(1000);
171+
} catch (InterruptedException interrupted) {
172+
Thread.currentThread().interrupt();
173+
failure.addSuppressed(interrupted);
174+
throw failure;
175+
}
176+
} else {
177+
throw e;
178+
}
179+
}
180+
}
181+
throw failure;
182+
}
183+
133184
private Map<String, String> parseUsersAndPasswords(String output) {
134185
Matcher matcher = USERPASS_REGEX.matcher(output);
135186
assertNotNull(matcher);

qa/packaging/src/test/java/org/elasticsearch/packaging/util/ServerUtils.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public class ServerUtils {
6666
private static final long waitTime = TimeUnit.MINUTES.toMillis(3);
6767
private static final long timeoutLength = TimeUnit.SECONDS.toMillis(30);
6868
private static final long requestInterval = TimeUnit.SECONDS.toMillis(5);
69-
private static final long dockerWaitForSecurityIndex = TimeUnit.SECONDS.toMillis(25);
69+
private static final long dockerWaitForSecurityIndex = TimeUnit.SECONDS.toMillis(60);
7070

7171
public static void waitForElasticsearch(Installation installation) throws Exception {
7272
final boolean securityEnabled;
@@ -260,9 +260,7 @@ public static void waitForElasticsearch(
260260
// `elastic` , the reserved realm checks the security index first. It can happen that we check the security index
261261
// too early after the security index creation in DockerTests causing an UnavailableShardsException. We retry
262262
// authentication errors for a couple of seconds just to verify this is not the case.
263-
if (installation.distribution.isDocker()
264-
&& timeElapsed < dockerWaitForSecurityIndex
265-
&& response.getStatusLine().getStatusCode() == 401) {
263+
if (timeElapsed < dockerWaitForSecurityIndex && response.getStatusLine().getStatusCode() == 401) {
266264
logger.info(
267265
"Authentication against docker failed (possibly due to UnavailableShardsException for the security index)"
268266
+ ", retrying..."

test/framework/src/main/java/org/elasticsearch/test/InternalTestCluster.java

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.apache.logging.log4j.LogManager;
1919
import org.apache.logging.log4j.Logger;
2020
import org.apache.lucene.store.AlreadyClosedException;
21+
import org.elasticsearch.action.UnavailableShardsException;
2122
import org.elasticsearch.action.admin.cluster.configuration.AddVotingConfigExclusionsRequest;
2223
import org.elasticsearch.action.admin.cluster.configuration.ClearVotingConfigExclusionsRequest;
2324
import org.elasticsearch.action.admin.cluster.configuration.TransportAddVotingConfigExclusionsAction;
@@ -145,6 +146,8 @@
145146
import static org.elasticsearch.node.Node.INITIAL_STATE_TIMEOUT_SETTING;
146147
import static org.elasticsearch.test.ESTestCase.TEST_REQUEST_TIMEOUT;
147148
import static org.elasticsearch.test.ESTestCase.assertBusy;
149+
import static org.elasticsearch.test.ESTestCase.assertFalse;
150+
import static org.elasticsearch.test.ESTestCase.assertTrue;
148151
import static org.elasticsearch.test.ESTestCase.randomFrom;
149152
import static org.elasticsearch.test.ESTestCase.runInParallel;
150153
import static org.elasticsearch.test.ESTestCase.safeAwait;
@@ -159,9 +162,7 @@
159162
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
160163
import static org.hamcrest.Matchers.not;
161164
import static org.junit.Assert.assertEquals;
162-
import static org.junit.Assert.assertFalse;
163165
import static org.junit.Assert.assertThat;
164-
import static org.junit.Assert.assertTrue;
165166
import static org.junit.Assert.fail;
166167

167168
/**
@@ -1239,16 +1240,29 @@ public synchronized void validateClusterFormed() {
12391240
}
12401241
logger.trace("validating cluster formed, expecting {}", expectedNodes);
12411242

1242-
assertFalse(
1243-
client().admin()
1244-
.cluster()
1245-
.prepareHealth(TEST_REQUEST_TIMEOUT)
1246-
.setWaitForEvents(Priority.LANGUID)
1247-
.setWaitForNodes(Integer.toString(expectedNodes.size()))
1248-
.get(TimeValue.timeValueSeconds(40))
1249-
.isTimedOut()
1250-
);
12511243
try {
1244+
assertBusy(() -> {
1245+
try {
1246+
final boolean timeout = client().admin()
1247+
.cluster()
1248+
.prepareHealth(TEST_REQUEST_TIMEOUT)
1249+
.setWaitForEvents(Priority.LANGUID)
1250+
.setWaitForNodes(Integer.toString(expectedNodes.size()))
1251+
.get(TimeValue.timeValueSeconds(40))
1252+
.isTimedOut();
1253+
if (timeout) {
1254+
throw new IllegalStateException("timed out waiting for cluster to form");
1255+
}
1256+
} catch (UnavailableShardsException e) {
1257+
if (e.getMessage() != null && e.getMessage().contains(".security")) {
1258+
// security index may not be ready yet, throwing assertion error to retry
1259+
throw new AssertionError(e);
1260+
} else {
1261+
throw e;
1262+
}
1263+
}
1264+
}, 30, TimeUnit.SECONDS);
1265+
12521266
assertBusy(() -> {
12531267
final List<ClusterState> states = nodes.values()
12541268
.stream()

x-pack/plugin/build.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,4 +219,3 @@ tasks.named("yamlRestTestV7CompatTransform").configure({ task ->
219219
task.skipTest("esql/190_lookup_join/alias-pattern-single", "LOOKUP JOIN does not support index aliases for now")
220220

221221
})
222-

x-pack/plugin/core/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ testClusters.configureEach {
153153
keystore 'bootstrap.password', 'x-pack-test-password'
154154
user username: "x_pack_rest_user", password: "x-pack-test-password"
155155
requiresFeature 'es.failure_store_feature_flag_enabled', Version.fromString("8.15.0")
156+
systemProperty 'es.queryable_built_in_roles_enabled', 'false'
156157
}
157158

158159
if (buildParams.isSnapshotBuild() == false) {

x-pack/plugin/fleet/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ testClusters.configureEach {
2929
setting 'xpack.security.enabled', 'true'
3030
setting 'xpack.security.autoconfiguration.enabled', 'false'
3131
user username: 'x_pack_rest_user', password: 'x-pack-test-password'
32+
systemProperty 'es.queryable_built_in_roles_enabled', 'false'
3233
}

0 commit comments

Comments
 (0)