Backport: Deprecate the kibana reserved user (#54967) (#55822)

This commit is contained in:
Larry Gregory 2020-04-28 10:30:25 -04:00 committed by GitHub
parent ddc7305ac9
commit 47d252424b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 284 additions and 112 deletions

View File

@ -198,10 +198,11 @@ public class SecurityDocumentationIT extends ESRestHighLevelClientTestCase {
List<User> users = new ArrayList<>(3); List<User> users = new ArrayList<>(3);
users.addAll(response.getUsers()); users.addAll(response.getUsers());
assertNotNull(response); assertNotNull(response);
// 9 users are expected to be returned // 10 users are expected to be returned
// test_users (3): user1, user2, user3 // 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
assertThat(users.size(), equalTo(9)); logger.info(users);
assertThat(users.size(), equalTo(10));
} }
{ {

View File

@ -92,4 +92,40 @@ To avoid deprecation warnings, discontinue use of the `node.local_storage`
setting. setting.
==== ====
//end::notable-breaking-changes[] [float]
[[builtin-users-changes]]
==== Changes to built-in users
[float]
===== The `kibana` user has been deprecated 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 deprecated 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.
//end::notable-breaking-changes[]

View File

@ -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. 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 To turn off the deprecated output format, you can disable the logger in the
`log4j2.properties` file: `log4j2.properties` file:
[source, properties] [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` All policies are defined under the `xpack.security.audit.logfile.events.ignore_filters`
settings namespace. For example, the following policy named _example1_ matches 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*_: wildcard form _app-logs*_:
[source,yaml] [source,yaml]
---------------------------- ----------------------------
xpack.security.audit.logfile.events.ignore_filters: xpack.security.audit.logfile.events.ignore_filters:
example1: example1:
users: ["kibana", "admin_user"] users: ["kibana_system", "admin_user"]
indices: ["app-logs*"] 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. , 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 As expected, operations generated by all other users (even operating only on indices that
match the _indices_ filter) will not match this policy either. match the _indices_ filter) will not match this policy either.

View File

@ -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}. `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}. `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}. `apm_system`:: The user the APM server uses when storing monitoring information in {es}.
`remote_monitoring_user`:: The user {metricbeat} uses when collecting and `remote_monitoring_user`:: The user {metricbeat} uses when collecting and
storing monitoring information in {es}. It has the `remote_monitoring_agent` and storing monitoring information in {es}. It has the `remote_monitoring_agent` and
`remote_monitoring_collector` built-in roles. `remote_monitoring_collector` built-in roles.
TIP: The built-in users serve specific purposes and are not intended for general 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 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 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 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 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: and `remote_monitoring_user` users:
[source,shell] [source,shell]
@ -107,7 +107,7 @@ since at that point the bootstrap password is no longer required.
[[add-built-in-user-kibana]] [[add-built-in-user-kibana]]
==== Adding built-in user passwords to {kib} ==== 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` with the new password by setting `elasticsearch.password` in the `kibana.yml`
configuration file: configuration file:
@ -120,7 +120,7 @@ See {kibana-ref}/using-kibana-with-security.html[Configuring security in {kib}].
[float] [float]
[[add-built-in-user-logstash]] [[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 The `logstash_system` user is used internally within Logstash when
monitoring is enabled for Logstash. 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 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] [float]
[[add-built-in-user-beats]] [[add-built-in-user-beats]]
@ -161,13 +161,13 @@ xpack.monitoring.elasticsearch.username: beats_system
xpack.monitoring.elasticsearch.password: beatspassword 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 The `remote_monitoring_user` is used when {metricbeat} collects and stores
monitoring data for the {stack}. See <<monitoring-production>>. 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 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 the case, then you should use the *Management > Users* page in {kib} or the
{ref}/security-api-change-password.html[Change Password API] to set a password {ref}/security-api-change-password.html[Change Password API] to set a password
for these users. for these users.
@ -178,8 +178,8 @@ for these users.
The `apm_system` user is used internally within APM when monitoring is enabled. The `apm_system` user is used internally within APM when monitoring is enabled.
To enable this feature in APM, you need to update the To enable this feature in APM, you need to update the
{apm-server-ref-70}/configuring-howto-apm-server.html[APM configuration file] to {apm-server-ref-70}/configuring-howto-apm-server.html[APM configuration file] to
reference the correct username and password. For example: reference the correct username and password. For example:
[source,yaml] [source,yaml]
@ -188,10 +188,10 @@ xpack.monitoring.elasticsearch.username: apm_system
xpack.monitoring.elasticsearch.password: apmserverpassword xpack.monitoring.elasticsearch.password: apmserverpassword
---------------------------------------------------------- ----------------------------------------------------------
See {apm-server-ref-70}/monitoring.html[Monitoring APM Server]. See {apm-server-ref-70}/monitoring.html[Monitoring APM Server].
If you have upgraded from an older version of {es}, then you may not have set a 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 then you should use the *Management > Users* page in {kib} or the
{ref}/security-api-change-password.html[Change Password API] to set a password {ref}/security-api-change-password.html[Change Password API] to set a password
for these users. for these users.

View File

@ -1,13 +1,13 @@
// tag::create-users[] // tag::create-users[]
There are <<built-in-users,built-in users>> that you can use for specific There are <<built-in-users,built-in users>> that you can use for specific
administrative purposes: `apm_system`, `beats_system`, `elastic`, `kibana`, administrative purposes: `apm_system`, `beats_system`, `elastic`, `kibana_system`,
`logstash_system`, and `remote_monitoring_user`. `logstash_system`, and `remote_monitoring_user`.
// end::create-users[] // end::create-users[]
Before you can use them, you must set their passwords: 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: the following command from the {es} directory:
+ +
-- --

View File

@ -1,36 +1,36 @@
When the {es} {security-features} are enabled, users must log in to {kib} 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 {kib} also performs some tasks under the covers that require use of the
built-in `kibana` user. 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: created:
** If you don't mind having passwords visible in your configuration file, ** 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 uncomment and update the following settings in the `kibana.yml` file in your
{kib} directory: {kib} directory:
+ +
-- --
TIP: If you installed {kib} using archive distributions (`zip` or TIP: If you installed {kib} using archive distributions (`zip` or
`tar.gz`), the `kibana.yml` configuration file is in `KIBANA_HOME/config`. If `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 you used package distributions (Debian or RPM), it's in `/etc/kibana`. For more
information, see {kibana-ref}/settings.html[Configuring {kib}]. information, see {kibana-ref}/settings.html[Configuring {kib}].
For example, add the following settings: For example, add the following settings:
[source,yaml] [source,yaml]
---- ----
elasticsearch.username: "kibana" elasticsearch.username: "kibana_system"
elasticsearch.password: "your_password" elasticsearch.password: "your_password"
---- ----
Specify the password that you set with the `elasticsearch-setup-passwords` Specify the password that you set with the `elasticsearch-setup-passwords`
command then save your changes to the file. command then save your changes to the file.
-- --
** If you prefer not to put your user ID and password in the `kibana.yml` 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} store them in a keystore instead. Run the following commands to create the {kib}
keystore and add the secure settings: keystore and add the secure settings:
+ +
-- --
@ -42,14 +42,14 @@ keystore and add the secure settings:
./bin/kibana-keystore add elasticsearch.password ./bin/kibana-keystore add elasticsearch.password
---------------------------------------------------------------------- ----------------------------------------------------------------------
When prompted, specify the `kibana` built-in user and its password for these 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}. setting values. The settings are automatically applied when you start {kib}.
To learn more, see {kibana-ref}/secure-settings.html[Secure settings]. To learn more, see {kibana-ref}/secure-settings.html[Secure settings].
// end::store-kibana-user[] // end::store-kibana-user[]
-- --
. Restart {kib}. For example, if you installed . Restart {kib}. For example, if you installed
{kib} with a `.tar.gz` package, run the following command from the {kib} {kib} with a `.tar.gz` package, run the following command from the {kib}
directory: directory:
+ +
-- --
@ -58,5 +58,5 @@ directory:
./bin/kibana ./bin/kibana
---------------------------------------------------------------------- ----------------------------------------------------------------------
See {kibana-ref}/start-stop.html[Starting and stopping {kib}]. See {kibana-ref}/start-stop.html[Starting and stopping {kib}].
-- --

View File

@ -1,7 +1,7 @@
[role="xpack"] [role="xpack"]
[testenv="trial"] [testenv="trial"]
[[encrypting-internode]] [[encrypting-internode]]
=== Encrypt internode communications === Encrypt internode communications
Now that we've generated a certificate authority and certificates, let's update Now that we've generated a certificate authority and certificates, let's update
the cluster to use these files. 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 IMPORTANT: When you enable {es} {security-features}, unless you have a trial
license, you must use Transport Layer Security (TLS) to encrypt internode license, you must use Transport Layer Security (TLS) to encrypt internode
communication. By following the steps in this tutorial tutorial, you learn how 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
{ref}/bootstrap-checks-xpack.html#bootstrap-checks-tls[TLS bootstrap check]. {ref}/bootstrap-checks-xpack.html#bootstrap-checks-tls[TLS bootstrap check].
. (Optional) Name the cluster. . (Optional) Name the cluster.
@ -23,11 +23,11 @@ For example, add the {ref}/cluster.name.html[cluster.name] setting in the
cluster.name: test-cluster cluster.name: test-cluster
---- ----
TIP: The `ES_PATH_CONF` environment variable contains the path for the {es} TIP: The `ES_PATH_CONF` environment variable contains the path for the {es}
configuration files. If you installed {es} using archive distributions (`zip` or configuration files. If you installed {es} using archive distributions (`zip` or
`tar.gz`), it defaults to `ES_HOME/config`. If you used package distributions `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 (Debian or RPM), it defaults to `/etc/elasticsearch`. For more information, see
{ref}/settings.html[Configuring {es}]. <<settings>>.
The default cluster name is `elasticsearch`. You should choose a unique name, The default cluster name is `elasticsearch`. You should choose a unique name,
however, to ensure that your nodes join the right cluster. however, to ensure that your nodes join the right cluster.
@ -46,7 +46,7 @@ node.name: node-1
In this tutorial, the cluster will consist of three nodes that exist on the same 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 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 This step is also necessary if you want to use the `node.name` value to define
the location of certificates in subsequent steps. 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 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` first time, add all of those node names to the `cluster.initial_master_nodes`
setting. setting.
See {ref}/modules-discovery-bootstrap-cluster.html[Bootstrapping a cluster] and See {ref}/modules-discovery-bootstrap-cluster.html[Bootstrapping a cluster] and
{ref}/discovery-settings.html[Important discovery and cluster formation settings]. {ref}/discovery-settings.html[Important discovery and cluster formation settings].
-- --
. Enable Transport Layer Security (TLS/SSL) for transport (internode) . Enable Transport Layer Security (TLS/SSL) for transport (internode)
communications. communications.
+ +
-- --
// tag::enable-tls[] // tag::enable-tls[]
@ -95,20 +95,20 @@ file:
[source,yaml] [source,yaml]
---- ----
xpack.security.enabled: true 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.keystore.path: certs/${node.name}.p12 <1>
xpack.security.transport.ssl.truststore.path: certs/${node.name}.p12 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, <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[] // end::enable-tls[]
NOTE: The PKCS#12 keystore that is output by the `elasticsearch-certutil` can be 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, generate your certificates, you might have different values for these settings,
but that scenario is not covered in this tutorial. 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
{ref}/security-settings.html#transport-tls-ssl-settings[Transport TLS settings]. {ref}/security-settings.html#transport-tls-ssl-settings[Transport TLS settings].
-- --
@ -116,7 +116,7 @@ For more information, see <<get-started-enable-security>> and
+ +
-- --
// tag::secure-passwords[] // tag::secure-passwords[]
For example, run the following commands: For example, run the following commands:
["source","sh",subs="attributes,callouts"] ["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, 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] 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>>. <<get-started-kibana-user,configure {kib} to use it>>.
For example, run the following commands to create the {kib} keystore and add the 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] 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 ./bin/kibana
---------------------------------------------------------------------- ----------------------------------------------------------------------
See {kibana-ref}/start-stop.html[Starting and stopping {kib}]. See {kibana-ref}/start-stop.html[Starting and stopping {kib}].
-- --

View File

@ -16,6 +16,7 @@ public class ClientReservedRealm {
assert username != null; assert username != null;
switch (username) { switch (username) {
case UsernamesField.ELASTIC_NAME: case UsernamesField.ELASTIC_NAME:
case UsernamesField.DEPRECATED_KIBANA_NAME:
case UsernamesField.KIBANA_NAME: case UsernamesField.KIBANA_NAME:
case UsernamesField.LOGSTASH_NAME: case UsernamesField.LOGSTASH_NAME:
case UsernamesField.BEATS_NAME: case UsernamesField.BEATS_NAME:

View File

@ -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);
}
}

View File

@ -9,13 +9,16 @@ import org.elasticsearch.xpack.core.security.support.MetadataUtils;
/** /**
* Built in user for the kibana server * Built in user for the kibana server
* @deprecated use KibanaSystemUser
*/ */
@Deprecated
public class KibanaUser extends User { 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 static final String ROLE_NAME = UsernamesField.KIBANA_ROLE;
public KibanaUser(boolean enabled) { 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);
} }
} }

View File

@ -8,7 +8,8 @@ package org.elasticsearch.xpack.core.security.user;
public final class UsernamesField { public final class UsernamesField {
public static final String ELASTIC_NAME = "elastic"; public static final String ELASTIC_NAME = "elastic";
public static final String ELASTIC_ROLE = "superuser"; 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 KIBANA_ROLE = "kibana_system";
public static final String SYSTEM_NAME = "_system"; public static final String SYSTEM_NAME = "_system";
public static final String SYSTEM_ROLE = "_system"; public static final String SYSTEM_ROLE = "_system";

View File

@ -46,7 +46,7 @@ public class IdentityProviderAuthenticationIT extends IdpRestTestCase {
@Before @Before
public void setupSecurityData() throws IOException { public void setupSecurityData() throws IOException {
setUserPassword("kibana", new SecureString("kibana".toCharArray())); setUserPassword("kibana_system", new SecureString("kibana_system".toCharArray()));
createApplicationPrivileges("elastic-cloud", org.elasticsearch.common.collect.Map.of( createApplicationPrivileges("elastic-cloud", org.elasticsearch.common.collect.Map.of(
"deployment_admin", Set.of("sso:admin"), "deployment_admin", Set.of("sso:admin"),
"deployment_viewer", Set.of("sso:viewer")) "deployment_viewer", Set.of("sso:viewer"))
@ -114,7 +114,7 @@ public class IdentityProviderAuthenticationIT extends IdpRestTestCase {
private SamlPrepareAuthenticationResponse generateSamlAuthnRequest(String realmName) throws Exception { private SamlPrepareAuthenticationResponse generateSamlAuthnRequest(String realmName) throws Exception {
final Request request = new Request("POST", "/_security/saml/prepare"); final Request request = new Request("POST", "/_security/saml/prepare");
request.setJsonEntity("{\"realm\":\"" + realmName + "\"}"); request.setJsonEntity("{\"realm\":\"" + realmName + "\"}");
try (RestClient kibanaClient = restClientAsKibana()) { try (RestClient kibanaClient = restClientAsKibanaSystem()) {
final Response response = kibanaClient.performRequest(request); final Response response = kibanaClient.performRequest(request);
final Map<String, Object> map = entityAsMap(response); final Map<String, Object> map = entityAsMap(response);
assertThat(ObjectPath.eval("realm", map), equalTo(realmName)); assertThat(ObjectPath.eval("realm", map), equalTo(realmName));
@ -153,7 +153,7 @@ public class IdentityProviderAuthenticationIT extends IdpRestTestCase {
request.setJsonEntity("{\"content\":\"" + encodedResponse + "\", \"realm\":\"" + REALM_NAME + "\"}"); request.setJsonEntity("{\"content\":\"" + encodedResponse + "\", \"realm\":\"" + REALM_NAME + "\"}");
} }
final String accessToken; final String accessToken;
try (RestClient kibanaClient = restClientAsKibana()) { try (RestClient kibanaClient = restClientAsKibanaSystem()) {
final Response response = kibanaClient.performRequest(request); final Response response = kibanaClient.performRequest(request);
final Map<String, Object> map = entityAsMap(response); final Map<String, Object> map = entityAsMap(response);
assertThat(ObjectPath.eval("username", map), instanceOf(String.class)); assertThat(ObjectPath.eval("username", map), instanceOf(String.class));
@ -185,10 +185,10 @@ public class IdentityProviderAuthenticationIT extends IdpRestTestCase {
getClusterHosts().toArray(new HttpHost[getClusterHosts().size()])); getClusterHosts().toArray(new HttpHost[getClusterHosts().size()]));
} }
private RestClient restClientAsKibana() throws IOException { private RestClient restClientAsKibanaSystem() throws IOException {
return buildClient( return buildClient(
Settings.builder().put(ThreadContext.PREFIX + ".Authorization", basicAuthHeaderValue("kibana", Settings.builder().put(ThreadContext.PREFIX + ".Authorization", basicAuthHeaderValue("kibana_system",
new SecureString("kibana".toCharArray()))).build(), new SecureString("kibana_system".toCharArray()))).build(),
getClusterHosts().toArray(new HttpHost[getClusterHosts().size()])); getClusterHosts().toArray(new HttpHost[getClusterHosts().size()]));
} }
} }

View File

@ -9,6 +9,7 @@ import org.apache.logging.log4j.message.ParameterizedMessage;
import org.apache.logging.log4j.util.Supplier; import org.apache.logging.log4j.util.Supplier;
import org.elasticsearch.Version; import org.elasticsearch.Version;
import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionListener;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.settings.KeyStoreWrapper; import org.elasticsearch.common.settings.KeyStoreWrapper;
import org.elasticsearch.common.settings.SecureSetting; import org.elasticsearch.common.settings.SecureSetting;
import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.common.settings.SecureString;
@ -24,10 +25,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.Hasher;
import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken; import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken;
import org.elasticsearch.xpack.core.security.support.Exceptions; 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.APMSystemUser;
import org.elasticsearch.xpack.core.security.user.AnonymousUser; import org.elasticsearch.xpack.core.security.user.AnonymousUser;
import org.elasticsearch.xpack.core.security.user.BeatsSystemUser; import org.elasticsearch.xpack.core.security.user.BeatsSystemUser;
import org.elasticsearch.xpack.core.security.user.ElasticUser; 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.KibanaUser;
import org.elasticsearch.xpack.core.security.user.LogstashSystemUser; import org.elasticsearch.xpack.core.security.user.LogstashSystemUser;
import org.elasticsearch.xpack.core.security.user.RemoteMonitoringUser; import org.elasticsearch.xpack.core.security.user.RemoteMonitoringUser;
@ -41,6 +44,7 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; 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. * A realm for predefined users. These users can only be modified in terms of changing their passwords; no other modifications are allowed.
@ -66,6 +70,8 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
private final ReservedUserInfo disabledDefaultUserInfo; private final ReservedUserInfo disabledDefaultUserInfo;
private final ReservedUserInfo enabledDefaultUserInfo; private final ReservedUserInfo enabledDefaultUserInfo;
private final DeprecationLogger deprecationLogger = new DeprecationLogger(logger);
public ReservedRealm(Environment env, Settings settings, NativeUsersStore nativeUsersStore, AnonymousUser anonymousUser, public ReservedRealm(Environment env, Settings settings, NativeUsersStore nativeUsersStore, AnonymousUser anonymousUser,
SecurityIndexManager securityIndex, ThreadPool threadPool) { SecurityIndexManager securityIndex, ThreadPool threadPool) {
super(new RealmConfig(new RealmConfig.RealmIdentifier(TYPE, TYPE), settings, env, threadPool.getThreadContext()), threadPool); super(new RealmConfig(new RealmConfig.RealmIdentifier(TYPE, TYPE), settings, env, threadPool.getThreadContext()), threadPool);
@ -98,6 +104,7 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
result = AuthenticationResult.terminate("failed to authenticate user [" + token.principal() + "]", null); result = AuthenticationResult.terminate("failed to authenticate user [" + token.principal() + "]", null);
} else if (userInfo.verifyPassword(token.credentials())) { } else if (userInfo.verifyPassword(token.credentials())) {
final User user = getUser(token.principal(), userInfo); final User user = getUser(token.principal(), userInfo);
logDeprecatedUser(user);
result = AuthenticationResult.success(user); result = AuthenticationResult.success(user);
} else { } else {
result = AuthenticationResult.terminate("failed to authenticate user [" + token.principal() + "]", null); result = AuthenticationResult.terminate("failed to authenticate user [" + token.principal() + "]", null);
@ -147,6 +154,8 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
return new ElasticUser(userInfo.enabled); return new ElasticUser(userInfo.enabled);
case KibanaUser.NAME: case KibanaUser.NAME:
return new KibanaUser(userInfo.enabled); return new KibanaUser(userInfo.enabled);
case KibanaSystemUser.NAME:
return new KibanaSystemUser(userInfo.enabled);
case LogstashSystemUser.NAME: case LogstashSystemUser.NAME:
return new LogstashSystemUser(userInfo.enabled); return new LogstashSystemUser(userInfo.enabled);
case BeatsSystemUser.NAME: case BeatsSystemUser.NAME:
@ -177,6 +186,9 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
userInfo = reservedUserInfos.get(KibanaUser.NAME); userInfo = reservedUserInfos.get(KibanaUser.NAME);
users.add(new KibanaUser(userInfo == null || userInfo.enabled)); 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); userInfo = reservedUserInfos.get(LogstashSystemUser.NAME);
users.add(new LogstashSystemUser(userInfo == null || userInfo.enabled)); users.add(new LogstashSystemUser(userInfo == null || userInfo.enabled));
@ -223,6 +235,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) { private ReservedUserInfo getDefaultUserInfo(String username) {
if (ElasticUser.NAME.equals(username)) { if (ElasticUser.NAME.equals(username)) {
return bootstrapUserInfo.deepClone(); return bootstrapUserInfo.deepClone();

View File

@ -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.APMSystemUser;
import org.elasticsearch.xpack.core.security.user.BeatsSystemUser; import org.elasticsearch.xpack.core.security.user.BeatsSystemUser;
import org.elasticsearch.xpack.core.security.user.ElasticUser; 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.KibanaUser;
import org.elasticsearch.xpack.core.security.user.LogstashSystemUser; import org.elasticsearch.xpack.core.security.user.LogstashSystemUser;
import org.elasticsearch.xpack.core.security.user.RemoteMonitoringUser; import org.elasticsearch.xpack.core.security.user.RemoteMonitoringUser;
@ -46,7 +47,9 @@ import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
@ -65,8 +68,14 @@ import static java.util.Arrays.asList;
public class SetupPasswordTool extends LoggingAwareMultiCommand { public class SetupPasswordTool extends LoggingAwareMultiCommand {
private static final char[] CHARS = ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789").toCharArray(); private static final char[] CHARS = ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789").toCharArray();
public static final List<String> USERS = asList(ElasticUser.NAME, APMSystemUser.NAME, KibanaUser.NAME, LogstashSystemUser.NAME, public static final List<String> USERS = asList(ElasticUser.NAME, APMSystemUser.NAME, KibanaUser.NAME, KibanaSystemUser.NAME,
BeatsSystemUser.NAME, RemoteMonitoringUser.NAME); LogstashSystemUser.NAME, BeatsSystemUser.NAME, RemoteMonitoringUser.NAME);
public static final Map<String, String> USERS_WITH_SHARED_PASSWORDS = Collections.unmodifiableMap(new HashMap<String, String>() {
{
put(KibanaSystemUser.NAME, KibanaUser.NAME);
}
});
private final BiFunction<Environment, Settings, CommandLineHttpClient> clientFunction; private final BiFunction<Environment, Settings, CommandLineHttpClient> clientFunction;
private final CheckedFunction<Environment, KeyStoreWrapper, Exception> keyStoreFunction; private final CheckedFunction<Environment, KeyStoreWrapper, Exception> keyStoreFunction;
@ -503,10 +512,18 @@ public class SetupPasswordTool extends LoggingAwareMultiCommand {
*/ */
void changePasswords(CheckedFunction<String, SecureString, UserException> passwordFn, void changePasswords(CheckedFunction<String, SecureString, UserException> passwordFn,
CheckedBiConsumer<String, SecureString, Exception> successCallback, Terminal terminal) throws Exception { 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 { try {
for (String user : USERS) { 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 * Change elastic user last. This tool will not run after the elastic user

View File

@ -27,13 +27,13 @@ public class KibanaSystemRoleIntegTests extends SecurityIntegTestCase {
public String configUsers() { public String configUsers() {
final String usersPasswdHashed = new String(getFastStoredHashAlgoForTests().hash(USERS_PASSWD)); final String usersPasswdHashed = new String(getFastStoredHashAlgoForTests().hash(USERS_PASSWD));
return super.configUsers() + return super.configUsers() +
"kibana_system:" + usersPasswdHashed; "my_kibana_system:" + usersPasswdHashed;
} }
@Override @Override
public String configUsersRoles() { public String configUsersRoles() {
return super.configUsersRoles() + return super.configUsersRoles() +
"kibana_system:kibana_system"; "kibana_system:my_kibana_system";
} }
@ -42,13 +42,14 @@ public class KibanaSystemRoleIntegTests extends SecurityIntegTestCase {
if (randomBoolean()) { if (randomBoolean()) {
CreateIndexResponse createIndexResponse = client().filterWithHeader(singletonMap("Authorization", CreateIndexResponse createIndexResponse = client().filterWithHeader(singletonMap("Authorization",
UsernamePasswordToken.basicAuthHeaderValue("kibana_system", USERS_PASSWD))) UsernamePasswordToken.basicAuthHeaderValue("my_kibana_system", USERS_PASSWD)))
.admin().indices().prepareCreate(index).get(); .admin().indices().prepareCreate(index).get();
assertThat(createIndexResponse.isAcknowledged(), is(true)); assertThat(createIndexResponse.isAcknowledged(), is(true));
} }
IndexResponse response = client() IndexResponse response = client()
.filterWithHeader(singletonMap("Authorization", UsernamePasswordToken.basicAuthHeaderValue("kibana_system", USERS_PASSWD))) .filterWithHeader(singletonMap("Authorization",
UsernamePasswordToken.basicAuthHeaderValue("my_kibana_system", USERS_PASSWD)))
.prepareIndex() .prepareIndex()
.setIndex(index) .setIndex(index)
.setType("dashboard") .setType("dashboard")
@ -58,7 +59,8 @@ public class KibanaSystemRoleIntegTests extends SecurityIntegTestCase {
assertEquals(DocWriteResponse.Result.CREATED, response.getResult()); assertEquals(DocWriteResponse.Result.CREATED, response.getResult());
DeleteResponse deleteResponse = client() DeleteResponse deleteResponse = client()
.filterWithHeader(singletonMap("Authorization", UsernamePasswordToken.basicAuthHeaderValue("kibana_system", USERS_PASSWD))) .filterWithHeader(singletonMap("Authorization",
UsernamePasswordToken.basicAuthHeaderValue("my_kibana_system", USERS_PASSWD)))
.prepareDelete(index, "dashboard", response.getId()) .prepareDelete(index, "dashboard", response.getId())
.get(); .get();
assertEquals(DocWriteResponse.Result.DELETED, deleteResponse.getResult()); assertEquals(DocWriteResponse.Result.DELETED, deleteResponse.getResult());

View File

@ -17,6 +17,7 @@ import org.elasticsearch.xpack.core.security.client.SecurityClient;
import org.elasticsearch.xpack.core.security.user.APMSystemUser; import org.elasticsearch.xpack.core.security.user.APMSystemUser;
import org.elasticsearch.xpack.core.security.user.BeatsSystemUser; import org.elasticsearch.xpack.core.security.user.BeatsSystemUser;
import org.elasticsearch.xpack.core.security.user.ElasticUser; 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.KibanaUser;
import org.elasticsearch.xpack.core.security.user.LogstashSystemUser; import org.elasticsearch.xpack.core.security.user.LogstashSystemUser;
import org.elasticsearch.xpack.core.security.user.RemoteMonitoringUser; import org.elasticsearch.xpack.core.security.user.RemoteMonitoringUser;
@ -103,8 +104,8 @@ public abstract class NativeRealmIntegTestCase extends SecurityIntegTestCase {
RequestOptions.Builder optionsBuilder = RequestOptions.DEFAULT.toBuilder(); RequestOptions.Builder optionsBuilder = RequestOptions.DEFAULT.toBuilder();
optionsBuilder.addHeader("Authorization", UsernamePasswordToken.basicAuthHeaderValue(ElasticUser.NAME, reservedPassword)); optionsBuilder.addHeader("Authorization", UsernamePasswordToken.basicAuthHeaderValue(ElasticUser.NAME, reservedPassword));
RequestOptions options = optionsBuilder.build(); RequestOptions options = optionsBuilder.build();
final List<String> usernames = Arrays.asList(KibanaUser.NAME, LogstashSystemUser.NAME, BeatsSystemUser.NAME, APMSystemUser.NAME, final List<String> usernames = Arrays.asList(KibanaUser.NAME, KibanaSystemUser.NAME, LogstashSystemUser.NAME, BeatsSystemUser.NAME,
RemoteMonitoringUser.NAME); APMSystemUser.NAME, RemoteMonitoringUser.NAME);
for (String username : usernames) { for (String username : usernames) {
Request request = new Request("PUT", "/_security/user/" + username + "/_password"); Request request = new Request("PUT", "/_security/user/" + username + "/_password");
request.setJsonEntity("{\"password\": \"" + new String(reservedPassword.getChars()) + "\"}"); request.setJsonEntity("{\"password\": \"" + new String(reservedPassword.getChars()) + "\"}");

View File

@ -31,6 +31,7 @@ import org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames;
import org.elasticsearch.xpack.core.security.user.APMSystemUser; import org.elasticsearch.xpack.core.security.user.APMSystemUser;
import org.elasticsearch.xpack.core.security.user.BeatsSystemUser; import org.elasticsearch.xpack.core.security.user.BeatsSystemUser;
import org.elasticsearch.xpack.core.security.user.ElasticUser; 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.KibanaUser;
import org.elasticsearch.xpack.core.security.user.LogstashSystemUser; import org.elasticsearch.xpack.core.security.user.LogstashSystemUser;
import org.elasticsearch.xpack.core.security.user.RemoteMonitoringUser; import org.elasticsearch.xpack.core.security.user.RemoteMonitoringUser;
@ -86,8 +87,8 @@ public class NativeUsersStoreTests extends ESTestCase {
public void testPasswordUpsertWhenSetEnabledOnReservedUser() throws Exception { public void testPasswordUpsertWhenSetEnabledOnReservedUser() throws Exception {
final NativeUsersStore nativeUsersStore = startNativeUsersStore(); final NativeUsersStore nativeUsersStore = startNativeUsersStore();
final String user = randomFrom(ElasticUser.NAME, KibanaUser.NAME, LogstashSystemUser.NAME, final String user = randomFrom(ElasticUser.NAME, KibanaUser.NAME, KibanaSystemUser.NAME,
BeatsSystemUser.NAME, APMSystemUser.NAME, RemoteMonitoringUser.NAME); LogstashSystemUser.NAME, BeatsSystemUser.NAME, APMSystemUser.NAME, RemoteMonitoringUser.NAME);
final PlainActionFuture<Void> future = new PlainActionFuture<>(); final PlainActionFuture<Void> future = new PlainActionFuture<>();
nativeUsersStore.setEnabled(user, true, WriteRequest.RefreshPolicy.IMMEDIATE, future); nativeUsersStore.setEnabled(user, true, WriteRequest.RefreshPolicy.IMMEDIATE, future);
@ -105,8 +106,8 @@ public class NativeUsersStoreTests extends ESTestCase {
public void testBlankPasswordInIndexImpliesDefaultPassword() throws Exception { public void testBlankPasswordInIndexImpliesDefaultPassword() throws Exception {
final NativeUsersStore nativeUsersStore = startNativeUsersStore(); final NativeUsersStore nativeUsersStore = startNativeUsersStore();
final String user = randomFrom(ElasticUser.NAME, KibanaUser.NAME, LogstashSystemUser.NAME, final String user = randomFrom(ElasticUser.NAME, KibanaUser.NAME, KibanaSystemUser.NAME,
BeatsSystemUser.NAME, APMSystemUser.NAME, RemoteMonitoringUser.NAME); LogstashSystemUser.NAME, BeatsSystemUser.NAME, APMSystemUser.NAME, RemoteMonitoringUser.NAME);
final Map<String, Object> values = new HashMap<>(); final Map<String, Object> values = new HashMap<>();
values.put(ENABLED_FIELD, Boolean.TRUE); values.put(ENABLED_FIELD, Boolean.TRUE);
values.put(PASSWORD_FIELD, BLANK_PASSWORD); values.put(PASSWORD_FIELD, BLANK_PASSWORD);

View File

@ -16,6 +16,7 @@ import org.elasticsearch.xpack.core.security.client.SecurityClient;
import org.elasticsearch.xpack.core.security.user.APMSystemUser; import org.elasticsearch.xpack.core.security.user.APMSystemUser;
import org.elasticsearch.xpack.core.security.user.BeatsSystemUser; import org.elasticsearch.xpack.core.security.user.BeatsSystemUser;
import org.elasticsearch.xpack.core.security.user.ElasticUser; 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.KibanaUser;
import org.elasticsearch.xpack.core.security.user.LogstashSystemUser; import org.elasticsearch.xpack.core.security.user.LogstashSystemUser;
import org.elasticsearch.xpack.core.security.user.RemoteMonitoringUser; import org.elasticsearch.xpack.core.security.user.RemoteMonitoringUser;
@ -52,8 +53,8 @@ public class ReservedRealmIntegTests extends NativeRealmIntegTestCase {
} }
public void testAuthenticate() { public void testAuthenticate() {
final List<String> usernames = Arrays.asList(ElasticUser.NAME, KibanaUser.NAME, LogstashSystemUser.NAME, final List<String> usernames = Arrays.asList(ElasticUser.NAME, KibanaUser.NAME, KibanaSystemUser.NAME,
BeatsSystemUser.NAME, APMSystemUser.NAME, RemoteMonitoringUser.NAME); LogstashSystemUser.NAME, BeatsSystemUser.NAME, APMSystemUser.NAME, RemoteMonitoringUser.NAME);
for (String username : usernames) { for (String username : usernames) {
ClusterHealthResponse response = client() ClusterHealthResponse response = client()
.filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(username, getReservedPassword()))) .filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(username, getReservedPassword())))
@ -72,8 +73,8 @@ public class ReservedRealmIntegTests extends NativeRealmIntegTestCase {
*/ */
public void testAuthenticateAfterEnablingUser() { public void testAuthenticateAfterEnablingUser() {
final SecurityClient c = securityClient(); final SecurityClient c = securityClient();
final List<String> usernames = Arrays.asList(ElasticUser.NAME, KibanaUser.NAME, LogstashSystemUser.NAME, final List<String> usernames = Arrays.asList(ElasticUser.NAME, KibanaUser.NAME, KibanaSystemUser.NAME,
BeatsSystemUser.NAME, APMSystemUser.NAME, RemoteMonitoringUser.NAME); LogstashSystemUser.NAME, BeatsSystemUser.NAME, APMSystemUser.NAME, RemoteMonitoringUser.NAME);
for (String username : usernames) { for (String username : usernames) {
c.prepareSetEnabled(username, true).get(); c.prepareSetEnabled(username, true).get();
ClusterHealthResponse response = client() ClusterHealthResponse response = client()
@ -88,8 +89,8 @@ public class ReservedRealmIntegTests extends NativeRealmIntegTestCase {
} }
public void testChangingPassword() { public void testChangingPassword() {
String username = randomFrom(ElasticUser.NAME, KibanaUser.NAME, LogstashSystemUser.NAME, String username = randomFrom(ElasticUser.NAME, KibanaUser.NAME, KibanaSystemUser.NAME,
BeatsSystemUser.NAME, APMSystemUser.NAME, RemoteMonitoringUser.NAME); LogstashSystemUser.NAME, BeatsSystemUser.NAME, APMSystemUser.NAME, RemoteMonitoringUser.NAME);
final char[] newPassword = "supersecretvalue".toCharArray(); final char[] newPassword = "supersecretvalue".toCharArray();
if (randomBoolean()) { if (randomBoolean()) {

View File

@ -25,6 +25,7 @@ import org.elasticsearch.xpack.core.security.user.APMSystemUser;
import org.elasticsearch.xpack.core.security.user.AnonymousUser; import org.elasticsearch.xpack.core.security.user.AnonymousUser;
import org.elasticsearch.xpack.core.security.user.BeatsSystemUser; import org.elasticsearch.xpack.core.security.user.BeatsSystemUser;
import org.elasticsearch.xpack.core.security.user.ElasticUser; 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.KibanaUser;
import org.elasticsearch.xpack.core.security.user.LogstashSystemUser; import org.elasticsearch.xpack.core.security.user.LogstashSystemUser;
import org.elasticsearch.xpack.core.security.user.RemoteMonitoringUser; import org.elasticsearch.xpack.core.security.user.RemoteMonitoringUser;
@ -169,6 +170,11 @@ public class ReservedRealmTests extends ESTestCase {
verify(securityIndex, times(2)).checkMappingVersion(predicateCaptor.capture()); verify(securityIndex, times(2)).checkMappingVersion(predicateCaptor.capture());
verifyVersionPredicate(principal, predicateCaptor.getValue()); verifyVersionPredicate(principal, predicateCaptor.getValue());
verifyNoMoreInteractions(usersStore); 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 { public void testLookup() throws Exception {
@ -264,8 +270,8 @@ public class ReservedRealmTests extends ESTestCase {
PlainActionFuture<Collection<User>> userFuture = new PlainActionFuture<>(); PlainActionFuture<Collection<User>> userFuture = new PlainActionFuture<>();
reservedRealm.users(userFuture); reservedRealm.users(userFuture);
assertThat(userFuture.actionGet(), assertThat(userFuture.actionGet(),
containsInAnyOrder(new ElasticUser(true), new KibanaUser(true), new LogstashSystemUser(true), containsInAnyOrder(new ElasticUser(true), new KibanaUser(true), new KibanaSystemUser(true),
new BeatsSystemUser(true), new APMSystemUser(true), new RemoteMonitoringUser(true))); new LogstashSystemUser(true), new BeatsSystemUser(true), new APMSystemUser(true), new RemoteMonitoringUser(true)));
} }
public void testGetUsersDisabled() { public void testGetUsersDisabled() {
@ -397,8 +403,8 @@ public class ReservedRealmTests extends ESTestCase {
new AnonymousUser(Settings.EMPTY), securityIndex, threadPool); new AnonymousUser(Settings.EMPTY), securityIndex, threadPool);
PlainActionFuture<AuthenticationResult> listener = new PlainActionFuture<>(); PlainActionFuture<AuthenticationResult> listener = new PlainActionFuture<>();
final String principal = randomFrom(KibanaUser.NAME, LogstashSystemUser.NAME, BeatsSystemUser.NAME, APMSystemUser.NAME, final String principal = randomFrom(KibanaUser.NAME, KibanaSystemUser.NAME, LogstashSystemUser.NAME, BeatsSystemUser.NAME,
RemoteMonitoringUser.NAME); APMSystemUser.NAME, RemoteMonitoringUser.NAME);
doAnswer((i) -> { doAnswer((i) -> {
ActionListener callback = (ActionListener) i.getArguments()[1]; ActionListener callback = (ActionListener) i.getArguments()[1];
callback.onResponse(null); callback.onResponse(null);
@ -420,16 +426,16 @@ public class ReservedRealmTests extends ESTestCase {
new AnonymousUser(Settings.EMPTY), securityIndex, threadPool); new AnonymousUser(Settings.EMPTY), securityIndex, threadPool);
PlainActionFuture<AuthenticationResult> listener = new PlainActionFuture<>(); PlainActionFuture<AuthenticationResult> listener = new PlainActionFuture<>();
final String principal = randomFrom(KibanaUser.NAME, LogstashSystemUser.NAME, BeatsSystemUser.NAME, APMSystemUser.NAME, final String principal = randomFrom(KibanaUser.NAME, KibanaSystemUser.NAME, LogstashSystemUser.NAME, BeatsSystemUser.NAME,
RemoteMonitoringUser.NAME); APMSystemUser.NAME, RemoteMonitoringUser.NAME);
reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, mockSecureSettings.getString("bootstrap.password")), listener); reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, mockSecureSettings.getString("bootstrap.password")), listener);
final AuthenticationResult result = listener.get(); final AuthenticationResult result = listener.get();
assertThat(result.getStatus(), is(AuthenticationResult.Status.TERMINATE)); assertThat(result.getStatus(), is(AuthenticationResult.Status.TERMINATE));
} }
private User randomReservedUser(boolean enabled) { private User randomReservedUser(boolean enabled) {
return randomFrom(new ElasticUser(enabled), new KibanaUser(enabled), new LogstashSystemUser(enabled), return randomFrom(new ElasticUser(enabled), new KibanaUser(enabled), new KibanaSystemUser(enabled),
new BeatsSystemUser(enabled), new APMSystemUser(enabled), new RemoteMonitoringUser(enabled)); new LogstashSystemUser(enabled), new BeatsSystemUser(enabled), new APMSystemUser(enabled), new RemoteMonitoringUser(enabled));
} }
/* /*

View File

@ -111,6 +111,18 @@ public class SetupPasswordToolTests extends CommandTestCase {
// elastic user is updated last // elastic user is updated last
usersInSetOrder = new ArrayList<>(SetupPasswordTool.USERS); 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++) { for (int i = 0; i < usersInSetOrder.size() - 1; i++) {
if (ElasticUser.NAME.equals(usersInSetOrder.get(i))) { if (ElasticUser.NAME.equals(usersInSetOrder.get(i))) {
Collections.swap(usersInSetOrder, i, i + 1); Collections.swap(usersInSetOrder, i, i + 1);
@ -118,6 +130,9 @@ public class SetupPasswordToolTests extends CommandTestCase {
} }
for (String user : SetupPasswordTool.USERS) { for (String user : SetupPasswordTool.USERS) {
if (SetupPasswordTool.USERS_WITH_SHARED_PASSWORDS.containsValue(user)) {
continue;
}
terminal.addSecretInput(user + "-password"); terminal.addSecretInput(user + "-password");
terminal.addSecretInput(user + "-password"); terminal.addSecretInput(user + "-password");
} }
@ -168,11 +183,26 @@ public class SetupPasswordToolTests extends CommandTestCase {
URL checkUrl = authenticateUrl(url); URL checkUrl = authenticateUrl(url);
inOrder.verify(httpClient).execute(eq("GET"), eq(checkUrl), eq(ElasticUser.NAME), eq(bootstrapPassword), any(CheckedSupplier.class), inOrder.verify(httpClient).execute(eq("GET"), eq(checkUrl), eq(ElasticUser.NAME), eq(bootstrapPassword), any(CheckedSupplier.class),
any(CheckedFunction.class)); any(CheckedFunction.class));
Map<String, String> capturedPasswords = new HashMap<>(usersInSetOrder.size());
for (String user : usersInSetOrder) { for (String user : usersInSetOrder) {
URL urlWithRoute = passwordUrl(url, user); 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), 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 { public void testAuthnFail() throws Exception {
@ -391,12 +421,13 @@ public class SetupPasswordToolTests extends CommandTestCase {
URL checkUrl = authenticateUrl(url); URL checkUrl = authenticateUrl(url);
inOrder.verify(httpClient).execute(eq("GET"), eq(checkUrl), eq(ElasticUser.NAME), eq(bootstrapPassword), any(CheckedSupplier.class), inOrder.verify(httpClient).execute(eq("GET"), eq(checkUrl), eq(ElasticUser.NAME), eq(bootstrapPassword), any(CheckedSupplier.class),
any(CheckedFunction.class)); any(CheckedFunction.class));
for (String user : usersInSetOrder) { for (String user : usersInSetOrder) {
URL urlWithRoute = passwordUrl(url, user); URL urlWithRoute = passwordUrl(url, user);
ArgumentCaptor<CheckedSupplier<String, Exception>> passwordCaptor = ArgumentCaptor.forClass((Class) CheckedSupplier.class); ArgumentCaptor<CheckedSupplier<String, Exception>> passwordCaptor = ArgumentCaptor.forClass((Class) CheckedSupplier.class);
inOrder.verify(httpClient).execute(eq("PUT"), eq(urlWithRoute), eq(ElasticUser.NAME), eq(bootstrapPassword), inOrder.verify(httpClient).execute(eq("PUT"), eq(urlWithRoute), eq(ElasticUser.NAME), eq(bootstrapPassword),
passwordCaptor.capture(), any(CheckedFunction.class)); 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"); terminal.addTextInput("Y");
for (String user : SetupPasswordTool.USERS) { for (String user : SetupPasswordTool.USERS) {
if (SetupPasswordTool.USERS_WITH_SHARED_PASSWORDS.containsValue(user)) {
continue;
}
// fail in strength and match // fail in strength and match
int failCount = randomIntBetween(3, 10); int failCount = randomIntBetween(3, 10);
while (failCount-- > 0) { while (failCount-- > 0) {
@ -437,7 +472,7 @@ public class SetupPasswordToolTests extends CommandTestCase {
ArgumentCaptor<CheckedSupplier<String, Exception>> passwordCaptor = ArgumentCaptor.forClass((Class) CheckedSupplier.class); ArgumentCaptor<CheckedSupplier<String, Exception>> passwordCaptor = ArgumentCaptor.forClass((Class) CheckedSupplier.class);
inOrder.verify(httpClient).execute(eq("PUT"), eq(urlWithRoute), eq(ElasticUser.NAME), eq(bootstrapPassword), inOrder.verify(httpClient).execute(eq("PUT"), eq(urlWithRoute), eq(ElasticUser.NAME), eq(bootstrapPassword),
passwordCaptor.capture(), any(CheckedFunction.class)); 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";
}
} }

View File

@ -83,7 +83,7 @@ public class PkiAuthDelegationIntegTests extends SecurityIntegTestCase {
"user_manage_security:" + usersPasswdHashed + "\n" + "user_manage_security:" + usersPasswdHashed + "\n" +
"user_delegate_pki:" + usersPasswdHashed + "\n" + "user_delegate_pki:" + usersPasswdHashed + "\n" +
"user_all:" + usersPasswdHashed + "\n" + "user_all:" + usersPasswdHashed + "\n" +
"kibana_system:" + usersPasswdHashed + "\n"; "my_kibana_system:" + usersPasswdHashed + "\n";
} }
@Override @Override
@ -109,7 +109,7 @@ public class PkiAuthDelegationIntegTests extends SecurityIntegTestCase {
"role_manage_security:user_manage_security\n" + "role_manage_security:user_manage_security\n" +
"role_delegate_pki:user_delegate_pki\n" + "role_delegate_pki:user_delegate_pki\n" +
"role_all:user_all\n" + "role_all:user_all\n" +
"kibana_system:kibana_system\n"; "kibana_system:my_kibana_system\n";
} }
@Override @Override
@ -140,7 +140,7 @@ public class PkiAuthDelegationIntegTests extends SecurityIntegTestCase {
} }
try (RestHighLevelClient restClient = new TestRestHighLevelClient()) { 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 // delegate
RequestOptions.Builder optionsBuilder = RequestOptions.DEFAULT.toBuilder(); RequestOptions.Builder optionsBuilder = RequestOptions.DEFAULT.toBuilder();
optionsBuilder.addHeader("Authorization", optionsBuilder.addHeader("Authorization",
@ -177,7 +177,7 @@ public class PkiAuthDelegationIntegTests extends SecurityIntegTestCase {
} }
try (RestHighLevelClient restClient = new TestRestHighLevelClient()) { 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 // delegate
RequestOptions.Builder optionsBuilder = RequestOptions.DEFAULT.toBuilder(); RequestOptions.Builder optionsBuilder = RequestOptions.DEFAULT.toBuilder();
optionsBuilder.addHeader("Authorization", optionsBuilder.addHeader("Authorization",

View File

@ -10,6 +10,7 @@ import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.core.security.user.AsyncSearchUser; import org.elasticsearch.xpack.core.security.user.AsyncSearchUser;
import org.elasticsearch.xpack.core.security.user.ElasticUser; import org.elasticsearch.xpack.core.security.user.ElasticUser;
import org.elasticsearch.xpack.core.security.user.InternalUserSerializationHelper; 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.KibanaUser;
import org.elasticsearch.xpack.core.security.user.SystemUser; import org.elasticsearch.xpack.core.security.user.SystemUser;
import org.elasticsearch.xpack.core.security.user.User; import org.elasticsearch.xpack.core.security.user.User;
@ -124,5 +125,12 @@ public class UserSerializationTests extends ESTestCase {
readFrom = User.readFrom(output.bytes().streamInput()); readFrom = User.readFrom(output.bytes().streamInput());
assertEquals(kibanaUser, readFrom); 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);
} }
} }

View File

@ -9,6 +9,7 @@ import org.elasticsearch.cli.MockTerminal;
import org.elasticsearch.client.Request; import org.elasticsearch.client.Request;
import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Response; import org.elasticsearch.client.Response;
import org.elasticsearch.client.WarningsHandler;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.SuppressForbidden; import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.io.PathUtils; 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 -> { userPasswordMap.entrySet().forEach(entry -> {
final String basicHeader = "Basic " + final String basicHeader = "Basic " +
Base64.getEncoder().encodeToString((entry.getKey() + ":" + entry.getValue()).getBytes(StandardCharsets.UTF_8)); 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"); Request request = new Request("GET", "/_security/_authenticate");
RequestOptions.Builder options = request.getOptions().toBuilder(); RequestOptions.Builder options = request.getOptions().toBuilder();
options.addHeader("Authorization", basicHeader); 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); request.setOptions(options);
Map<String, Object> userInfoMap = entityAsMap(client().performRequest(request)); Map<String, Object> userInfoMap = entityAsMap(client().performRequest(request));
assertEquals(entry.getKey(), userInfoMap.get("username")); assertEquals(entry.getKey(), userInfoMap.get("username"));