From 269b152a8f372cd729f3847a26c6cfb31f9b02b8 Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Mon, 27 Apr 2020 13:31:21 -0400 Subject: [PATCH] Deprecate the kibana reserved user; introduce kibana_system user (#54967) * deprecate the kibana reserved user; introduce kibana_system user * fix license and test errors * fix IdentityProviderAuthenticationIT tests * test deprecation logging * First pass at SetupPasswordTool updates * fix checkstyle * update docs * update number of expected users * update test to expect deprecation header Co-authored-by: Elastic Machine --- .../SecurityDocumentationIT.java | 6 +-- .../migration/migrate_8_0/security.asciidoc | 37 +++++++++++++ .../security/auditing/output-logfile.asciidoc | 8 +-- .../authentication/built-in-users.asciidoc | 30 +++++------ .../get-started-builtin-users.asciidoc | 6 +-- .../get-started-kibana-users.asciidoc | 42 +++++++-------- .../tutorial-tls-internode.asciidoc | 36 ++++++------- .../authc/esnative/ClientReservedRealm.java | 1 + .../core/security/user/KibanaSystemUser.java | 21 ++++++++ .../xpack/core/security/user/KibanaUser.java | 7 ++- .../core/security/user/UsernamesField.java | 3 +- .../idp/IdentityProviderAuthenticationIT.java | 12 ++--- .../authc/esnative/ReservedRealm.java | 21 ++++++++ .../esnative/tool/SetupPasswordTool.java | 21 ++++++-- .../KibanaSystemRoleIntegTests.java | 12 +++-- .../test/NativeRealmIntegTestCase.java | 5 +- .../authc/esnative/NativeUsersStoreTests.java | 9 ++-- .../esnative/ReservedRealmIntegTests.java | 13 ++--- .../authc/esnative/ReservedRealmTests.java | 22 +++++--- .../esnative/tool/SetupPasswordToolTests.java | 53 +++++++++++++++++-- .../pki/PkiAuthDelegationIntegTests.java | 8 +-- .../security/user/UserSerializationTests.java | 8 +++ .../esnative/tool/SetupPasswordToolIT.java | 7 ++- 23 files changed, 277 insertions(+), 111 deletions(-) create mode 100644 x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/KibanaSystemUser.java diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java index 848b99366f316..c5ba7ba6011f3 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java @@ -200,11 +200,11 @@ public void testGetUsers() throws Exception { List users = new ArrayList<>(3); users.addAll(response.getUsers()); assertNotNull(response); - // 9 users are expected to be returned + // 10 users are expected to be returned // test_users (3): user1, user2, user3 - // system_users (6): elastic, beats_system, apm_system, logstash_system, kibana, remote_monitoring_user + // system_users (6): elastic, beats_system, apm_system, logstash_system, kibana, kibana_system, remote_monitoring_user logger.info(users); - assertThat(users.size(), equalTo(9)); + assertThat(users.size(), equalTo(10)); } { diff --git a/docs/reference/migration/migrate_8_0/security.asciidoc b/docs/reference/migration/migrate_8_0/security.asciidoc index 80e5a27534e47..b422cde2aa7fb 100644 --- a/docs/reference/migration/migrate_8_0/security.asciidoc +++ b/docs/reference/migration/migrate_8_0/security.asciidoc @@ -132,3 +132,40 @@ It is now an error to enable SSL for the HTTP (Rest) server without also configu a certificate and key through use of the `xpack.security.http.ssl.keystore.path` setting or the `xpack.security.http.ssl.certificate` and `xpack.security.http.ssl.key` settings. + + +[float] +[[builtin-users-changes]] +==== Changes to built-in users + +[float] +===== The `kibana` user has been removed in favor of the `kibana_system` user + +The `kibana` user was historically used to authenticate {kib} to {es}. +The name of this user was confusing, and was often mistakenly used to login to {kib}. +This has been renamed to `kibana_system` in order to reduce confusion, and to better +align with other built-in system accounts. + +If your `kibana.yml` used to contain: +[source,yaml] +-------------------------------------------------- +elasticsearch.username: kibana +-------------------------------------------------- + +then you should update to use the new `kibana_system` user instead: +[source,yaml] +-------------------------------------------------- +elasticsearch.username: kibana_system +-------------------------------------------------- + + +[float] +[[builtin-roles-changes]] +==== Changes to built-in roles + +[float] +===== The `kibana_user` role has been removed in favor of the `kibana_admin` role + +Users who were previously assigned the `kibana_user` role should instead be assigned +the `kibana_admin` role. This role grants the same set of privileges as `kibana_user`, but has been +renamed to better reflect its intended use. diff --git a/x-pack/docs/en/security/auditing/output-logfile.asciidoc b/x-pack/docs/en/security/auditing/output-logfile.asciidoc index 1f237951c8b85..cfadb1a4cf848 100644 --- a/x-pack/docs/en/security/auditing/output-logfile.asciidoc +++ b/x-pack/docs/en/security/auditing/output-logfile.asciidoc @@ -10,7 +10,7 @@ are similar. For systems that are not ingesting the audit file for search or analytics it is strongly recommended to keep only the newer format. To turn off the deprecated output format, you can disable the logger in the -`log4j2.properties` file: +`log4j2.properties` file: [source, properties] -------------------------------------------------- @@ -139,18 +139,18 @@ non-matching events are printed as usual. All policies are defined under the `xpack.security.audit.logfile.events.ignore_filters` settings namespace. For example, the following policy named _example1_ matches -events from the _kibana_ or _admin_user_ principals **and** operating over indices of the +events from the _kibana_system_ or _admin_user_ principals **and** operating over indices of the wildcard form _app-logs*_: [source,yaml] ---------------------------- xpack.security.audit.logfile.events.ignore_filters: example1: - users: ["kibana", "admin_user"] + users: ["kibana_system", "admin_user"] indices: ["app-logs*"] ---------------------------- -An audit event generated by the _kibana_ user and operating over multiple indices +An audit event generated by the _kibana_system_ user and operating over multiple indices , some of which do not match the indices wildcard, will not match. As expected, operations generated by all other users (even operating only on indices that match the _indices_ filter) will not match this policy either. diff --git a/x-pack/docs/en/security/authentication/built-in-users.asciidoc b/x-pack/docs/en/security/authentication/built-in-users.asciidoc index 7e4551633a88c..ad9244e8acc76 100644 --- a/x-pack/docs/en/security/authentication/built-in-users.asciidoc +++ b/x-pack/docs/en/security/authentication/built-in-users.asciidoc @@ -12,9 +12,9 @@ used to <>. `logstash_system`:: The user Logstash uses when storing monitoring information in {es}. `beats_system`:: The user the Beats use when storing monitoring information in {es}. `apm_system`:: The user the APM server uses when storing monitoring information in {es}. -`remote_monitoring_user`:: The user {metricbeat} uses when collecting and -storing monitoring information in {es}. It has the `remote_monitoring_agent` and -`remote_monitoring_collector` built-in roles. +`remote_monitoring_user`:: The user {metricbeat} uses when collecting and +storing monitoring information in {es}. It has the `remote_monitoring_agent` and +`remote_monitoring_collector` built-in roles. TIP: The built-in users serve specific purposes and are not intended for general use. In particular, do not use the `elastic` superuser unless full access to @@ -65,7 +65,7 @@ The +elasticsearch-setup-passwords+ tool is the simplest method to set the built-in users' passwords for the first time. It uses the `elastic` user's bootstrap password to run user management API requests. For example, you can run the command in an "interactive" mode, which prompts you to enter new passwords -for the `elastic`, `kibana`, `logstash_system`, `beats_system`, `apm_system`, +for the `elastic`, `kibana_system`, `logstash_system`, `beats_system`, `apm_system`, and `remote_monitoring_user` users: [source,shell] @@ -107,7 +107,7 @@ since at that point the bootstrap password is no longer required. [[add-built-in-user-kibana]] ==== Adding built-in user passwords to {kib} -After the `kibana` user password is set, you need to update the {kib} server +After the `kibana_system` user password is set, you need to update the {kib} server with the new password by setting `elasticsearch.password` in the `kibana.yml` configuration file: @@ -120,7 +120,7 @@ See {kibana-ref}/using-kibana-with-security.html[Configuring security in {kib}]. [float] [[add-built-in-user-logstash]] -==== Adding built-in user passwords to {ls} +==== Adding built-in user passwords to {ls} The `logstash_system` user is used internally within Logstash when monitoring is enabled for Logstash. @@ -143,7 +143,7 @@ been changed, you can enable the user via the following API call: PUT _security/user/logstash_system/_enable --------------------------------------------------------------------- -See {logstash-ref}/ls-security.html#ls-monitoring-user[Configuring credentials for {ls} monitoring]. +See {logstash-ref}/ls-security.html#ls-monitoring-user[Configuring credentials for {ls} monitoring]. [float] [[add-built-in-user-beats]] @@ -161,13 +161,13 @@ xpack.monitoring.elasticsearch.username: beats_system xpack.monitoring.elasticsearch.password: beatspassword ---------------------------------------------------------- -For example, see {metricbeat-ref}/monitoring.html[Monitoring {metricbeat}]. +For example, see {metricbeat-ref}/monitoring.html[Monitoring {metricbeat}]. -The `remote_monitoring_user` is used when {metricbeat} collects and stores -monitoring data for the {stack}. See <>. +The `remote_monitoring_user` is used when {metricbeat} collects and stores +monitoring data for the {stack}. See <>. If you have upgraded from an older version of {es}, then you may not have set a -password for the `beats_system` or `remote_monitoring_user` users. If this is +password for the `beats_system` or `remote_monitoring_user` users. If this is the case, then you should use the *Management > Users* page in {kib} or the <> to set a password for these users. @@ -178,8 +178,8 @@ for these users. The `apm_system` user is used internally within APM when monitoring is enabled. -To enable this feature in APM, you need to update the -{apm-server-ref}/configuring-howto-apm-server.html[APM configuration file] to +To enable this feature in APM, you need to update the +{apm-server-ref}/configuring-howto-apm-server.html[APM configuration file] to reference the correct username and password. For example: [source,yaml] @@ -188,10 +188,10 @@ xpack.monitoring.elasticsearch.username: apm_system xpack.monitoring.elasticsearch.password: apmserverpassword ---------------------------------------------------------- -See {apm-server-ref}/monitoring.html[Monitoring APM Server]. +See {apm-server-ref}/monitoring.html[Monitoring APM Server]. If you have upgraded from an older version of {es}, then you may not have set a -password for the `apm_system` user. If this is the case, +password for the `apm_system` user. If this is the case, then you should use the *Management > Users* page in {kib} or the <> to set a password for these users. diff --git a/x-pack/docs/en/security/get-started-builtin-users.asciidoc b/x-pack/docs/en/security/get-started-builtin-users.asciidoc index bf8275e49bf8e..ed44d6141a607 100644 --- a/x-pack/docs/en/security/get-started-builtin-users.asciidoc +++ b/x-pack/docs/en/security/get-started-builtin-users.asciidoc @@ -1,13 +1,13 @@ // tag::create-users[] There are <> that you can use for specific -administrative purposes: `apm_system`, `beats_system`, `elastic`, `kibana`, -`logstash_system`, and `remote_monitoring_user`. +administrative purposes: `apm_system`, `beats_system`, `elastic`, `kibana_system`, +`logstash_system`, and `remote_monitoring_user`. // end::create-users[] Before you can use them, you must set their passwords: -. Restart {es}. For example, if you installed {es} with a `.tar.gz` package, run +. Restart {es}. For example, if you installed {es} with a `.tar.gz` package, run the following command from the {es} directory: + -- diff --git a/x-pack/docs/en/security/get-started-kibana-users.asciidoc b/x-pack/docs/en/security/get-started-kibana-users.asciidoc index 2d06f670cdcba..1c24444c5a2d7 100644 --- a/x-pack/docs/en/security/get-started-kibana-users.asciidoc +++ b/x-pack/docs/en/security/get-started-kibana-users.asciidoc @@ -1,36 +1,36 @@ When the {es} {security-features} are enabled, users must log in to {kib} -with a valid user ID and password. +with a valid user ID and password. -{kib} also performs some tasks under the covers that require use of the -built-in `kibana` user. +{kib} also performs some tasks under the covers that require use of the +built-in `kibana_system` user. -. Configure {kib} to use the built-in `kibana` user and the password that you +. Configure {kib} to use the built-in `kibana_system` user and the password that you created: -** If you don't mind having passwords visible in your configuration file, -uncomment and update the following settings in the `kibana.yml` file in your +** If you don't mind having passwords visible in your configuration file, +uncomment and update the following settings in the `kibana.yml` file in your {kib} directory: + -- -TIP: If you installed {kib} using archive distributions (`zip` or -`tar.gz`), the `kibana.yml` configuration file is in `KIBANA_HOME/config`. If -you used package distributions (Debian or RPM), it's in `/etc/kibana`. For more -information, see {kibana-ref}/settings.html[Configuring {kib}]. +TIP: If you installed {kib} using archive distributions (`zip` or +`tar.gz`), the `kibana.yml` configuration file is in `KIBANA_HOME/config`. If +you used package distributions (Debian or RPM), it's in `/etc/kibana`. For more +information, see {kibana-ref}/settings.html[Configuring {kib}]. For example, add the following settings: [source,yaml] ---- -elasticsearch.username: "kibana" +elasticsearch.username: "kibana_system" elasticsearch.password: "your_password" ---- -Specify the password that you set with the `elasticsearch-setup-passwords` -command then save your changes to the file. +Specify the password that you set with the `elasticsearch-setup-passwords` +command then save your changes to the file. -- -** If you prefer not to put your user ID and password in the `kibana.yml` file, -store them in a keystore instead. Run the following commands to create the {kib} +** If you prefer not to put your user ID and password in the `kibana.yml` file, +store them in a keystore instead. Run the following commands to create the {kib} keystore and add the secure settings: + -- @@ -42,14 +42,14 @@ keystore and add the secure settings: ./bin/kibana-keystore add elasticsearch.password ---------------------------------------------------------------------- -When prompted, specify the `kibana` built-in user and its password for these -setting values. The settings are automatically applied when you start {kib}. +When prompted, specify the `kibana_system` built-in user and its password for these +setting values. The settings are automatically applied when you start {kib}. To learn more, see {kibana-ref}/secure-settings.html[Secure settings]. // end::store-kibana-user[] -- -. Restart {kib}. For example, if you installed -{kib} with a `.tar.gz` package, run the following command from the {kib} +. Restart {kib}. For example, if you installed +{kib} with a `.tar.gz` package, run the following command from the {kib} directory: + -- @@ -58,5 +58,5 @@ directory: ./bin/kibana ---------------------------------------------------------------------- -See {kibana-ref}/start-stop.html[Starting and stopping {kib}]. --- \ No newline at end of file +See {kibana-ref}/start-stop.html[Starting and stopping {kib}]. +-- diff --git a/x-pack/docs/en/security/securing-communications/tutorial-tls-internode.asciidoc b/x-pack/docs/en/security/securing-communications/tutorial-tls-internode.asciidoc index 2bda53ae04fdc..6691809693556 100644 --- a/x-pack/docs/en/security/securing-communications/tutorial-tls-internode.asciidoc +++ b/x-pack/docs/en/security/securing-communications/tutorial-tls-internode.asciidoc @@ -1,7 +1,7 @@ [role="xpack"] [testenv="trial"] [[encrypting-internode]] -=== Encrypt internode communications +=== Encrypt internode communications Now that we've generated a certificate authority and certificates, let's update the cluster to use these files. @@ -9,7 +9,7 @@ the cluster to use these files. IMPORTANT: When you enable {es} {security-features}, unless you have a trial license, you must use Transport Layer Security (TLS) to encrypt internode communication. By following the steps in this tutorial tutorial, you learn how -to meet the minimum requirements to pass the +to meet the minimum requirements to pass the <>. . (Optional) Name the cluster. @@ -23,10 +23,10 @@ For example, add the <> setting in the cluster.name: test-cluster ---- -TIP: The `ES_PATH_CONF` environment variable contains the path for the {es} -configuration files. If you installed {es} using archive distributions (`zip` or -`tar.gz`), it defaults to `ES_HOME/config`. If you used package distributions -(Debian or RPM), it defaults to `/etc/elasticsearch`. For more information, see +TIP: The `ES_PATH_CONF` environment variable contains the path for the {es} +configuration files. If you installed {es} using archive distributions (`zip` or +`tar.gz`), it defaults to `ES_HOME/config`. If you used package distributions +(Debian or RPM), it defaults to `/etc/elasticsearch`. For more information, see <>. The default cluster name is `elasticsearch`. You should choose a unique name, @@ -46,7 +46,7 @@ node.name: node-1 In this tutorial, the cluster will consist of three nodes that exist on the same machine and share the same (loopback) IP address and hostname. Therefore, we -must give each node a unique name. +must give each node a unique name. This step is also necessary if you want to use the `node.name` value to define the location of certificates in subsequent steps. @@ -79,13 +79,13 @@ itself into a new cluster. TIP: If you are starting a cluster with multiple master-eligible nodes for the first time, add all of those node names to the `cluster.initial_master_nodes` setting. - + See <> and <>. -- . Enable Transport Layer Security (TLS/SSL) for transport (internode) -communications. +communications. + -- // tag::enable-tls[] @@ -95,20 +95,20 @@ file: [source,yaml] ---- xpack.security.enabled: true -xpack.security.transport.ssl.enabled: true +xpack.security.transport.ssl.enabled: true xpack.security.transport.ssl.keystore.path: certs/${node.name}.p12 <1> xpack.security.transport.ssl.truststore.path: certs/${node.name}.p12 ---- <1> If the file name for your certificate does not match the `node.name` value, -you must put the appropriate file name in the `elasticsearch.yml` file. +you must put the appropriate file name in the `elasticsearch.yml` file. // end::enable-tls[] NOTE: The PKCS#12 keystore that is output by the `elasticsearch-certutil` can be -used as both a keystore and a truststore. If you use other tools to manage and +used as both a keystore and a truststore. If you use other tools to manage and generate your certificates, you might have different values for these settings, but that scenario is not covered in this tutorial. -For more information, see <> and +For more information, see <> and <>. -- @@ -116,7 +116,7 @@ For more information, see <> and + -- // tag::secure-passwords[] -For example, run the following commands: +For example, run the following commands: ["source","sh",subs="attributes,callouts"] ---------------------------------------------------------------------- @@ -146,7 +146,7 @@ command from the {es} directory: ---------------------------------------------------------------------- -- -. Create passwords for the built-in users and configure {kib} to use them. +. Create passwords for the built-in users and configure {kib} to use them. + -- NOTE: If you already configured passwords for these users in other tutorials, @@ -154,11 +154,11 @@ you can skip this step. include::{xes-repo-dir}/security/get-started-builtin-users.asciidoc[tag=create-users] -After you setup the password for the `kibana` built-in user, +After you setup the password for the `kibana_system` built-in user, <>. For example, run the following commands to create the {kib} keystore and add the -`kibana` built-in user and its password in secure settings: +`kibana_system` built-in user and its password in secure settings: include::{xes-repo-dir}/security/get-started-kibana-users.asciidoc[tag=store-kibana-user] -- @@ -173,5 +173,5 @@ command from the {kib} directory: ./bin/kibana ---------------------------------------------------------------------- -See {kibana-ref}/start-stop.html[Starting and stopping {kib}]. +See {kibana-ref}/start-stop.html[Starting and stopping {kib}]. -- diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/esnative/ClientReservedRealm.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/esnative/ClientReservedRealm.java index 81b98e34996e4..6644daaa1ced6 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/esnative/ClientReservedRealm.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/esnative/ClientReservedRealm.java @@ -16,6 +16,7 @@ public static boolean isReserved(String username, Settings settings) { assert username != null; switch (username) { case UsernamesField.ELASTIC_NAME: + case UsernamesField.DEPRECATED_KIBANA_NAME: case UsernamesField.KIBANA_NAME: case UsernamesField.LOGSTASH_NAME: case UsernamesField.BEATS_NAME: diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/KibanaSystemUser.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/KibanaSystemUser.java new file mode 100644 index 0000000000000..885dd6a6aabef --- /dev/null +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/KibanaSystemUser.java @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.core.security.user; + +import org.elasticsearch.xpack.core.security.support.MetadataUtils; + +/** + * Built in user for the kibana server + */ +public class KibanaSystemUser extends User { + + public static final String NAME = UsernamesField.KIBANA_NAME; + public static final String ROLE_NAME = UsernamesField.KIBANA_ROLE; + + public KibanaSystemUser(boolean enabled) { + super(NAME, new String[]{ ROLE_NAME }, null, null, MetadataUtils.DEFAULT_RESERVED_METADATA, enabled); + } +} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/KibanaUser.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/KibanaUser.java index 8dfa149987d0e..595e90215df7f 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/KibanaUser.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/KibanaUser.java @@ -9,13 +9,16 @@ /** * Built in user for the kibana server + * @deprecated use KibanaSystemUser */ +@Deprecated public class KibanaUser extends User { - public static final String NAME = UsernamesField.KIBANA_NAME; + public static final String NAME = UsernamesField.DEPRECATED_KIBANA_NAME; public static final String ROLE_NAME = UsernamesField.KIBANA_ROLE; public KibanaUser(boolean enabled) { - super(NAME, new String[]{ ROLE_NAME }, null, null, MetadataUtils.DEFAULT_RESERVED_METADATA, enabled); + super(NAME, new String[]{ ROLE_NAME }, null, null, + MetadataUtils.getDeprecatedReservedMetadata("Please use the [kibana_system] user instead."), enabled); } } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/UsernamesField.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/UsernamesField.java index 9c28b67a342e7..5201858aa99c6 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/UsernamesField.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/UsernamesField.java @@ -8,7 +8,8 @@ public final class UsernamesField { public static final String ELASTIC_NAME = "elastic"; public static final String ELASTIC_ROLE = "superuser"; - public static final String KIBANA_NAME = "kibana"; + public static final String DEPRECATED_KIBANA_NAME = "kibana"; + public static final String KIBANA_NAME = "kibana_system"; public static final String KIBANA_ROLE = "kibana_system"; public static final String SYSTEM_NAME = "_system"; public static final String SYSTEM_ROLE = "_system"; diff --git a/x-pack/plugin/identity-provider/qa/idp-rest-tests/src/test/java/org/elasticsearch/xpack/idp/IdentityProviderAuthenticationIT.java b/x-pack/plugin/identity-provider/qa/idp-rest-tests/src/test/java/org/elasticsearch/xpack/idp/IdentityProviderAuthenticationIT.java index 8b667eb846180..84bc2a9a5e527 100644 --- a/x-pack/plugin/identity-provider/qa/idp-rest-tests/src/test/java/org/elasticsearch/xpack/idp/IdentityProviderAuthenticationIT.java +++ b/x-pack/plugin/identity-provider/qa/idp-rest-tests/src/test/java/org/elasticsearch/xpack/idp/IdentityProviderAuthenticationIT.java @@ -45,7 +45,7 @@ public class IdentityProviderAuthenticationIT extends IdpRestTestCase { @Before public void setupSecurityData() throws IOException { - setUserPassword("kibana", new SecureString("kibana".toCharArray())); + setUserPassword("kibana_system", new SecureString("kibana_system".toCharArray())); createApplicationPrivileges("elastic-cloud", Map.ofEntries( Map.entry("deployment_admin", Set.of("sso:admin")), Map.entry("deployment_viewer", Set.of("sso:viewer")) @@ -113,7 +113,7 @@ private Map validateAuthnRequest(String entityId, String authnRe private SamlPrepareAuthenticationResponse generateSamlAuthnRequest(String realmName) throws Exception { final Request request = new Request("POST", "/_security/saml/prepare"); request.setJsonEntity("{\"realm\":\"" + realmName + "\"}"); - try (RestClient kibanaClient = restClientAsKibana()) { + try (RestClient kibanaClient = restClientAsKibanaSystem()) { final Response response = kibanaClient.performRequest(request); final Map map = entityAsMap(response); assertThat(ObjectPath.eval("realm", map), equalTo(realmName)); @@ -152,7 +152,7 @@ private void authenticateWithSamlResponse(String samlResponse, @Nullable String request.setJsonEntity("{\"content\":\"" + encodedResponse + "\", \"realm\":\"" + REALM_NAME + "\"}"); } final String accessToken; - try (RestClient kibanaClient = restClientAsKibana()) { + try (RestClient kibanaClient = restClientAsKibanaSystem()) { final Response response = kibanaClient.performRequest(request); final Map map = entityAsMap(response); assertThat(ObjectPath.eval("username", map), instanceOf(String.class)); @@ -184,10 +184,10 @@ private RestClient restClientWithToken(String accessToken) throws IOException { getClusterHosts().toArray(new HttpHost[getClusterHosts().size()])); } - private RestClient restClientAsKibana() throws IOException { + private RestClient restClientAsKibanaSystem() throws IOException { return buildClient( - Settings.builder().put(ThreadContext.PREFIX + ".Authorization", basicAuthHeaderValue("kibana", - new SecureString("kibana".toCharArray()))).build(), + Settings.builder().put(ThreadContext.PREFIX + ".Authorization", basicAuthHeaderValue("kibana_system", + new SecureString("kibana_system".toCharArray()))).build(), getClusterHosts().toArray(new HttpHost[getClusterHosts().size()])); } } diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealm.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealm.java index 3b356e8373f33..36caee39d6091 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealm.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealm.java @@ -8,6 +8,7 @@ import org.apache.logging.log4j.message.ParameterizedMessage; import org.apache.logging.log4j.util.Supplier; import org.elasticsearch.action.ActionListener; +import org.elasticsearch.common.logging.DeprecationLogger; import org.elasticsearch.common.settings.KeyStoreWrapper; import org.elasticsearch.common.settings.SecureSetting; import org.elasticsearch.common.settings.SecureString; @@ -23,10 +24,12 @@ import org.elasticsearch.xpack.core.security.authc.support.Hasher; import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken; import org.elasticsearch.xpack.core.security.support.Exceptions; +import org.elasticsearch.xpack.core.security.support.MetadataUtils; import org.elasticsearch.xpack.core.security.user.APMSystemUser; import org.elasticsearch.xpack.core.security.user.AnonymousUser; import org.elasticsearch.xpack.core.security.user.BeatsSystemUser; import org.elasticsearch.xpack.core.security.user.ElasticUser; +import org.elasticsearch.xpack.core.security.user.KibanaSystemUser; import org.elasticsearch.xpack.core.security.user.KibanaUser; import org.elasticsearch.xpack.core.security.user.LogstashSystemUser; import org.elasticsearch.xpack.core.security.user.RemoteMonitoringUser; @@ -40,6 +43,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; /** * A realm for predefined users. These users can only be modified in terms of changing their passwords; no other modifications are allowed. @@ -62,6 +66,8 @@ public class ReservedRealm extends CachingUsernamePasswordRealm { private final ReservedUserInfo disabledDefaultUserInfo; private final ReservedUserInfo enabledDefaultUserInfo; + private final DeprecationLogger deprecationLogger = new DeprecationLogger(logger); + public ReservedRealm(Environment env, Settings settings, NativeUsersStore nativeUsersStore, AnonymousUser anonymousUser, SecurityIndexManager securityIndex, ThreadPool threadPool) { super(new RealmConfig(new RealmConfig.RealmIdentifier(TYPE, TYPE), @@ -98,6 +104,7 @@ protected void doAuthenticate(UsernamePasswordToken token, ActionListener> listener) { userInfo = reservedUserInfos.get(KibanaUser.NAME); users.add(new KibanaUser(userInfo == null || userInfo.enabled)); + userInfo = reservedUserInfos.get(KibanaSystemUser.NAME); + users.add(new KibanaSystemUser(userInfo == null || userInfo.enabled)); + userInfo = reservedUserInfos.get(LogstashSystemUser.NAME); users.add(new LogstashSystemUser(userInfo == null || userInfo.enabled)); @@ -220,6 +232,15 @@ private void getUserInfo(final String username, ActionListener } } + private void logDeprecatedUser(final User user){ + Map metadata = user.metadata(); + if (Boolean.TRUE.equals(metadata.get(MetadataUtils.DEPRECATED_METADATA_KEY))) { + deprecationLogger.deprecatedAndMaybeLog("deprecated_user-" + user.principal(), "The user [" + user.principal() + + "] is deprecated and will be removed in a future version of Elasticsearch. " + + metadata.get(MetadataUtils.DEPRECATED_REASON_METADATA_KEY)); + } + } + private ReservedUserInfo getDefaultUserInfo(String username) { if (ElasticUser.NAME.equals(username)) { return bootstrapUserInfo.deepClone(); diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordTool.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordTool.java index c2e72fb1faa3f..9a5a3e23cf451 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordTool.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordTool.java @@ -30,6 +30,7 @@ import org.elasticsearch.xpack.core.security.user.APMSystemUser; import org.elasticsearch.xpack.core.security.user.BeatsSystemUser; import org.elasticsearch.xpack.core.security.user.ElasticUser; +import org.elasticsearch.xpack.core.security.user.KibanaSystemUser; import org.elasticsearch.xpack.core.security.user.KibanaUser; import org.elasticsearch.xpack.core.security.user.LogstashSystemUser; import org.elasticsearch.xpack.core.security.user.RemoteMonitoringUser; @@ -46,7 +47,7 @@ import java.net.URL; import java.nio.charset.StandardCharsets; import java.security.SecureRandom; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -65,8 +66,10 @@ public class SetupPasswordTool extends LoggingAwareMultiCommand { private static final char[] CHARS = ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789").toCharArray(); - public static final List USERS = asList(ElasticUser.NAME, APMSystemUser.NAME, KibanaUser.NAME, LogstashSystemUser.NAME, - BeatsSystemUser.NAME, RemoteMonitoringUser.NAME); + public static final List USERS = asList(ElasticUser.NAME, APMSystemUser.NAME, KibanaUser.NAME, KibanaSystemUser.NAME, + LogstashSystemUser.NAME, BeatsSystemUser.NAME, RemoteMonitoringUser.NAME); + + public static final Map USERS_WITH_SHARED_PASSWORDS = Map.of(KibanaSystemUser.NAME, KibanaUser.NAME); private final Function clientFunction; private final CheckedFunction keyStoreFunction; @@ -503,10 +506,18 @@ private void changeUserPassword(String user, SecureString password, Terminal ter */ void changePasswords(CheckedFunction passwordFn, CheckedBiConsumer successCallback, Terminal terminal) throws Exception { - Map passwordsMap = new HashMap<>(USERS.size()); + Map passwordsMap = new LinkedHashMap<>(USERS.size()); try { for (String user : USERS) { - passwordsMap.put(user, passwordFn.apply(user)); + if (USERS_WITH_SHARED_PASSWORDS.containsValue(user)) { + continue; + } + + SecureString password = passwordFn.apply(user); + passwordsMap.put(user, password); + if (USERS_WITH_SHARED_PASSWORDS.containsKey(user)) { + passwordsMap.put(USERS_WITH_SHARED_PASSWORDS.get(user), password.clone()); + } } /* * Change elastic user last. This tool will not run after the elastic user diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/KibanaSystemRoleIntegTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/KibanaSystemRoleIntegTests.java index 39470c76438fa..7c043e749aab9 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/KibanaSystemRoleIntegTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/KibanaSystemRoleIntegTests.java @@ -27,13 +27,13 @@ public class KibanaSystemRoleIntegTests extends SecurityIntegTestCase { public String configUsers() { final String usersPasswdHashed = new String(getFastStoredHashAlgoForTests().hash(USERS_PASSWD)); return super.configUsers() + - "kibana_system:" + usersPasswdHashed; + "my_kibana_system:" + usersPasswdHashed; } @Override public String configUsersRoles() { return super.configUsersRoles() + - "kibana_system:kibana_system"; + "kibana_system:my_kibana_system"; } @@ -42,13 +42,14 @@ public void testCreateIndexDeleteInKibanaIndex() throws Exception { if (randomBoolean()) { CreateIndexResponse createIndexResponse = client().filterWithHeader(singletonMap("Authorization", - UsernamePasswordToken.basicAuthHeaderValue("kibana_system", USERS_PASSWD))) + UsernamePasswordToken.basicAuthHeaderValue("my_kibana_system", USERS_PASSWD))) .admin().indices().prepareCreate(index).get(); assertThat(createIndexResponse.isAcknowledged(), is(true)); } IndexResponse response = client() - .filterWithHeader(singletonMap("Authorization", UsernamePasswordToken.basicAuthHeaderValue("kibana_system", USERS_PASSWD))) + .filterWithHeader(singletonMap("Authorization", + UsernamePasswordToken.basicAuthHeaderValue("my_kibana_system", USERS_PASSWD))) .prepareIndex() .setIndex(index) .setSource("foo", "bar") @@ -57,7 +58,8 @@ public void testCreateIndexDeleteInKibanaIndex() throws Exception { assertEquals(DocWriteResponse.Result.CREATED, response.getResult()); DeleteResponse deleteResponse = client() - .filterWithHeader(singletonMap("Authorization", UsernamePasswordToken.basicAuthHeaderValue("kibana_system", USERS_PASSWD))) + .filterWithHeader(singletonMap("Authorization", + UsernamePasswordToken.basicAuthHeaderValue("my_kibana_system", USERS_PASSWD))) .prepareDelete(index, response.getId()) .get(); assertEquals(DocWriteResponse.Result.DELETED, deleteResponse.getResult()); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/test/NativeRealmIntegTestCase.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/test/NativeRealmIntegTestCase.java index 9836b888496f4..ad16ec0febf7e 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/test/NativeRealmIntegTestCase.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/test/NativeRealmIntegTestCase.java @@ -18,6 +18,7 @@ import org.elasticsearch.xpack.core.security.user.APMSystemUser; import org.elasticsearch.xpack.core.security.user.BeatsSystemUser; import org.elasticsearch.xpack.core.security.user.ElasticUser; +import org.elasticsearch.xpack.core.security.user.KibanaSystemUser; import org.elasticsearch.xpack.core.security.user.KibanaUser; import org.elasticsearch.xpack.core.security.user.LogstashSystemUser; import org.elasticsearch.xpack.core.security.user.RemoteMonitoringUser; @@ -108,8 +109,8 @@ public void setupReservedPasswords(RestClient restClient) throws IOException { RequestOptions.Builder optionsBuilder = RequestOptions.DEFAULT.toBuilder(); optionsBuilder.addHeader("Authorization", UsernamePasswordToken.basicAuthHeaderValue(ElasticUser.NAME, reservedPassword)); RequestOptions options = optionsBuilder.build(); - final List usernames = Arrays.asList(KibanaUser.NAME, LogstashSystemUser.NAME, BeatsSystemUser.NAME, APMSystemUser.NAME, - RemoteMonitoringUser.NAME); + final List usernames = Arrays.asList(KibanaUser.NAME, KibanaSystemUser.NAME, LogstashSystemUser.NAME, BeatsSystemUser.NAME, + APMSystemUser.NAME, RemoteMonitoringUser.NAME); for (String username : usernames) { Request request = new Request("PUT", "/_security/user/" + username + "/_password"); request.setJsonEntity("{\"password\": \"" + new String(reservedPassword.getChars()) + "\"}"); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStoreTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStoreTests.java index b8b68db6c0881..35a5f6d8c58ba 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStoreTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStoreTests.java @@ -30,6 +30,7 @@ import org.elasticsearch.xpack.core.security.user.APMSystemUser; import org.elasticsearch.xpack.core.security.user.BeatsSystemUser; import org.elasticsearch.xpack.core.security.user.ElasticUser; +import org.elasticsearch.xpack.core.security.user.KibanaSystemUser; import org.elasticsearch.xpack.core.security.user.KibanaUser; import org.elasticsearch.xpack.core.security.user.LogstashSystemUser; import org.elasticsearch.xpack.core.security.user.RemoteMonitoringUser; @@ -85,8 +86,8 @@ void doExecute(ActionType action, Request request, ActionListener future = new PlainActionFuture<>(); nativeUsersStore.setEnabled(user, true, WriteRequest.RefreshPolicy.IMMEDIATE, future); @@ -104,8 +105,8 @@ public void testPasswordUpsertWhenSetEnabledOnReservedUser() throws Exception { public void testBlankPasswordInIndexImpliesDefaultPassword() throws Exception { final NativeUsersStore nativeUsersStore = startNativeUsersStore(); - final String user = randomFrom(ElasticUser.NAME, KibanaUser.NAME, LogstashSystemUser.NAME, - BeatsSystemUser.NAME, APMSystemUser.NAME, RemoteMonitoringUser.NAME); + final String user = randomFrom(ElasticUser.NAME, KibanaUser.NAME, KibanaSystemUser.NAME, + LogstashSystemUser.NAME, BeatsSystemUser.NAME, APMSystemUser.NAME, RemoteMonitoringUser.NAME); final Map values = new HashMap<>(); values.put(ENABLED_FIELD, Boolean.TRUE); values.put(PASSWORD_FIELD, BLANK_PASSWORD); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmIntegTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmIntegTests.java index 137ba2279d96e..43f31b2cc537e 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmIntegTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmIntegTests.java @@ -19,6 +19,7 @@ import org.elasticsearch.xpack.core.security.user.APMSystemUser; import org.elasticsearch.xpack.core.security.user.BeatsSystemUser; import org.elasticsearch.xpack.core.security.user.ElasticUser; +import org.elasticsearch.xpack.core.security.user.KibanaSystemUser; import org.elasticsearch.xpack.core.security.user.KibanaUser; import org.elasticsearch.xpack.core.security.user.LogstashSystemUser; import org.elasticsearch.xpack.core.security.user.RemoteMonitoringUser; @@ -61,8 +62,8 @@ protected boolean addMockHttpTransport() { } public void testAuthenticate() { - final List usernames = Arrays.asList(ElasticUser.NAME, KibanaUser.NAME, LogstashSystemUser.NAME, - BeatsSystemUser.NAME, APMSystemUser.NAME, RemoteMonitoringUser.NAME); + final List usernames = Arrays.asList(ElasticUser.NAME, KibanaUser.NAME, KibanaSystemUser.NAME, + LogstashSystemUser.NAME, BeatsSystemUser.NAME, APMSystemUser.NAME, RemoteMonitoringUser.NAME); for (String username : usernames) { ClusterHealthResponse response = client() .filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(username, getReservedPassword()))) @@ -81,8 +82,8 @@ public void testAuthenticate() { */ public void testAuthenticateAfterEnablingUser() throws IOException { final RestHighLevelClient restClient = new TestRestHighLevelClient(); - final List usernames = Arrays.asList(ElasticUser.NAME, KibanaUser.NAME, LogstashSystemUser.NAME, - BeatsSystemUser.NAME, APMSystemUser.NAME, RemoteMonitoringUser.NAME); + final List usernames = Arrays.asList(ElasticUser.NAME, KibanaUser.NAME, KibanaSystemUser.NAME, + LogstashSystemUser.NAME, BeatsSystemUser.NAME, APMSystemUser.NAME, RemoteMonitoringUser.NAME); for (String username : usernames) { restClient.security().enableUser(new EnableUserRequest(username, RefreshPolicy.getDefault()), SECURITY_REQUEST_OPTIONS); ClusterHealthResponse response = client() @@ -97,8 +98,8 @@ public void testAuthenticateAfterEnablingUser() throws IOException { } public void testChangingPassword() throws IOException { - String username = randomFrom(ElasticUser.NAME, KibanaUser.NAME, LogstashSystemUser.NAME, - BeatsSystemUser.NAME, APMSystemUser.NAME, RemoteMonitoringUser.NAME); + String username = randomFrom(ElasticUser.NAME, KibanaUser.NAME, KibanaSystemUser.NAME, + LogstashSystemUser.NAME, BeatsSystemUser.NAME, APMSystemUser.NAME, RemoteMonitoringUser.NAME); final char[] newPassword = "supersecretvalue".toCharArray(); if (randomBoolean()) { diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmTests.java index 42efeebf03f19..a8870eef59f81 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmTests.java @@ -24,6 +24,7 @@ import org.elasticsearch.xpack.core.security.user.AnonymousUser; import org.elasticsearch.xpack.core.security.user.BeatsSystemUser; import org.elasticsearch.xpack.core.security.user.ElasticUser; +import org.elasticsearch.xpack.core.security.user.KibanaSystemUser; import org.elasticsearch.xpack.core.security.user.KibanaUser; import org.elasticsearch.xpack.core.security.user.LogstashSystemUser; import org.elasticsearch.xpack.core.security.user.RemoteMonitoringUser; @@ -162,6 +163,11 @@ private void verifySuccessfulAuthentication(boolean enabled) throws Exception { verify(securityIndex, times(2)).indexExists(); verify(usersStore, times(2)).getReservedUserInfo(eq(principal), any(ActionListener.class)); verifyNoMoreInteractions(usersStore); + + if (new KibanaUser(enabled).equals(expectedUser)) { + assertWarnings("The user [kibana] is deprecated and will be removed in a future version of Elasticsearch. " + + "Please use the [kibana_system] user instead."); + } } public void testLookup() throws Exception { @@ -249,8 +255,8 @@ public void testGetUsers() { PlainActionFuture> userFuture = new PlainActionFuture<>(); reservedRealm.users(userFuture); assertThat(userFuture.actionGet(), - containsInAnyOrder(new ElasticUser(true), new KibanaUser(true), new LogstashSystemUser(true), - new BeatsSystemUser(true), new APMSystemUser(true), new RemoteMonitoringUser(true))); + containsInAnyOrder(new ElasticUser(true), new KibanaUser(true), new KibanaSystemUser(true), + new LogstashSystemUser(true), new BeatsSystemUser(true), new APMSystemUser(true), new RemoteMonitoringUser(true))); } public void testGetUsersDisabled() { @@ -382,8 +388,8 @@ public void testNonElasticUsersCannotUseBootstrapPasswordWhenSecurityIndexExists new AnonymousUser(Settings.EMPTY), securityIndex, threadPool); PlainActionFuture listener = new PlainActionFuture<>(); - final String principal = randomFrom(KibanaUser.NAME, LogstashSystemUser.NAME, BeatsSystemUser.NAME, APMSystemUser.NAME, - RemoteMonitoringUser.NAME); + final String principal = randomFrom(KibanaUser.NAME, KibanaSystemUser.NAME, LogstashSystemUser.NAME, BeatsSystemUser.NAME, + APMSystemUser.NAME, RemoteMonitoringUser.NAME); doAnswer((i) -> { ActionListener callback = (ActionListener) i.getArguments()[1]; callback.onResponse(null); @@ -405,16 +411,16 @@ public void testNonElasticUsersCannotUseBootstrapPasswordWhenSecurityIndexDoesNo new AnonymousUser(Settings.EMPTY), securityIndex, threadPool); PlainActionFuture listener = new PlainActionFuture<>(); - final String principal = randomFrom(KibanaUser.NAME, LogstashSystemUser.NAME, BeatsSystemUser.NAME, APMSystemUser.NAME, - RemoteMonitoringUser.NAME); + final String principal = randomFrom(KibanaUser.NAME, KibanaSystemUser.NAME, LogstashSystemUser.NAME, BeatsSystemUser.NAME, + APMSystemUser.NAME, RemoteMonitoringUser.NAME); reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, mockSecureSettings.getString("bootstrap.password")), listener); final AuthenticationResult result = listener.get(); assertThat(result.getStatus(), is(AuthenticationResult.Status.TERMINATE)); } private User randomReservedUser(boolean enabled) { - return randomFrom(new ElasticUser(enabled), new KibanaUser(enabled), new LogstashSystemUser(enabled), - new BeatsSystemUser(enabled), new APMSystemUser(enabled), new RemoteMonitoringUser(enabled)); + return randomFrom(new ElasticUser(enabled), new KibanaUser(enabled), new KibanaSystemUser(enabled), + new LogstashSystemUser(enabled), new BeatsSystemUser(enabled), new APMSystemUser(enabled), new RemoteMonitoringUser(enabled)); } /* diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordToolTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordToolTests.java index d9bec2ba3701d..ebb8b02d05e2a 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordToolTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordToolTests.java @@ -111,6 +111,18 @@ public void setSecretsAndKeyStore() throws Exception { // elastic user is updated last usersInSetOrder = new ArrayList<>(SetupPasswordTool.USERS); + usersInSetOrder.sort((user1, user2) -> { + if (SetupPasswordTool.USERS_WITH_SHARED_PASSWORDS.containsKey(user1) + && SetupPasswordTool.USERS_WITH_SHARED_PASSWORDS.containsValue(user2)) { + return -1; + } + if (SetupPasswordTool.USERS_WITH_SHARED_PASSWORDS.containsKey(user2) + && SetupPasswordTool.USERS_WITH_SHARED_PASSWORDS.containsValue(user1)) { + return 1; + } + return 0; + }); + for (int i = 0; i < usersInSetOrder.size() - 1; i++) { if (ElasticUser.NAME.equals(usersInSetOrder.get(i))) { Collections.swap(usersInSetOrder, i, i + 1); @@ -118,6 +130,9 @@ public void setSecretsAndKeyStore() throws Exception { } for (String user : SetupPasswordTool.USERS) { + if (SetupPasswordTool.USERS_WITH_SHARED_PASSWORDS.containsValue(user)) { + continue; + } terminal.addSecretInput(user + "-password"); terminal.addSecretInput(user + "-password"); } @@ -168,11 +183,26 @@ public void testAutoSetup() throws Exception { URL checkUrl = authenticateUrl(url); inOrder.verify(httpClient).execute(eq("GET"), eq(checkUrl), eq(ElasticUser.NAME), eq(bootstrapPassword), any(CheckedSupplier.class), any(CheckedFunction.class)); + Map capturedPasswords = new HashMap<>(usersInSetOrder.size()); for (String user : usersInSetOrder) { URL urlWithRoute = passwordUrl(url, user); + ArgumentCaptor> passwordCaptor = ArgumentCaptor.forClass((Class) CheckedSupplier.class); inOrder.verify(httpClient).execute(eq("PUT"), eq(urlWithRoute), eq(ElasticUser.NAME), eq(bootstrapPassword), - any(CheckedSupplier.class), any(CheckedFunction.class)); + passwordCaptor.capture(), any(CheckedFunction.class)); + + String userPassword = passwordCaptor.getValue().get(); + capturedPasswords.put(user, userPassword); } + + for (Map.Entry entry : SetupPasswordTool.USERS_WITH_SHARED_PASSWORDS.entrySet()) { + assertEquals(capturedPasswords.get(entry.getKey()), capturedPasswords.get(entry.getValue())); + + capturedPasswords.remove(entry.getKey()); + capturedPasswords.remove(entry.getValue()); + } + + Set uniqueCapturedPasswords = new HashSet<>(capturedPasswords.values()); + assertEquals(uniqueCapturedPasswords.size(), capturedPasswords.size()); } public void testAuthnFail() throws Exception { @@ -391,12 +421,13 @@ public void testInteractiveSetup() throws Exception { URL checkUrl = authenticateUrl(url); inOrder.verify(httpClient).execute(eq("GET"), eq(checkUrl), eq(ElasticUser.NAME), eq(bootstrapPassword), any(CheckedSupplier.class), any(CheckedFunction.class)); + for (String user : usersInSetOrder) { URL urlWithRoute = passwordUrl(url, user); ArgumentCaptor> passwordCaptor = ArgumentCaptor.forClass((Class) CheckedSupplier.class); inOrder.verify(httpClient).execute(eq("PUT"), eq(urlWithRoute), eq(ElasticUser.NAME), eq(bootstrapPassword), passwordCaptor.capture(), any(CheckedFunction.class)); - assertThat(passwordCaptor.getValue().get(), containsString(user + "-password")); + assertThat(passwordCaptor.getValue().get(), containsString(getExpectedPasswordForUser(user))); } } @@ -409,6 +440,10 @@ public void testInteractivePasswordsFatFingers() throws Exception { } terminal.addTextInput("Y"); for (String user : SetupPasswordTool.USERS) { + if (SetupPasswordTool.USERS_WITH_SHARED_PASSWORDS.containsValue(user)) { + continue; + } + // fail in strength and match int failCount = randomIntBetween(3, 10); while (failCount-- > 0) { @@ -437,7 +472,7 @@ public void testInteractivePasswordsFatFingers() throws Exception { ArgumentCaptor> passwordCaptor = ArgumentCaptor.forClass((Class) CheckedSupplier.class); inOrder.verify(httpClient).execute(eq("PUT"), eq(urlWithRoute), eq(ElasticUser.NAME), eq(bootstrapPassword), passwordCaptor.capture(), any(CheckedFunction.class)); - assertThat(passwordCaptor.getValue().get(), containsString(user + "-password")); + assertThat(passwordCaptor.getValue().get(), containsString(getExpectedPasswordForUser(user))); } } @@ -510,4 +545,16 @@ protected Environment createEnv(Map settings) throws UserExcepti }; } + + private String getExpectedPasswordForUser(String user) throws Exception { + if (SetupPasswordTool.USERS_WITH_SHARED_PASSWORDS.containsValue(user)) { + for(Map.Entry entry : SetupPasswordTool.USERS_WITH_SHARED_PASSWORDS.entrySet()) { + if (entry.getValue().equals(user)) { + return entry.getKey() + "-password"; + } + } + throw new Exception("Expected to find corresponding user for " + user); + } + return user + "-password"; + } } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/pki/PkiAuthDelegationIntegTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/pki/PkiAuthDelegationIntegTests.java index d707e9dee5be2..1792858648c95 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/pki/PkiAuthDelegationIntegTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/pki/PkiAuthDelegationIntegTests.java @@ -83,7 +83,7 @@ protected String configUsers() { "user_manage_security:" + usersPasswdHashed + "\n" + "user_delegate_pki:" + usersPasswdHashed + "\n" + "user_all:" + usersPasswdHashed + "\n" + - "kibana_system:" + usersPasswdHashed + "\n"; + "my_kibana_system:" + usersPasswdHashed + "\n"; } @Override @@ -109,7 +109,7 @@ protected String configUsersRoles() { "role_manage_security:user_manage_security\n" + "role_delegate_pki:user_delegate_pki\n" + "role_all:user_all\n" + - "kibana_system:kibana_system\n"; + "kibana_system:my_kibana_system\n"; } @Override @@ -140,7 +140,7 @@ public void testDelegateThenAuthenticate() throws Exception { } try (RestHighLevelClient restClient = new TestRestHighLevelClient()) { - for (String delegateeUsername : Arrays.asList("user_all", "user_delegate_pki", "kibana_system")) { + for (String delegateeUsername : Arrays.asList("user_all", "user_delegate_pki", "my_kibana_system")) { // delegate RequestOptions.Builder optionsBuilder = RequestOptions.DEFAULT.toBuilder(); optionsBuilder.addHeader("Authorization", @@ -177,7 +177,7 @@ public void testTokenInvalidate() throws Exception { } try (RestHighLevelClient restClient = new TestRestHighLevelClient()) { - String delegateeUsername = randomFrom("user_all", "user_delegate_pki", "kibana_system"); + String delegateeUsername = randomFrom("user_all", "user_delegate_pki", "my_kibana_system"); // delegate RequestOptions.Builder optionsBuilder = RequestOptions.DEFAULT.toBuilder(); optionsBuilder.addHeader("Authorization", diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/user/UserSerializationTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/user/UserSerializationTests.java index fa7f2719a8543..d06ae97420a94 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/user/UserSerializationTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/user/UserSerializationTests.java @@ -10,6 +10,7 @@ import org.elasticsearch.xpack.core.security.user.AsyncSearchUser; import org.elasticsearch.xpack.core.security.user.ElasticUser; import org.elasticsearch.xpack.core.security.user.InternalUserSerializationHelper; +import org.elasticsearch.xpack.core.security.user.KibanaSystemUser; import org.elasticsearch.xpack.core.security.user.KibanaUser; import org.elasticsearch.xpack.core.security.user.SystemUser; import org.elasticsearch.xpack.core.security.user.User; @@ -124,5 +125,12 @@ public void testReservedUserSerialization() throws Exception { readFrom = User.readFrom(output.bytes().streamInput()); assertEquals(kibanaUser, readFrom); + + final KibanaSystemUser kibanaSystemUser = new KibanaSystemUser(true); + output = new BytesStreamOutput(); + User.writeTo(kibanaSystemUser, output); + readFrom = User.readFrom(output.bytes().streamInput()); + + assertEquals(kibanaSystemUser, readFrom); } } diff --git a/x-pack/qa/security-setup-password-tests/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordToolIT.java b/x-pack/qa/security-setup-password-tests/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordToolIT.java index 364d1fb1e2d3a..a5c1a9391ccf0 100644 --- a/x-pack/qa/security-setup-password-tests/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordToolIT.java +++ b/x-pack/qa/security-setup-password-tests/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordToolIT.java @@ -9,6 +9,7 @@ import org.elasticsearch.client.Request; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.Response; +import org.elasticsearch.client.WarningsHandler; import org.elasticsearch.common.Strings; import org.elasticsearch.common.SuppressForbidden; import org.elasticsearch.common.io.PathUtils; @@ -98,7 +99,7 @@ public void testSetupPasswordToolAutoSetup() throws Exception { } }); - assertEquals(6, userPasswordMap.size()); + assertEquals(7, userPasswordMap.size()); userPasswordMap.entrySet().forEach(entry -> { final String basicHeader = "Basic " + Base64.getEncoder().encodeToString((entry.getKey() + ":" + entry.getValue()).getBytes(StandardCharsets.UTF_8)); @@ -106,6 +107,10 @@ public void testSetupPasswordToolAutoSetup() throws Exception { Request request = new Request("GET", "/_security/_authenticate"); RequestOptions.Builder options = request.getOptions().toBuilder(); options.addHeader("Authorization", basicHeader); + if ("kibana".equals(entry.getKey())) { + // the kibana user is deprecated so a warning header is expected + options.setWarningsHandler(WarningsHandler.PERMISSIVE); + } request.setOptions(options); Map userInfoMap = entityAsMap(client().performRequest(request)); assertEquals(entry.getKey(), userInfoMap.get("username"));