diff --git a/modules/dlm/src/javaRestTest/java/org/elasticsearch/dlm/DataStreamLifecyclePermissionsRestIT.java b/modules/dlm/src/javaRestTest/java/org/elasticsearch/dlm/DataStreamLifecyclePermissionsRestIT.java index 162592ef311ef..157d502675edd 100644 --- a/modules/dlm/src/javaRestTest/java/org/elasticsearch/dlm/DataStreamLifecyclePermissionsRestIT.java +++ b/modules/dlm/src/javaRestTest/java/org/elasticsearch/dlm/DataStreamLifecyclePermissionsRestIT.java @@ -75,9 +75,9 @@ public static void init() throws URISyntaxException, FileNotFoundException { .configFile("node.key", Resource.fromClasspath("ssl/node.key")) .configFile("node.crt", Resource.fromClasspath("ssl/node.crt")) .configFile("ca.crt", Resource.fromClasspath("ssl/ca.crt")) - .user("test_admin", PASSWORD, "superuser") - .user("test_data_stream_lifecycle", PASSWORD, "manage_data_stream_lifecycle") - .user("test_non_privileged", PASSWORD, "not_privileged") + .user("test_admin", PASSWORD, "superuser", false) + .user("test_data_stream_lifecycle", PASSWORD, "manage_data_stream_lifecycle", false) + .user("test_non_privileged", PASSWORD, "not_privileged", false) .rolesFile(Resource.fromClasspath("roles.yml")) .build(); diff --git a/qa/ccs-common-rest/src/yamlRestTest/java/org/elasticsearch/test/rest/yaml/RcsCcsCommonYamlTestSuiteIT.java b/qa/ccs-common-rest/src/yamlRestTest/java/org/elasticsearch/test/rest/yaml/RcsCcsCommonYamlTestSuiteIT.java index 5bb63fe6751ab..e06d75a3f306a 100644 --- a/qa/ccs-common-rest/src/yamlRestTest/java/org/elasticsearch/test/rest/yaml/RcsCcsCommonYamlTestSuiteIT.java +++ b/qa/ccs-common-rest/src/yamlRestTest/java/org/elasticsearch/test/rest/yaml/RcsCcsCommonYamlTestSuiteIT.java @@ -114,7 +114,7 @@ public class RcsCcsCommonYamlTestSuiteIT extends ESClientYamlSuiteTestCase { return (String) API_KEY_MAP_REF.get().get("encoded"); }) .rolesFile(Resource.fromClasspath("roles.yml")) - .user("remote_search_user", "x-pack-test-password", "remote_search_role") + .user("remote_search_user", "x-pack-test-password", "remote_search_role", false) .build(); private static Map createCrossClusterAccessApiKey() throws IOException { diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/AbstractLocalClusterSpecBuilder.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/AbstractLocalClusterSpecBuilder.java index 5bae78889b226..be2e32745abd7 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/AbstractLocalClusterSpecBuilder.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/AbstractLocalClusterSpecBuilder.java @@ -96,8 +96,8 @@ public AbstractLocalClusterSpecBuilder user(String username, String password) } @Override - public AbstractLocalClusterSpecBuilder user(String username, String password, String role) { - this.users.add(new User(username, password, role)); + public AbstractLocalClusterSpecBuilder user(String username, String password, String role, boolean operator) { + this.users.add(new User(username, password, role, operator)); return this; } diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterFactory.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterFactory.java index f0abf5ba42077..06f1e3c089280 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterFactory.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterFactory.java @@ -44,9 +44,12 @@ import java.time.Duration; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Properties; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; @@ -471,6 +474,7 @@ private void configureSecurity() { } LOGGER.info("Creating users for node '{}'", name); + final Set operators = new HashSet<>(); for (User user : spec.getUsers()) { runToolScript( "elasticsearch-users", @@ -482,6 +486,24 @@ private void configureSecurity() { "-r", user.getRole() ); + if (user.isOperator()) { + operators.add(user.getUsername()); + } + } + + if (operators.isEmpty() == false) { + // TODO: Support service accounts here + Path destination = workingDir.resolve("config").resolve("operator_users.yml"); + try (Writer writer = Files.newBufferedWriter(destination, StandardOpenOption.CREATE, StandardOpenOption.APPEND)) { + writer.write(String.format(Locale.ROOT, """ + operator: + - usernames: [%s] + realm_type: "file" + auth_type: "realm" + """, operators.stream().collect(Collectors.joining("\",\"", "\"", "\"")))); + } catch (IOException e) { + throw new UncheckedIOException("Failed to configure operator users file " + destination, e); + } } } } diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpecBuilder.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpecBuilder.java index 0f184b9b0e2e2..cca1a607d0bf7 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpecBuilder.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpecBuilder.java @@ -51,14 +51,16 @@ public interface LocalClusterSpecBuilder extends LocalClusterSpecBuilder node(int index, Consumer config); /** - * Register a user using the default test role. + * Register a user using the default test role, as an operator */ LocalClusterSpecBuilder user(String username, String password); /** * Register a user using the given role. + * @param operator If true, configure the user as an operator. + * Note: This does not automatically enable operator privileges on the cluster */ - LocalClusterSpecBuilder user(String username, String password, String role); + LocalClusterSpecBuilder user(String username, String password, String role, boolean operator); /** * Register a roles file with cluster via the supplied {@link Resource}. diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/model/User.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/model/User.java index f056bbb4d0bda..2f105153f8192 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/model/User.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/model/User.java @@ -9,22 +9,26 @@ package org.elasticsearch.test.cluster.local.model; public class User { - public static final User DEFAULT_USER = new User("test_user", "x-pack-test-password", "_es_test_root"); + public static final String ROOT_USER_ROLE = "_es_test_root"; + public static final User DEFAULT_USER = new User("test_user", "x-pack-test-password", ROOT_USER_ROLE, true); private final String username; private final String password; private final String role; + private final boolean operator; public User(String username, String password) { this.username = username; this.password = password; - this.role = "_es_test_root"; + this.role = ROOT_USER_ROLE; + this.operator = true; } - public User(String username, String password, String role) { + public User(String username, String password, String role, boolean operator) { this.username = username; this.password = password; this.role = role; + this.operator = operator; } public String getUsername() { @@ -38,4 +42,8 @@ public String getPassword() { public String getRole() { return role; } + + public boolean isOperator() { + return operator; + } } diff --git a/x-pack/plugin/security/qa/basic-enable-security/src/javaRestTest/java/org/elasticsearch/xpack/security/EnableSecurityOnBasicLicenseIT.java b/x-pack/plugin/security/qa/basic-enable-security/src/javaRestTest/java/org/elasticsearch/xpack/security/EnableSecurityOnBasicLicenseIT.java index ec2a3e2b01803..30b82a34d2792 100644 --- a/x-pack/plugin/security/qa/basic-enable-security/src/javaRestTest/java/org/elasticsearch/xpack/security/EnableSecurityOnBasicLicenseIT.java +++ b/x-pack/plugin/security/qa/basic-enable-security/src/javaRestTest/java/org/elasticsearch/xpack/security/EnableSecurityOnBasicLicenseIT.java @@ -61,7 +61,7 @@ public class EnableSecurityOnBasicLicenseIT extends ESRestTestCase { .configFile("ca.crt", Resource.fromClasspath("ssl/ca.crt")) .rolesFile(Resource.fromClasspath("roles.yml")) .user("admin_user", "admin-password") - .user("security_test_user", "security-test-password", "security_test_role") + .user("security_test_user", "security-test-password", "security_test_role", false) .build(); @Override diff --git a/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityCcrIT.java b/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityCcrIT.java index b768a4d38dc7e..ca5e9779bca3d 100644 --- a/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityCcrIT.java +++ b/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityCcrIT.java @@ -71,7 +71,7 @@ public class RemoteClusterSecurityCcrIT extends AbstractRemoteClusterSecurityTes }""")); return (String) API_KEY_MAP_REF.get().get("encoded"); }) - .user("ccr_user", PASS.toString(), "ccr_user_role") + .user("ccr_user", PASS.toString(), "ccr_user_role", false) .build(); } diff --git a/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityMlIT.java b/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityMlIT.java index a9334c2fec6f0..5b5d4617b5c44 100644 --- a/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityMlIT.java +++ b/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityMlIT.java @@ -66,7 +66,7 @@ public class RemoteClusterSecurityMlIT extends AbstractRemoteClusterSecurityTest return (String) API_KEY_MAP_REF.get().get("encoded"); }) .rolesFile(Resource.fromClasspath("roles.yml")) - .user(REMOTE_ML_USER, PASS.toString(), "ml_jobs_shared_airline_data") + .user(REMOTE_ML_USER, PASS.toString(), "ml_jobs_shared_airline_data", false) .build(); } diff --git a/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityRestIT.java b/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityRestIT.java index b1dc87ac5a57e..677bb1ca27853 100644 --- a/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityRestIT.java +++ b/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityRestIT.java @@ -106,7 +106,7 @@ public class RemoteClusterSecurityRestIT extends AbstractRemoteClusterSecurityTe return (String) REST_API_KEY_MAP_REF.get().get("encoded"); }) .rolesFile(Resource.fromClasspath("roles.yml")) - .user(REMOTE_METRIC_USER, PASS.toString(), "read_remote_shared_metrics") + .user(REMOTE_METRIC_USER, PASS.toString(), "read_remote_shared_metrics", false) .build(); } diff --git a/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecuritySpecialUserIT.java b/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecuritySpecialUserIT.java index 6948a37670789..afa91a136aa82 100644 --- a/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecuritySpecialUserIT.java +++ b/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecuritySpecialUserIT.java @@ -63,7 +63,7 @@ public class RemoteClusterSecuritySpecialUserIT extends AbstractRemoteClusterSec .setting("xpack.security.authc.anonymous.roles", "read_remote_shared_logs") .setting("xpack.security.remote_cluster_client.ssl.enabled", "true") .setting("xpack.security.remote_cluster_client.ssl.certificate_authorities", "remote-cluster-ca.crt") - .user(REMOTE_SEARCH_USER, PASS.toString(), "read_remote_shared_metrics") + .user(REMOTE_SEARCH_USER, PASS.toString(), "read_remote_shared_metrics", false) .keystore("cluster.remote.my_remote_cluster.credentials", () -> { if (API_KEY_MAP_REF.get() == null) { final Map apiKeyMap = createCrossClusterAccessApiKey(""" diff --git a/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityTransformIT.java b/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityTransformIT.java index 4e9711c447b8e..313762b3982de 100644 --- a/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityTransformIT.java +++ b/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityTransformIT.java @@ -66,7 +66,7 @@ public class RemoteClusterSecurityTransformIT extends AbstractRemoteClusterSecur return (String) API_KEY_MAP_REF.get().get("encoded"); }) .rolesFile(Resource.fromClasspath("roles.yml")) - .user(REMOTE_TRANSFORM_USER, PASS.toString(), "transform_admin,transform_remote_shared_index") + .user(REMOTE_TRANSFORM_USER, PASS.toString(), "transform_admin,transform_remote_shared_index", false) .build(); } diff --git a/x-pack/plugin/security/qa/saml-rest-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/saml/SamlServiceProviderMetadataIT.java b/x-pack/plugin/security/qa/saml-rest-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/saml/SamlServiceProviderMetadataIT.java index 5049ba17c0175..383598c804f7a 100644 --- a/x-pack/plugin/security/qa/saml-rest-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/saml/SamlServiceProviderMetadataIT.java +++ b/x-pack/plugin/security/qa/saml-rest-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/saml/SamlServiceProviderMetadataIT.java @@ -20,6 +20,7 @@ import org.elasticsearch.http.PemHttpsConfigurator; import org.elasticsearch.mocksocket.MockHttpServer; import org.elasticsearch.test.cluster.ElasticsearchCluster; +import org.elasticsearch.test.cluster.local.model.User; import org.elasticsearch.test.cluster.util.resource.Resource; import org.elasticsearch.test.junit.RunnableTestRuleAdapter; import org.elasticsearch.test.rest.ESRestTestCase; @@ -106,8 +107,8 @@ private static ElasticsearchCluster initTestCluster() { .setting("xpack.security.transport.ssl.certificate_authorities", "ca.crt") .setting("xpack.security.transport.ssl.verification_mode", "certificate") .keystore("bootstrap.password", "x-pack-test-password") - .user("test_admin", "x-pack-test-password", "_es_test_root") - .user("rest_test", "rest_password") + .user("test_admin", "x-pack-test-password", User.ROOT_USER_ROLE, true) + .user("rest_test", "rest_password", User.ROOT_USER_ROLE, false) .configFile("node.key", Resource.fromClasspath("ssl/node.key")) .configFile("node.crt", Resource.fromClasspath("ssl/node.crt")) .configFile("ca.crt", Resource.fromClasspath("ssl/ca.crt")) diff --git a/x-pack/plugin/security/qa/service-account/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/service/ServiceAccountIT.java b/x-pack/plugin/security/qa/service-account/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/service/ServiceAccountIT.java index ac1f30bd86522..38a4c3419873b 100644 --- a/x-pack/plugin/security/qa/service-account/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/service/ServiceAccountIT.java +++ b/x-pack/plugin/security/qa/service-account/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/service/ServiceAccountIT.java @@ -247,8 +247,8 @@ public class ServiceAccountIT extends ESRestTestCase { .configFile("service_tokens", Resource.fromClasspath("service_tokens")) .rolesFile(Resource.fromClasspath("roles.yml")) .user("test_admin", "x-pack-test-password") - .user("elastic/fleet-server", "x-pack-test-password", "superuser") - .user("service_account_manager", "x-pack-test-password", "service_account_manager") + .user("elastic/fleet-server", "x-pack-test-password", "superuser", false) + .user("service_account_manager", "x-pack-test-password", "service_account_manager", false) .build(); @BeforeClass diff --git a/x-pack/qa/multi-node/src/javaRestTest/java/org/elasticsearch/multi_node/GlobalCheckpointSyncActionIT.java b/x-pack/qa/multi-node/src/javaRestTest/java/org/elasticsearch/multi_node/GlobalCheckpointSyncActionIT.java index 12cfa8e48b3e4..eb91f4c9dc32f 100644 --- a/x-pack/qa/multi-node/src/javaRestTest/java/org/elasticsearch/multi_node/GlobalCheckpointSyncActionIT.java +++ b/x-pack/qa/multi-node/src/javaRestTest/java/org/elasticsearch/multi_node/GlobalCheckpointSyncActionIT.java @@ -31,7 +31,7 @@ public class GlobalCheckpointSyncActionIT extends ESRestTestCase { .setting("xpack.ml.enabled", "false") .setting("xpack.license.self_generated.type", "trial") .rolesFile(Resource.fromClasspath("roles.yml")) - .user("test-user", "x-pack-test-password", "test") + .user("test-user", "x-pack-test-password", "test", false) .user("super-user", "x-pack-super-password") .build(); diff --git a/x-pack/qa/oidc-op-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/oidc/C2IdOpTestCase.java b/x-pack/qa/oidc-op-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/oidc/C2IdOpTestCase.java index 8866395598323..106e1d27910f2 100644 --- a/x-pack/qa/oidc-op-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/oidc/C2IdOpTestCase.java +++ b/x-pack/qa/oidc-op-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/oidc/C2IdOpTestCase.java @@ -171,7 +171,7 @@ public abstract class C2IdOpTestCase extends ESRestTestCase { .keystore("xpack.security.authc.realms.jwt.op-jwt.client_authentication.shared_secret", "jwt-realm-shared-secret") .configFile("testnode.jks", Resource.fromClasspath("ssl/testnode.jks")) .configFile("op-jwks.json", Resource.fromClasspath("op-jwks.json")) - .user("x_pack_rest_user", "x-pack-test-password", "superuser") + .user("x_pack_rest_user", "x-pack-test-password", "superuser", false) .build(); @Override