Browse Source

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 <elasticmachine@users.noreply.github.com>
Larry Gregory 5 years ago
parent
commit
269b152a8f
23 changed files with 277 additions and 111 deletions
  1. 3 3
      client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java
  2. 37 0
      docs/reference/migration/migrate_8_0/security.asciidoc
  3. 4 4
      x-pack/docs/en/security/auditing/output-logfile.asciidoc
  4. 15 15
      x-pack/docs/en/security/authentication/built-in-users.asciidoc
  5. 3 3
      x-pack/docs/en/security/get-started-builtin-users.asciidoc
  6. 21 21
      x-pack/docs/en/security/get-started-kibana-users.asciidoc
  7. 18 18
      x-pack/docs/en/security/securing-communications/tutorial-tls-internode.asciidoc
  8. 1 0
      x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/esnative/ClientReservedRealm.java
  9. 21 0
      x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/KibanaSystemUser.java
  10. 5 2
      x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/KibanaUser.java
  11. 2 1
      x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/UsernamesField.java
  12. 6 6
      x-pack/plugin/identity-provider/qa/idp-rest-tests/src/test/java/org/elasticsearch/xpack/idp/IdentityProviderAuthenticationIT.java
  13. 21 0
      x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealm.java
  14. 16 5
      x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordTool.java
  15. 7 5
      x-pack/plugin/security/src/test/java/org/elasticsearch/integration/KibanaSystemRoleIntegTests.java
  16. 3 2
      x-pack/plugin/security/src/test/java/org/elasticsearch/test/NativeRealmIntegTestCase.java
  17. 5 4
      x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStoreTests.java
  18. 7 6
      x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmIntegTests.java
  19. 14 8
      x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmTests.java
  20. 50 3
      x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordToolTests.java
  21. 4 4
      x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/pki/PkiAuthDelegationIntegTests.java
  22. 8 0
      x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/user/UserSerializationTests.java
  23. 6 1
      x-pack/qa/security-setup-password-tests/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordToolIT.java

+ 3 - 3
client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java

@@ -200,11 +200,11 @@ public class SecurityDocumentationIT extends ESRestHighLevelClientTestCase {
             List<User> 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));
         }
 
         {

+ 37 - 0
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.

+ 4 - 4
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.

+ 15 - 15
x-pack/docs/en/security/authentication/built-in-users.asciidoc

@@ -12,9 +12,9 @@ used to <<set-built-in-user-passwords,set all of the built-in user passwords>>.
 `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 <<monitoring-production>>. 
+The `remote_monitoring_user` is used when {metricbeat} collects and stores
+monitoring data for the {stack}. See <<monitoring-production>>.
 
 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
 <<security-api-change-password,change password API>> 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
 <<security-api-change-password,change password API>> to set a password
 for these users.

+ 3 - 3
x-pack/docs/en/security/get-started-builtin-users.asciidoc

@@ -1,13 +1,13 @@
 // tag::create-users[]
 There are <<built-in-users,built-in users>> 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:
 +
 --

+ 21 - 21
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}]. 
---
+See {kibana-ref}/start-stop.html[Starting and stopping {kib}].
+--

+ 18 - 18
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
 <<bootstrap-checks-tls,TLS bootstrap check>>.
 
 . (Optional) Name the cluster.
@@ -23,10 +23,10 @@ For example, add the <<cluster.name,cluster.name>> 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
 <<settings>>.
 
 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 <<modules-discovery-bootstrap-cluster>> and
 <<discovery-settings>>.
 --
 
 . 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 <<get-started-enable-security>> and 
+For more information, see <<get-started-enable-security>> and
 <<transport-tls-ssl-settings>>.
 --
 
@@ -116,7 +116,7 @@ For more information, see <<get-started-enable-security>> 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,
 <<get-started-kibana-user,configure {kib} to use it>>.
 
 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}].
 --

+ 1 - 0
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/esnative/ClientReservedRealm.java

@@ -16,6 +16,7 @@ public class ClientReservedRealm {
         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:

+ 21 - 0
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);
+    }
+}

+ 5 - 2
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/KibanaUser.java

@@ -9,13 +9,16 @@ import org.elasticsearch.xpack.core.security.support.MetadataUtils;
 
 /**
  * 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);
     }
 }

+ 2 - 1
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/UsernamesField.java

@@ -8,7 +8,8 @@ package org.elasticsearch.xpack.core.security.user;
 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";

+ 6 - 6
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 @@ public class IdentityProviderAuthenticationIT extends IdpRestTestCase {
     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<String, Object> map = entityAsMap(response);
             assertThat(ObjectPath.eval("realm", map), equalTo(realmName));
@@ -152,7 +152,7 @@ public class IdentityProviderAuthenticationIT extends IdpRestTestCase {
             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<String, Object> map = entityAsMap(response);
             assertThat(ObjectPath.eval("username", map), instanceOf(String.class));
@@ -184,10 +184,10 @@ public class IdentityProviderAuthenticationIT extends IdpRestTestCase {
             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()]));
     }
 }

+ 21 - 0
x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealm.java

@@ -8,6 +8,7 @@ package org.elasticsearch.xpack.security.authc.esnative;
 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.esnative.ClientReservedRealm;
 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.Arrays;
 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 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
                             result = AuthenticationResult.terminate("failed to authenticate user [" + token.principal() + "]", null);
                         } else if (userInfo.verifyPassword(token.credentials())) {
                             final User user = getUser(token.principal(), userInfo);
+                            logDeprecatedUser(user);
                             result = AuthenticationResult.success(user);
                         } else {
                             result = AuthenticationResult.terminate("failed to authenticate user [" + token.principal() + "]", null);
@@ -147,6 +154,8 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
                 return new ElasticUser(userInfo.enabled);
             case KibanaUser.NAME:
                 return new KibanaUser(userInfo.enabled);
+            case KibanaSystemUser.NAME:
+                return new KibanaSystemUser(userInfo.enabled);
             case LogstashSystemUser.NAME:
                 return new LogstashSystemUser(userInfo.enabled);
             case BeatsSystemUser.NAME:
@@ -177,6 +186,9 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
                 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 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
         }
     }
 
+    private void logDeprecatedUser(final User user){
+        Map<String, Object> 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();

+ 16 - 5
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.support.Validation;
 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.URISyntaxException;
 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 @@ import static java.util.Arrays.asList;
 public class SetupPasswordTool extends LoggingAwareMultiCommand {
 
     private static final char[] CHARS = ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789").toCharArray();
-    public static final List<String> USERS = asList(ElasticUser.NAME, APMSystemUser.NAME, KibanaUser.NAME, LogstashSystemUser.NAME,
-        BeatsSystemUser.NAME, RemoteMonitoringUser.NAME);
+    public static final List<String> USERS = asList(ElasticUser.NAME, APMSystemUser.NAME, KibanaUser.NAME, KibanaSystemUser.NAME,
+        LogstashSystemUser.NAME, BeatsSystemUser.NAME, RemoteMonitoringUser.NAME);
+
+    public static final Map<String, String> USERS_WITH_SHARED_PASSWORDS = Map.of(KibanaSystemUser.NAME, KibanaUser.NAME);
 
     private final Function<Environment, CommandLineHttpClient> clientFunction;
     private final CheckedFunction<Environment, KeyStoreWrapper, Exception> keyStoreFunction;
@@ -503,10 +506,18 @@ public class SetupPasswordTool extends LoggingAwareMultiCommand {
          */
         void changePasswords(CheckedFunction<String, SecureString, UserException> passwordFn,
                              CheckedBiConsumer<String, SecureString, Exception> successCallback, Terminal terminal) throws Exception {
-            Map<String, SecureString> passwordsMap = new HashMap<>(USERS.size());
+            Map<String, SecureString> 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

+ 7 - 5
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 class KibanaSystemRoleIntegTests extends SecurityIntegTestCase {
 
         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 class KibanaSystemRoleIntegTests extends SecurityIntegTestCase {
         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());

+ 3 - 2
x-pack/plugin/security/src/test/java/org/elasticsearch/test/NativeRealmIntegTestCase.java

@@ -18,6 +18,7 @@ import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken
 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 abstract class NativeRealmIntegTestCase extends SecurityIntegTestCase {
         RequestOptions.Builder optionsBuilder = RequestOptions.DEFAULT.toBuilder();
         optionsBuilder.addHeader("Authorization", UsernamePasswordToken.basicAuthHeaderValue(ElasticUser.NAME, reservedPassword));
         RequestOptions options = optionsBuilder.build();
-        final List<String> usernames = Arrays.asList(KibanaUser.NAME, LogstashSystemUser.NAME, BeatsSystemUser.NAME, APMSystemUser.NAME,
-            RemoteMonitoringUser.NAME);
+        final List<String> 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()) + "\"}");

+ 5 - 4
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.index.RestrictedIndicesNames;
 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 @@ public class NativeUsersStoreTests extends ESTestCase {
     public void testPasswordUpsertWhenSetEnabledOnReservedUser() 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 PlainActionFuture<Void> future = new PlainActionFuture<>();
         nativeUsersStore.setEnabled(user, true, WriteRequest.RefreshPolicy.IMMEDIATE, future);
@@ -104,8 +105,8 @@ public class NativeUsersStoreTests extends ESTestCase {
     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<String, Object> values = new HashMap<>();
         values.put(ENABLED_FIELD, Boolean.TRUE);
         values.put(PASSWORD_FIELD, BLANK_PASSWORD);

+ 7 - 6
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.authc.support.Hasher;
 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 @@ public class ReservedRealmIntegTests extends NativeRealmIntegTestCase {
     }
 
     public void testAuthenticate() {
-        final List<String> usernames = Arrays.asList(ElasticUser.NAME, KibanaUser.NAME, LogstashSystemUser.NAME,
-            BeatsSystemUser.NAME, APMSystemUser.NAME, RemoteMonitoringUser.NAME);
+        final List<String> 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 class ReservedRealmIntegTests extends NativeRealmIntegTestCase {
      */
     public void testAuthenticateAfterEnablingUser() throws IOException {
         final RestHighLevelClient restClient = new TestRestHighLevelClient();
-        final List<String> usernames = Arrays.asList(ElasticUser.NAME, KibanaUser.NAME, LogstashSystemUser.NAME,
-            BeatsSystemUser.NAME, APMSystemUser.NAME, RemoteMonitoringUser.NAME);
+        final List<String> 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 class ReservedRealmIntegTests extends NativeRealmIntegTestCase {
     }
 
     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()) {

+ 14 - 8
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.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;
@@ -162,6 +163,11 @@ public class ReservedRealmTests extends ESTestCase {
         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 class ReservedRealmTests extends ESTestCase {
         PlainActionFuture<Collection<User>> 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 class ReservedRealmTests extends ESTestCase {
             new AnonymousUser(Settings.EMPTY), securityIndex, threadPool);
         PlainActionFuture<AuthenticationResult> 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 class ReservedRealmTests extends ESTestCase {
             new AnonymousUser(Settings.EMPTY), securityIndex, threadPool);
         PlainActionFuture<AuthenticationResult> 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));
     }
 
     /*

+ 50 - 3
x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordToolTests.java

@@ -111,6 +111,18 @@ public class SetupPasswordToolTests extends CommandTestCase {
 
         // 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 class SetupPasswordToolTests extends CommandTestCase {
         }
 
         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 class SetupPasswordToolTests extends CommandTestCase {
         URL checkUrl = authenticateUrl(url);
         inOrder.verify(httpClient).execute(eq("GET"), eq(checkUrl), eq(ElasticUser.NAME), eq(bootstrapPassword), any(CheckedSupplier.class),
                 any(CheckedFunction.class));
+        Map<String, String> capturedPasswords = new HashMap<>(usersInSetOrder.size());
         for (String user : usersInSetOrder) {
             URL urlWithRoute = passwordUrl(url, user);
+            ArgumentCaptor<CheckedSupplier<String, Exception>> 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<String, String> 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<String> uniqueCapturedPasswords = new HashSet<>(capturedPasswords.values());
+       assertEquals(uniqueCapturedPasswords.size(), capturedPasswords.size());
     }
 
     public void testAuthnFail() throws Exception {
@@ -391,12 +421,13 @@ public class SetupPasswordToolTests extends CommandTestCase {
         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<CheckedSupplier<String, Exception>> 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 class SetupPasswordToolTests extends CommandTestCase {
         }
         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 class SetupPasswordToolTests extends CommandTestCase {
             ArgumentCaptor<CheckedSupplier<String, Exception>> 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 @@ public class SetupPasswordToolTests extends CommandTestCase {
         };
 
     }
+
+    private String getExpectedPasswordForUser(String user) throws Exception {
+        if (SetupPasswordTool.USERS_WITH_SHARED_PASSWORDS.containsValue(user)) {
+            for(Map.Entry<String, String> 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";
+    }
 }

+ 4 - 4
x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/pki/PkiAuthDelegationIntegTests.java

@@ -83,7 +83,7 @@ public class PkiAuthDelegationIntegTests extends SecurityIntegTestCase {
             "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 @@ public class PkiAuthDelegationIntegTests extends SecurityIntegTestCase {
                 "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 class PkiAuthDelegationIntegTests extends SecurityIntegTestCase {
         }
 
         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 class PkiAuthDelegationIntegTests extends SecurityIntegTestCase {
         }
 
         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",

+ 8 - 0
x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/user/UserSerializationTests.java

@@ -10,6 +10,7 @@ import org.elasticsearch.test.ESTestCase;
 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 class UserSerializationTests extends ESTestCase {
         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);
     }
 }

+ 6 - 1
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.cli.MockTerminal;
 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 class SetupPasswordToolIT extends ESRestTestCase {
             }
         });
 
-        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 class SetupPasswordToolIT extends ESRestTestCase {
                 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<String, Object> userInfoMap = entityAsMap(client().performRequest(request));
                 assertEquals(entry.getKey(), userInfoMap.get("username"));