diff --git a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/MonitoredSystem.java b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/MonitoredSystem.java index 47180c7970f..96cee79f148 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/MonitoredSystem.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/MonitoredSystem.java @@ -11,7 +11,8 @@ public enum MonitoredSystem { ES("es"), KIBANA("kibana"), - LOGSTASH("logstash"); + LOGSTASH("logstash"), + BEATS("beats"); private final String system; @@ -31,6 +32,8 @@ public enum MonitoredSystem { return KIBANA; case "logstash": return LOGSTASH; + case "beats": + return BEATS; default: throw new IllegalArgumentException("Unknown monitoring system [" + system + "]"); } diff --git a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/exporter/MonitoringTemplateUtils.java b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/exporter/MonitoringTemplateUtils.java index ea39b1c6b20..2b5bcdcc80b 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/exporter/MonitoringTemplateUtils.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/exporter/MonitoringTemplateUtils.java @@ -24,7 +24,7 @@ public final class MonitoringTemplateUtils { /** * Data types that should be supported by the {@linkplain #DATA_INDEX data index} that were not by the initial release. */ - public static final String[] NEW_DATA_TYPES = { "kibana", "logstash" }; + public static final String[] NEW_DATA_TYPES = { "kibana", "logstash", "beats" }; private MonitoringTemplateUtils() { } diff --git a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/resolver/ResolversRegistry.java b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/resolver/ResolversRegistry.java index 99b79f146cb..c43ba1ee7ff 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/resolver/ResolversRegistry.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/resolver/ResolversRegistry.java @@ -51,6 +51,7 @@ public class ResolversRegistry implements Iterable // register resolvers for monitored systems registerMonitoredSystem(MonitoredSystem.KIBANA, settings); registerMonitoredSystem(MonitoredSystem.LOGSTASH, settings); + registerMonitoredSystem(MonitoredSystem.BEATS, settings); } /** diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmMigrator.java b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmMigrator.java index 8ad050786d4..fb8afb3f9e3 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmMigrator.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmMigrator.java @@ -24,6 +24,8 @@ import org.elasticsearch.xpack.security.SecurityLifecycleService; import org.elasticsearch.xpack.security.authc.support.Hasher; import org.elasticsearch.xpack.security.authc.support.SecuredString; import org.elasticsearch.xpack.security.client.SecurityClient; +import org.elasticsearch.xpack.security.user.BeatsSystemUser; +import org.elasticsearch.xpack.security.user.BuiltinUserInfo; import org.elasticsearch.xpack.security.user.LogstashSystemUser; import org.elasticsearch.xpack.security.user.User; @@ -37,6 +39,8 @@ import java.util.function.BiConsumer; import static java.util.Collections.emptyList; import static org.elasticsearch.xpack.security.SecurityLifecycleService.SECURITY_INDEX_NAME; +import java.util.ArrayList; + /** * Performs migration steps for the {@link NativeRealm} and {@link ReservedRealm}. * When upgrading an Elasticsearch/X-Pack installation from a previous version, this class is responsible for ensuring that user/role @@ -47,6 +51,10 @@ public class NativeRealmMigrator { private final XPackLicenseState licenseState; private final Logger logger; private InternalClient client; + private final BuiltinUserInfo[] builtinUsers = new BuiltinUserInfo[] { + LogstashSystemUser.USER_INFO, + BeatsSystemUser.USER_INFO + }; public NativeRealmMigrator(Settings settings, XPackLicenseState licenseState, InternalClient internalClient) { this.licenseState = licenseState; @@ -85,9 +93,12 @@ public class NativeRealmMigrator { private List>> collectUpgradeTasks(@Nullable Version previousVersion) { List>> tasks = new ArrayList<>(); - if (shouldDisableLogstashUser(previousVersion)) { - tasks.add(this::createLogstashUserAsDisabled); + for (BuiltinUserInfo info : builtinUsers) { + if (isNewUser(previousVersion, info)) { + tasks.add((v,l) -> createUserAsDisabled(info, v, l)); + } } + if (shouldConvertDefaultPasswords(previousVersion)) { tasks.add(this::doConvertDefaultPasswords); } @@ -95,41 +106,42 @@ public class NativeRealmMigrator { } /** - * If we're upgrading from a security version where the {@link LogstashSystemUser} did not exist, then we mark the user as disabled. + * If we're upgrading from a security version where the new user did not exist, then we mark the user as disabled. * Otherwise the user will exist with a default password, which is desirable for an out-of-the-box experience in fresh * installs but problematic for already-locked-down upgrades. */ - private boolean shouldDisableLogstashUser(@Nullable Version previousVersion) { - return previousVersion != null && previousVersion.before(LogstashSystemUser.DEFINED_SINCE); + private boolean isNewUser(@Nullable Version previousVersion, BuiltinUserInfo info) { + return previousVersion != null && previousVersion.before(info.getDefinedSince()); } - private void createLogstashUserAsDisabled(@Nullable Version previousVersion, ActionListener listener) { + private void createUserAsDisabled(BuiltinUserInfo info, @Nullable Version previousVersion, ActionListener listener) { logger.info("Upgrading security from version [{}] - new reserved user [{}] will default to disabled", - previousVersion, LogstashSystemUser.NAME); + previousVersion, info.getName()); // Only clear the cache is authentication is allowed by the current license // otherwise the license management checks will prevent it from completing successfully. final boolean clearCache = licenseState.isAuthAllowed(); - client.prepareGet(SECURITY_INDEX_NAME, NativeUsersStore.RESERVED_USER_DOC_TYPE, LogstashSystemUser.NAME).execute( - ActionListener.wrap(getResponse -> { - if (getResponse.isExists()) { - // the document exists - we shouldn't do anything - listener.onResponse(null); - } else { - client.prepareIndex(SECURITY_INDEX_NAME, NativeUsersStore.RESERVED_USER_DOC_TYPE, LogstashSystemUser.NAME) - .setSource(Requests.INDEX_CONTENT_TYPE, User.Fields.ENABLED.getPreferredName(), false, - User.Fields.PASSWORD.getPreferredName(), "") - .setCreate(true) - .execute(ActionListener.wrap(r -> { - if (clearCache) { - new SecurityClient(client).prepareClearRealmCache() - .usernames(LogstashSystemUser.NAME) - .execute(ActionListener.wrap(re -> listener.onResponse(null), listener::onFailure)); - } else { - listener.onResponse(null); - } - }, listener::onFailure)); - } - }, listener::onFailure)); + final String userName = info.getName(); + client.prepareGet(SECURITY_INDEX_NAME, NativeUsersStore.RESERVED_USER_DOC_TYPE, userName).execute( + ActionListener.wrap(getResponse -> { + if (getResponse.isExists()) { + // the document exists - we shouldn't do anything + listener.onResponse(null); + } else { + client.prepareIndex(SECURITY_INDEX_NAME, NativeUsersStore.RESERVED_USER_DOC_TYPE, userName) + .setSource(Requests.INDEX_CONTENT_TYPE, User.Fields.ENABLED.getPreferredName(), false, + User.Fields.PASSWORD.getPreferredName(), "") + .setCreate(true) + .execute(ActionListener.wrap(r -> { + if (clearCache) { + new SecurityClient(client).prepareClearRealmCache() + .usernames(userName) + .execute(ActionListener.wrap(re -> listener.onResponse(null), listener::onFailure)); + } else { + listener.onResponse(null); + } + }, listener::onFailure)); + } + }, listener::onFailure)); } /** diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealm.java b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealm.java index d1428022408..d8632c04a49 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealm.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealm.java @@ -23,6 +23,7 @@ import org.elasticsearch.xpack.security.authc.support.SecuredString; import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken; import org.elasticsearch.xpack.security.support.Exceptions; import org.elasticsearch.xpack.security.user.AnonymousUser; +import org.elasticsearch.xpack.security.user.BeatsSystemUser; import org.elasticsearch.xpack.security.user.ElasticUser; import org.elasticsearch.xpack.security.user.KibanaUser; import org.elasticsearch.xpack.security.user.LogstashSystemUser; @@ -141,6 +142,7 @@ public class ReservedRealm extends CachingUsernamePasswordRealm { case ElasticUser.NAME: case KibanaUser.NAME: case LogstashSystemUser.NAME: + case BeatsSystemUser.NAME: return XPackSettings.RESERVED_REALM_ENABLED_SETTING.get(settings); default: return AnonymousUser.isAnonymousUsername(username, settings); @@ -156,6 +158,8 @@ public class ReservedRealm extends CachingUsernamePasswordRealm { return new KibanaUser(userInfo.enabled); case LogstashSystemUser.NAME: return new LogstashSystemUser(userInfo.enabled); + case BeatsSystemUser.NAME: + return new BeatsSystemUser(userInfo.enabled); default: if (anonymousEnabled && anonymousUser.principal().equals(username)) { return anonymousUser; @@ -181,6 +185,9 @@ public class ReservedRealm extends CachingUsernamePasswordRealm { userInfo = reservedUserInfos.get(LogstashSystemUser.NAME); users.add(new LogstashSystemUser(userInfo == null || userInfo.enabled)); + userInfo = reservedUserInfos.get(BeatsSystemUser.NAME); + users.add(new BeatsSystemUser(userInfo == null || userInfo.enabled)); + if (anonymousEnabled) { users.add(anonymousUser); } @@ -223,6 +230,8 @@ public class ReservedRealm extends CachingUsernamePasswordRealm { switch (username) { case LogstashSystemUser.NAME: return LogstashSystemUser.DEFINED_SINCE; + case BeatsSystemUser.NAME: + return BeatsSystemUser.DEFINED_SINCE; default: return Version.V_5_0_0; } diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/authz/store/ReservedRolesStore.java b/plugin/src/main/java/org/elasticsearch/xpack/security/authz/store/ReservedRolesStore.java index 62920e32fa4..bc9a546902e 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/security/authz/store/ReservedRolesStore.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/authz/store/ReservedRolesStore.java @@ -60,6 +60,8 @@ public class ReservedRolesStore { null, MetadataUtils.DEFAULT_RESERVED_METADATA)) .put("logstash_system", new RoleDescriptor("logstash_system", new String[] { "monitor", MonitoringBulkAction.NAME}, null, null, MetadataUtils.DEFAULT_RESERVED_METADATA)) + .put("beats_system", new RoleDescriptor("beats_system", new String[] { "monitor", MonitoringBulkAction.NAME}, + null, null, MetadataUtils.DEFAULT_RESERVED_METADATA)) .immutableMap(); } diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/user/BeatsSystemUser.java b/plugin/src/main/java/org/elasticsearch/xpack/security/user/BeatsSystemUser.java new file mode 100644 index 00000000000..6e9cef9f832 --- /dev/null +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/user/BeatsSystemUser.java @@ -0,0 +1,20 @@ +/* + * 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.security.user; + +import org.elasticsearch.Version; +import org.elasticsearch.xpack.security.support.MetadataUtils; + +public class BeatsSystemUser extends User { + public static final String NAME = "beats_system"; + private static final String ROLE_NAME = "beats_system"; + public static final Version DEFINED_SINCE = Version.V_6_0_0_alpha1_UNRELEASED; + public static final BuiltinUserInfo USER_INFO = new BuiltinUserInfo(NAME, ROLE_NAME, DEFINED_SINCE); + + public BeatsSystemUser(boolean enabled) { + super(NAME, new String[]{ ROLE_NAME }, null, null, MetadataUtils.DEFAULT_RESERVED_METADATA, enabled); + } +} diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/user/BuiltinUserInfo.java b/plugin/src/main/java/org/elasticsearch/xpack/security/user/BuiltinUserInfo.java new file mode 100644 index 00000000000..b54a7360e09 --- /dev/null +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/user/BuiltinUserInfo.java @@ -0,0 +1,38 @@ +/* + * 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.security.user; + +import org.elasticsearch.Version; + +/** + * BuiltinUserInfo provides common user meta data for newly introduced pre defined System Users. + */ +public class BuiltinUserInfo { + private final String name; + private final String role; + private final Version definedSince; + + public BuiltinUserInfo(String name, String role, Version definedSince) { + this.name = name; + this.role = role; + this.definedSince = definedSince; + } + + /** Get the builtin users name. */ + public String getName() { + return name; + } + + /** Get the builtin users default role name. */ + public String getRole() { + return role; + } + + /** Get version the builtin user was introduced with. */ + public Version getDefinedSince() { + return definedSince; + } +} diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/user/LogstashSystemUser.java b/plugin/src/main/java/org/elasticsearch/xpack/security/user/LogstashSystemUser.java index 8b0fb06b68f..039a74a61dc 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/security/user/LogstashSystemUser.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/user/LogstashSystemUser.java @@ -16,6 +16,7 @@ public class LogstashSystemUser extends User { public static final String NAME = "logstash_system"; private static final String ROLE_NAME = "logstash_system"; public static final Version DEFINED_SINCE = Version.V_5_2_0_UNRELEASED; + public static final BuiltinUserInfo USER_INFO = new BuiltinUserInfo(NAME, ROLE_NAME, DEFINED_SINCE); public LogstashSystemUser(boolean enabled) { super(NAME, new String[]{ ROLE_NAME }, null, null, MetadataUtils.DEFAULT_RESERVED_METADATA, enabled); diff --git a/plugin/src/main/resources/monitoring-beats.json b/plugin/src/main/resources/monitoring-beats.json new file mode 100644 index 00000000000..a9a63b7f8d2 --- /dev/null +++ b/plugin/src/main/resources/monitoring-beats.json @@ -0,0 +1,88 @@ +{ + "template": ".monitoring-beats-${monitoring.template.version}-*", + "settings": { + "index.number_of_shards": 1, + "index.number_of_replicas": 1, + "index.codec": "best_compression" + }, + "mappings": { + "beats_stats": { + "properties": { + "cluster_uuid": { + "type": "keyword" + }, + "timestamp": { + "type": "date", + "format": "date_time" + }, + "source_node": { + "properties": { + "uuid": { + "type": "keyword" + }, + "host": { + "type": "keyword" + }, + "transport_address": { + "type": "keyword" + }, + "ip": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "attributes": { + "dynamic": true, + "properties": { + "data": { + "type": "boolean" + }, + "master": { + "type": "boolean" + }, + "client": { + "type": "boolean" + } + } + } + } + }, + "beats_stats": { + "properties": { + "timestamp": { + "type": "date", + "format": "date_time" + }, + "tags": { + "type": "keyword" + }, + "beat": { + "properties": { + "uuid": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "version": { + "type": "keyword" + }, + "host": { + "type": "keyword" + }, + "name": { + "type": "keyword" + } + } + }, + "metrics": { + "properties": { + } + } + } + } + } + } + } +} diff --git a/plugin/src/main/resources/monitoring-data.json b/plugin/src/main/resources/monitoring-data.json index 84f1ebcea81..413e5cd8a83 100644 --- a/plugin/src/main/resources/monitoring-data.json +++ b/plugin/src/main/resources/monitoring-data.json @@ -23,6 +23,9 @@ }, "logstash": { "enabled": false + }, + "beats": { + "enabled": false } } } diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterResourceTests.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterResourceTests.java index a57b3e61cbe..9e40c861a31 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterResourceTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterResourceTests.java @@ -43,7 +43,7 @@ public class HttpExporterResourceTests extends AbstractPublishableHttpResourceTe * kibana, logstash, beats */ private final int EXPECTED_TYPES = MonitoringTemplateUtils.NEW_DATA_TYPES.length; - private final int EXPECTED_TEMPLATES = 4; + private final int EXPECTED_TEMPLATES = 5; private final RestClient client = mock(RestClient.class); private final Response versionResponse = mock(Response.class); diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterTests.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterTests.java index 39b1b17e3e5..1d1032c158a 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterTests.java @@ -307,7 +307,7 @@ public class HttpExporterTests extends ESTestCase { equalTo(version + typeMappings.size() + templates.size() + pipelines.size() + bwc.size())); assertThat(version, equalTo(1)); assertThat(typeMappings, hasSize(MonitoringTemplateUtils.NEW_DATA_TYPES.length)); - assertThat(templates, hasSize(4)); + assertThat(templates, hasSize(5)); assertThat(pipelines, hasSize(useIngest ? 1 : 0)); assertThat(bwc, hasSize(1)); diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmMigratorTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmMigratorTests.java index 789ead4c976..6591857bc5e 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmMigratorTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmMigratorTests.java @@ -44,6 +44,7 @@ import org.elasticsearch.xpack.security.SecurityLifecycleService; import org.elasticsearch.xpack.security.action.realm.ClearRealmCacheAction; import org.elasticsearch.xpack.security.action.realm.ClearRealmCacheRequest; import org.elasticsearch.xpack.security.authc.support.Hasher; +import org.elasticsearch.xpack.security.user.BeatsSystemUser; import org.elasticsearch.xpack.security.user.ElasticUser; import org.elasticsearch.xpack.security.user.KibanaUser; import org.elasticsearch.xpack.security.user.LogstashSystemUser; @@ -150,14 +151,14 @@ public class NativeRealmMigratorTests extends ESTestCase { } public void testNoChangeOnFreshInstall() throws Exception { - verifyUpgrade(null, false, false); + verifyUpgrade(null, null, false); } public void testNoChangeOnUpgradeAfterV5_3() throws Exception { - verifyUpgrade(randomFrom(Version.V_6_0_0_alpha1_UNRELEASED), false, false); + verifyUpgrade(randomFrom(Version.V_6_0_0_alpha1_UNRELEASED), null, false); } - public void testDisableLogstashAndConvertPasswordsOnUpgradeFromVersionPriorToV5_2() throws Exception { + public void testDisableLogstashBeatsAndConvertPasswordsOnUpgradeFromVersionPriorToV5_2() throws Exception { this.reservedUsers = Collections.singletonMap( KibanaUser.NAME, MapBuilder.newMapBuilder() @@ -165,7 +166,21 @@ public class NativeRealmMigratorTests extends ESTestCase { .put(User.Fields.ENABLED.getPreferredName(), false) .immutableMap() ); - verifyUpgrade(randomFrom(Version.V_5_1_1_UNRELEASED, Version.V_5_0_2, Version.V_5_0_0), true, true); + String[] disabledUsers = new String[]{LogstashSystemUser.NAME, BeatsSystemUser.NAME}; + verifyUpgrade(randomFrom(Version.V_5_1_1_UNRELEASED, Version.V_5_0_2, Version.V_5_0_0), disabledUsers, true); + } + + public void testDisableBeatsAndConvertPasswordsOnUpgradeFromVersionPriorToV6() throws Exception { + this.reservedUsers = Collections.singletonMap( + KibanaUser.NAME, + MapBuilder.newMapBuilder() + .put(User.Fields.PASSWORD.getPreferredName(), new String(Hasher.BCRYPT.hash(ReservedRealm.DEFAULT_PASSWORD_TEXT))) + .put(User.Fields.ENABLED.getPreferredName(), false) + .immutableMap() + ); + String[] disabledUsers = new String[]{BeatsSystemUser.NAME}; + Version version = randomFrom(Version.V_5_3_0_UNRELEASED, Version.V_5_2_1_UNRELEASED); + verifyUpgrade(version, disabledUsers, true); } public void testConvertPasswordsOnUpgradeFromVersion5_2() throws Exception { @@ -177,24 +192,31 @@ public class NativeRealmMigratorTests extends ESTestCase { .put(User.Fields.ENABLED.getPreferredName(), randomBoolean()) .immutableMap() )); - verifyUpgrade(Version.V_5_2_0_UNRELEASED, false, true); + String[] disabledUsers = new String[]{BeatsSystemUser.NAME}; + verifyUpgrade(Version.V_5_2_0_UNRELEASED, disabledUsers, true); } - private void verifyUpgrade(Version fromVersion, boolean disableLogstashUser, boolean convertDefaultPasswords) throws Exception { + private void verifyUpgrade(Version fromVersion, String[] disabledUsers, boolean convertDefaultPasswords) throws Exception { final PlainActionFuture future = doUpgrade(fromVersion); boolean expectedResult = false; - if (disableLogstashUser) { + if (disabledUsers != null) { + final int userCount = disabledUsers.length; final boolean clearCache = licenseState.isAuthAllowed(); ArgumentCaptor captor = ArgumentCaptor.forClass(GetRequest.class); - verify(mockClient).execute(eq(GetAction.INSTANCE), captor.capture(), any(ActionListener.class)); - assertEquals(LogstashSystemUser.NAME, captor.getValue().id()); + verify(mockClient, times(userCount)).execute(eq(GetAction.INSTANCE), captor.capture(), any(ActionListener.class)); + for (int i = 0; i < userCount; i++) { + assertEquals(disabledUsers[i], captor.getAllValues().get(i).id()); + } + ArgumentCaptor indexCaptor = ArgumentCaptor.forClass(IndexRequest.class); - verify(mockClient).execute(eq(IndexAction.INSTANCE), indexCaptor.capture(), any(ActionListener.class)); - assertEquals(LogstashSystemUser.NAME, indexCaptor.getValue().id()); - assertEquals(false, indexCaptor.getValue().sourceAsMap().get(User.Fields.ENABLED.getPreferredName())); + verify(mockClient, times(userCount)).execute(eq(IndexAction.INSTANCE), indexCaptor.capture(), any(ActionListener.class)); + for (int i = 0; i < userCount; i++) { + assertEquals(disabledUsers[i], captor.getAllValues().get(i).id()); + assertEquals(false, indexCaptor.getValue().sourceAsMap().get(User.Fields.ENABLED.getPreferredName())); + } if (clearCache) { - verify(mockClient).execute(eq(ClearRealmCacheAction.INSTANCE), any(ClearRealmCacheRequest.class), + verify(mockClient, times(userCount)).execute(eq(ClearRealmCacheAction.INSTANCE), any(ClearRealmCacheRequest.class), any(ActionListener.class)); } expectedResult = true; diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmTests.java index 961ba4794a7..51927202e12 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmTests.java @@ -18,6 +18,7 @@ import org.elasticsearch.xpack.security.authc.support.Hasher; import org.elasticsearch.xpack.security.authc.support.SecuredString; import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken; import org.elasticsearch.xpack.security.user.AnonymousUser; +import org.elasticsearch.xpack.security.user.BeatsSystemUser; import org.elasticsearch.xpack.security.user.ElasticUser; import org.elasticsearch.xpack.security.user.KibanaUser; import org.elasticsearch.xpack.security.user.LogstashSystemUser; @@ -296,7 +297,8 @@ public class ReservedRealmTests extends ESTestCase { new AnonymousUser(Settings.EMPTY), securityLifecycleService); PlainActionFuture> userFuture = new PlainActionFuture<>(); reservedRealm.users(userFuture); - assertThat(userFuture.actionGet(), containsInAnyOrder(new ElasticUser(true), new KibanaUser(true), new LogstashSystemUser(true))); + assertThat(userFuture.actionGet(), containsInAnyOrder(new ElasticUser(true), new KibanaUser(true), + new LogstashSystemUser(true), new BeatsSystemUser(true))); } public void testGetUsersDisabled() { diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/authz/store/ReservedRolesStoreTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/authz/store/ReservedRolesStoreTests.java index 429795dbda0..2eb70410e5b 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/authz/store/ReservedRolesStoreTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/authz/store/ReservedRolesStoreTests.java @@ -331,7 +331,7 @@ public class ReservedRolesStoreTests extends ESTestCase { assertThat(logstashSystemRole.cluster().check(ClusterRerouteAction.NAME), is(false)); assertThat(logstashSystemRole.cluster().check(ClusterUpdateSettingsAction.NAME), is(false)); assertThat(logstashSystemRole.cluster().check(MonitoringBulkAction.NAME), is(true)); - + assertThat(logstashSystemRole.runAs().check(randomAsciiOfLengthBetween(1, 30)), is(false)); assertThat(logstashSystemRole.indices().allowedIndicesMatcher(IndexAction.NAME).test("foo"), is(false)); @@ -339,4 +339,26 @@ public class ReservedRolesStoreTests extends ESTestCase { assertThat(logstashSystemRole.indices().allowedIndicesMatcher("indices:foo").test(randomAsciiOfLengthBetween(8, 24)), is(false)); } + + public void testBeatsSystemRole() { + RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("beats_system"); + assertNotNull(roleDescriptor); + assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); + + Role beatsSystemRole = Role.builder(roleDescriptor, null).build(); + assertThat(beatsSystemRole.cluster().check(ClusterHealthAction.NAME), is(true)); + assertThat(beatsSystemRole.cluster().check(ClusterStateAction.NAME), is(true)); + assertThat(beatsSystemRole.cluster().check(ClusterStatsAction.NAME), is(true)); + assertThat(beatsSystemRole.cluster().check(PutIndexTemplateAction.NAME), is(false)); + assertThat(beatsSystemRole.cluster().check(ClusterRerouteAction.NAME), is(false)); + assertThat(beatsSystemRole.cluster().check(ClusterUpdateSettingsAction.NAME), is(false)); + assertThat(beatsSystemRole.cluster().check(MonitoringBulkAction.NAME), is(true)); + + assertThat(beatsSystemRole.runAs().check(randomAsciiOfLengthBetween(1, 30)), is(false)); + + assertThat(beatsSystemRole.indices().allowedIndicesMatcher(IndexAction.NAME).test("foo"), is(false)); + assertThat(beatsSystemRole.indices().allowedIndicesMatcher(IndexAction.NAME).test(".reporting"), is(false)); + assertThat(beatsSystemRole.indices().allowedIndicesMatcher("indices:foo").test(randomAsciiOfLengthBetween(8, 24)), + is(false)); + } }