diff --git a/x-pack/build.gradle b/x-pack/build.gradle index 88e09d82168f7..d6487f4a5cf02 100644 --- a/x-pack/build.gradle +++ b/x-pack/build.gradle @@ -50,6 +50,7 @@ subprojects { ext.projectSubstitutions += [ "org.elasticsearch.plugin:x-pack-deprecation:${version}": xpackModule('deprecation')] ext.projectSubstitutions += [ "org.elasticsearch.plugin:x-pack-graph:${version}": xpackModule('graph')] ext.projectSubstitutions += [ "org.elasticsearch.plugin:x-pack-logstash:${version}": xpackModule('logstash')] + ext.projectSubstitutions += [ "org.elasticsearch.plugin:x-pack-beats:${version}": xpackModule('beats')] ext.projectSubstitutions += [ "org.elasticsearch.plugin:x-pack-ml:${version}": xpackModule('ml')] ext.projectSubstitutions += [ "org.elasticsearch.plugin:x-pack-monitoring:${version}": xpackModule('monitoring')] ext.projectSubstitutions += [ "org.elasticsearch.plugin:x-pack-security:${version}": xpackModule('security')] diff --git a/x-pack/plugin/beats/build.gradle b/x-pack/plugin/beats/build.gradle new file mode 100644 index 0000000000000..22bf83807af5e --- /dev/null +++ b/x-pack/plugin/beats/build.gradle @@ -0,0 +1,22 @@ +evaluationDependsOn(xpackModule('core')) + +apply plugin: 'elasticsearch.esplugin' +esplugin { + name 'x-pack-beats' + description 'Elasticsearch Expanded Pack Plugin - Beats' + classname 'org.elasticsearch.xpack.beats.Beats' + extendedPlugins = ['x-pack-core'] +} +archivesBaseName = 'x-pack-beats' + +dependencies { + compileOnly "org.elasticsearch.plugin:x-pack-core:${version}" + testCompile project(path: xpackModule('core'), configuration: 'testArtifacts') + +} + +run { + plugin xpackModule('core') +} + +integTest.enabled = false diff --git a/x-pack/plugin/beats/src/main/java/org/elasticsearch/xpack/beats/Beats.java b/x-pack/plugin/beats/src/main/java/org/elasticsearch/xpack/beats/Beats.java new file mode 100644 index 0000000000000..ae9738073d195 --- /dev/null +++ b/x-pack/plugin/beats/src/main/java/org/elasticsearch/xpack/beats/Beats.java @@ -0,0 +1,69 @@ +/* + * 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.beats; + +import org.elasticsearch.Version; +import org.elasticsearch.cluster.metadata.IndexTemplateMetaData; +import org.elasticsearch.common.inject.Module; +import org.elasticsearch.common.logging.Loggers; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.plugins.ActionPlugin; +import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.xpack.core.XPackPlugin; +import org.elasticsearch.xpack.core.XPackSettings; +import org.elasticsearch.xpack.core.template.TemplateUtils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.function.UnaryOperator; +import java.util.regex.Pattern; + +/** + * This class activates/deactivates the beats modules depending if we're running a node client or transport client + */ +public class Beats extends Plugin implements ActionPlugin { + + private static final String BEATS_AGENTS_TEMPLATE_NAME = "beats-agents-template"; + private static final String BEATS_ADMIN_TEMPLATE_NAME = "beats-admin-template"; + private static final String TEMPLATE_VERSION_PATTERN = + Pattern.quote("${beats.template.version}"); + + private final boolean enabled; + private final boolean transportClientMode; + + public Beats(Settings settings) { + this.enabled = XPackSettings.BEATS_ENABLED.get(settings); + this.transportClientMode = XPackPlugin.transportClientMode(settings); + } + + boolean isEnabled() { + return enabled; + } + + boolean isTransportClient() { + return transportClientMode; + } + + public Collection createGuiceModules() { + List modules = new ArrayList<>(); + modules.add(b -> { + XPackPlugin.bindFeatureSet(b, BeatsFeatureSet.class); + }); + return modules; + } + + public UnaryOperator> getIndexTemplateMetaDataUpgrader() { + return templates -> { + TemplateUtils.loadTemplateIntoMap("/" + BEATS_AGENTS_TEMPLATE_NAME + ".json", templates, BEATS_AGENTS_TEMPLATE_NAME, + Version.CURRENT.toString(), TEMPLATE_VERSION_PATTERN, Loggers.getLogger(Beats.class)); + TemplateUtils.loadTemplateIntoMap("/" + BEATS_ADMIN_TEMPLATE_NAME + ".json", templates, BEATS_ADMIN_TEMPLATE_NAME, + Version.CURRENT.toString(), TEMPLATE_VERSION_PATTERN, Loggers.getLogger(Beats.class)); + return templates; + }; + } +} diff --git a/x-pack/plugin/beats/src/main/java/org/elasticsearch/xpack/beats/BeatsFeatureSet.java b/x-pack/plugin/beats/src/main/java/org/elasticsearch/xpack/beats/BeatsFeatureSet.java new file mode 100644 index 0000000000000..26d18c01074d4 --- /dev/null +++ b/x-pack/plugin/beats/src/main/java/org/elasticsearch/xpack/beats/BeatsFeatureSet.java @@ -0,0 +1,66 @@ +/* + * 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.beats; + +import org.elasticsearch.action.ActionListener; +import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.license.XPackLicenseState; +import org.elasticsearch.xpack.core.XPackFeatureSet; +import org.elasticsearch.xpack.core.XPackField; +import org.elasticsearch.xpack.core.XPackSettings; +import org.elasticsearch.xpack.core.beats.BeatsFeatureSetUsage; + + +import java.io.IOException; +import java.util.Map; + +public class BeatsFeatureSet implements XPackFeatureSet { + + private final boolean enabled; + private final XPackLicenseState licenseState; + + @Inject + public BeatsFeatureSet(Settings settings, @Nullable XPackLicenseState licenseState) { + this.enabled = XPackSettings.BEATS_ENABLED.get(settings); + this.licenseState = licenseState; + } + + @Override + public String name() { + return XPackField.BEATS; + } + + @Override + public String description() { + return "Beats management component for X-Pack"; + } + + @Override + public boolean available() { + return licenseState != null && licenseState.isBeatsAllowed(); + } + + @Override + public boolean enabled() { + return enabled; + } + + @Override + public Map nativeCodeInfo() { + return null; + } + + @Override + public void usage(ActionListener listener) { + listener.onResponse(new BeatsFeatureSetUsage(available(), enabled())); + } + +} diff --git a/x-pack/plugin/beats/src/main/plugin-metadata/plugin-security.policy b/x-pack/plugin/beats/src/main/plugin-metadata/plugin-security.policy new file mode 100644 index 0000000000000..c54f07cf5cd8d --- /dev/null +++ b/x-pack/plugin/beats/src/main/plugin-metadata/plugin-security.policy @@ -0,0 +1,25 @@ +grant { + // needed for multiple server implementations used in tests + permission java.net.SocketPermission "*", "accept,connect"; +}; + +grant codeBase "${codebase.netty-common}" { + // for reading the system-wide configuration for the backlog of established sockets + permission java.io.FilePermission "/proc/sys/net/core/somaxconn", "read"; +}; + +grant codeBase "${codebase.netty-transport}" { + // Netty NioEventLoop wants to change this, because of https://bugs.openjdk.java.net/browse/JDK-6427854 + // the bug says it only happened rarely, and that its fixed, but apparently it still happens rarely! + permission java.util.PropertyPermission "sun.nio.ch.bugLevel", "write"; +}; + +grant codeBase "${codebase.elasticsearch-rest-client}" { + // rest client uses system properties which gets the default proxy + permission java.net.NetPermission "getProxySelector"; +}; + +grant codeBase "${codebase.httpasyncclient}" { + // rest client uses system properties which gets the default proxy + permission java.net.NetPermission "getProxySelector"; +}; diff --git a/x-pack/plugin/beats/src/test/java/org/elasticsearch/xpack/beats/BeatsFeatureSetTests.java b/x-pack/plugin/beats/src/test/java/org/elasticsearch/xpack/beats/BeatsFeatureSetTests.java new file mode 100644 index 0000000000000..1fc39a4325df5 --- /dev/null +++ b/x-pack/plugin/beats/src/test/java/org/elasticsearch/xpack/beats/BeatsFeatureSetTests.java @@ -0,0 +1,64 @@ +/* + * 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.beats; + +import org.elasticsearch.action.support.PlainActionFuture; +import org.elasticsearch.common.io.stream.BytesStreamOutput; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.license.XPackLicenseState; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.core.XPackFeatureSet; +import org.elasticsearch.xpack.core.beats.BeatsFeatureSetUsage; + +import static org.mockito.Mockito.mock; +import static org.hamcrest.core.Is.is; +import static org.mockito.Mockito.when; + +public class BeatsFeatureSetTests extends ESTestCase { + + public void testEnabledSetting() throws Exception { + boolean enabled = randomBoolean(); + Settings settings = Settings.builder() + .put("path.home", createTempDir()) + .put("xpack.beats.enabled", enabled) + .build(); + BeatsFeatureSet featureSet = new BeatsFeatureSet(settings, null); + assertThat(featureSet.enabled(), is(enabled)); + + PlainActionFuture future = new PlainActionFuture<>(); + featureSet.usage(future); + XPackFeatureSet.Usage usage = future.get(); + + BytesStreamOutput out = new BytesStreamOutput(); + usage.writeTo(out); + XPackFeatureSet.Usage serializedUsage = new BeatsFeatureSetUsage(out.bytes().streamInput()); + assertThat(serializedUsage.enabled(), is(enabled)); + } + + public void testEnabledDefault() throws Exception { + Settings settings = Settings.builder().put("path.home", createTempDir()).build(); + BeatsFeatureSet featureSet = new BeatsFeatureSet(settings, null); + assertThat(featureSet.enabled(), is(true)); + } + + public void testAvailable() throws Exception { + final XPackLicenseState licenseState = mock(XPackLicenseState.class); + BeatsFeatureSet featureSet = new BeatsFeatureSet(Settings.EMPTY, licenseState); + boolean available = randomBoolean(); + when(licenseState.isBeatsAllowed()).thenReturn(available); + assertThat(featureSet.available(), is(available)); + + PlainActionFuture future = new PlainActionFuture<>(); + featureSet.usage(future); + XPackFeatureSet.Usage usage = future.get(); + assertThat(usage.available(), is(available)); + + BytesStreamOutput out = new BytesStreamOutput(); + usage.writeTo(out); + XPackFeatureSet.Usage serializedUsage = new BeatsFeatureSetUsage(out.bytes().streamInput()); + assertThat(serializedUsage.available(), is(available)); + } +} diff --git a/x-pack/plugin/build.gradle b/x-pack/plugin/build.gradle index e4dc314eb72a7..3f1f6a46a44c4 100644 --- a/x-pack/plugin/build.gradle +++ b/x-pack/plugin/build.gradle @@ -15,7 +15,7 @@ archivesBaseName = 'x-pack' es_meta_plugin { name = 'x-pack' description = 'Elasticsearch Expanded Pack Plugin' - plugins = ['core', 'deprecation', 'graph', 'logstash', + plugins = ['core', 'deprecation', 'graph', 'logstash', 'beats', 'ml', 'monitoring', 'security', 'upgrade', 'watcher', 'sql', 'rollup'] } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/XPackLicenseState.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/XPackLicenseState.java index 2e4caff1a725d..72c0a47b5f803 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/XPackLicenseState.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/XPackLicenseState.java @@ -52,6 +52,9 @@ public class XPackLicenseState { messages.put(XPackField.LOGSTASH, new String[] { "Logstash will continue to poll centrally-managed pipelines" }); + messages.put(XPackField.BEATS, new String[] { + "Beats will continue to poll centrally-managed configuration" + }); messages.put(XPackField.DEPRECATION, new String[] { "Deprecation APIs are disabled" }); @@ -81,6 +84,7 @@ public class XPackLicenseState { messages.put(XPackField.GRAPH, XPackLicenseState::graphAcknowledgementMessages); messages.put(XPackField.MACHINE_LEARNING, XPackLicenseState::machineLearningAcknowledgementMessages); messages.put(XPackField.LOGSTASH, XPackLicenseState::logstashAcknowledgementMessages); + messages.put(XPackField.BEATS, XPackLicenseState::beatsAcknowledgementMessages); messages.put(XPackField.SQL, XPackLicenseState::sqlAcknowledgementMessages); ACKNOWLEDGMENT_MESSAGES = Collections.unmodifiableMap(messages); } @@ -217,6 +221,21 @@ private static String[] logstashAcknowledgementMessages(OperationMode currentMod return Strings.EMPTY_ARRAY; } + private static String[] beatsAcknowledgementMessages(OperationMode currentMode, OperationMode newMode) { + switch (newMode) { + case BASIC: + switch (currentMode) { + case TRIAL: + case STANDARD: + case GOLD: + case PLATINUM: + return new String[] { "Logstash will no longer poll for centrally-managed configuration" }; + } + break; + } + return Strings.EMPTY_ARRAY; + } + private static String[] sqlAcknowledgementMessages(OperationMode currentMode, OperationMode newMode) { switch (newMode) { case BASIC: @@ -512,6 +531,28 @@ public boolean isLogstashAllowed() { } } + /** + * Beats is allowed as long as there is an active license of type TRIAL, STANDARD, GOLD or PLATINUM + * @return {@code true} as long as there is a valid license + */ + public boolean isBeatsAllowed() { + Status localStatus = status; + + if (localStatus.active == false) { + return false; + } + + switch (localStatus.mode) { + case TRIAL: + case GOLD: + case PLATINUM: + case STANDARD: + return true; + default: + return false; + } + } + /** * Deprecation APIs are always allowed as long as there is an active license * @return {@code true} as long as there is a valid license diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackClientPlugin.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackClientPlugin.java index 4853588bd3ead..5c7bac909ca7d 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackClientPlugin.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackClientPlugin.java @@ -39,6 +39,7 @@ import org.elasticsearch.xpack.core.graph.GraphFeatureSetUsage; import org.elasticsearch.xpack.core.graph.action.GraphExploreAction; import org.elasticsearch.xpack.core.logstash.LogstashFeatureSetUsage; +import org.elasticsearch.xpack.core.beats.BeatsFeatureSetUsage; import org.elasticsearch.xpack.core.ml.MachineLearningFeatureSetUsage; import org.elasticsearch.xpack.core.ml.MlMetadata; import org.elasticsearch.xpack.core.ml.action.CloseJobAction; @@ -319,6 +320,8 @@ public List getNamedWriteables() { new NamedWriteableRegistry.Entry(XPackFeatureSet.Usage.class, XPackField.GRAPH, GraphFeatureSetUsage::new), // logstash new NamedWriteableRegistry.Entry(XPackFeatureSet.Usage.class, XPackField.LOGSTASH, LogstashFeatureSetUsage::new), + // beats + new NamedWriteableRegistry.Entry(XPackFeatureSet.Usage.class, XPackField.BEATS, BeatsFeatureSetUsage::new), // ML - Custom metadata new NamedWriteableRegistry.Entry(MetaData.Custom.class, "ml", MlMetadata::new), new NamedWriteableRegistry.Entry(NamedDiff.class, "ml", MlMetadata.MlMetadataDiff::new), diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackField.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackField.java index dd482c4e22d78..70eb047c8edef 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackField.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackField.java @@ -19,6 +19,8 @@ public final class XPackField { public static final String MACHINE_LEARNING = "ml"; /** Name constant for the Logstash feature. */ public static final String LOGSTASH = "logstash"; + /** Name constant for the Beats feature. */ + public static final String BEATS = "beats"; /** Name constant for the Deprecation API feature. */ public static final String DEPRECATION = "deprecation"; /** Name constant for the upgrade feature. */ diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackSettings.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackSettings.java index aa7b2b216b229..8d8a4cc514c66 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackSettings.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackSettings.java @@ -60,6 +60,10 @@ public class XPackSettings { public static final Setting LOGSTASH_ENABLED = Setting.boolSetting("xpack.logstash.enabled", true, Setting.Property.NodeScope); + /** Setting for enabling or disabling Beats extensions. Defaults to true. */ + public static final Setting BEATS_ENABLED = Setting.boolSetting("xpack.beats.enabled", true, + Setting.Property.NodeScope); + /** Setting for enabling or disabling TLS. Defaults to false. */ public static final Setting TRANSPORT_SSL_ENABLED = Setting.boolSetting("xpack.security.transport.ssl.enabled", false, Property.NodeScope); diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/beats/BeatsFeatureSetUsage.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/beats/BeatsFeatureSetUsage.java new file mode 100644 index 0000000000000..94bb19ba51c8d --- /dev/null +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/beats/BeatsFeatureSetUsage.java @@ -0,0 +1,24 @@ +/* + * 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.beats; + +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.xpack.core.XPackFeatureSet; +import org.elasticsearch.xpack.core.XPackField; + +import java.io.IOException; + +public class BeatsFeatureSetUsage extends XPackFeatureSet.Usage { + + public BeatsFeatureSetUsage(StreamInput in) throws IOException { + super(in); + } + + public BeatsFeatureSetUsage(boolean available, boolean enabled) { + super(XPackField.BEATS, available, enabled); + } + +} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStore.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStore.java index 059c4dfbb6547..8b69808471f3c 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStore.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStore.java @@ -85,6 +85,18 @@ private static Map initializeReservedRoles() { 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_agent", new RoleDescriptor("beats_agent", + null, + new RoleDescriptor.IndicesPrivileges[] { + RoleDescriptor.IndicesPrivileges.builder().indices(".management-beats-agents").privileges("create_index", "index", "read").build() + }, + null, MetadataUtils.DEFAULT_RESERVED_METADATA)) + .put("beats_admin", new RoleDescriptor("beats_admin", + null, + new RoleDescriptor.IndicesPrivileges[] { + RoleDescriptor.IndicesPrivileges.builder().indices(".management-beats-*").privileges("all").build() + }, + null, MetadataUtils.DEFAULT_RESERVED_METADATA)) .put(UsernamesField.BEATS_ROLE, new RoleDescriptor(UsernamesField.BEATS_ROLE, new String[] { "monitor", MonitoringBulkAction.NAME}, null, null, MetadataUtils.DEFAULT_RESERVED_METADATA)) .put("machine_learning_user", new RoleDescriptor("machine_learning_user", new String[] { "monitor_ml" }, diff --git a/x-pack/plugin/core/src/main/resources/beats-admin-template.json b/x-pack/plugin/core/src/main/resources/beats-admin-template.json new file mode 100644 index 0000000000000..b0819953b75d3 --- /dev/null +++ b/x-pack/plugin/core/src/main/resources/beats-admin-template.json @@ -0,0 +1,42 @@ +{ + "index_patterns": [ + ".management-beats-admin" + ], + "settings": { + "index": { + "number_of_shards": 1, + "auto_expand_replicas": "0-1", + "codec": "best_compression" + } + }, + "mappings": { + "_doc": { + "_meta": { + "beats-version": "${beats.template.version}" + }, + "dynamic": "strict", + "properties": { + "type": { + "type": "keyword" + }, + "enrollment_token": { + "properties": { + "token": { + "type": "keyword" + } + } + }, + "configuration_fragment": { + "properties": { + "tag": { + "type": "keyword" + }, + "fragment_yml": { + "type": "text" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/x-pack/plugin/core/src/main/resources/beats-agents-template.json b/x-pack/plugin/core/src/main/resources/beats-agents-template.json new file mode 100644 index 0000000000000..a47ad9743769e --- /dev/null +++ b/x-pack/plugin/core/src/main/resources/beats-agents-template.json @@ -0,0 +1,54 @@ +{ + "index_patterns": [ + ".management-beats-agents" + ], + "settings": { + "index": { + "number_of_shards": 1, + "auto_expand_replicas": "0-1", + "codec": "best_compression" + } + }, + "mappings": { + "_doc": { + "_meta": { + "beats-version": "${beats.template.version}" + }, + "dynamic": "strict", + "properties": { + "beat": { + "properties": { + "id": { + "type": "keyword" + }, + "enrollment_token": { + "type": "keyword" + }, + "access_token": { + "type": "keyword" + }, + "verified_on": { + "type": "date" + }, + "type": { + "type": "keyword" + }, + "ephemeral_id": { + "type": "keyword" + }, + "local_configuration_yml": { + "type": "text" + }, + "central_configuration_yml": { + "type": "text" + }, + "metadata": { + "dynamic": "true", + "type": "object" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStoreTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStoreTests.java index b25f3f374b389..4352f202c5e3b 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStoreTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStoreTests.java @@ -478,6 +478,73 @@ public void testLogstashSystemRole() { is(false)); } + public void testBeatsAgentRole() { + RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("beats_agent"); + assertNotNull(roleDescriptor); + assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); + + Role beatsAgentRole = Role.builder(roleDescriptor, null).build(); + assertThat(beatsAgentRole.cluster().check(ClusterHealthAction.NAME), is(false)); + assertThat(beatsAgentRole.cluster().check(ClusterStateAction.NAME), is(false)); + assertThat(beatsAgentRole.cluster().check(ClusterStatsAction.NAME), is(false)); + assertThat(beatsAgentRole.cluster().check(PutIndexTemplateAction.NAME), is(false)); + assertThat(beatsAgentRole.cluster().check(ClusterRerouteAction.NAME), is(false)); + assertThat(beatsAgentRole.cluster().check(ClusterUpdateSettingsAction.NAME), is(false)); + assertThat(beatsAgentRole.cluster().check(MonitoringBulkAction.NAME), is(false)); + + assertThat(beatsAgentRole.runAs().check(randomAlphaOfLengthBetween(1, 30)), is(false)); + + assertThat(beatsAgentRole.indices().allowedIndicesMatcher("indices:foo").test(randomAlphaOfLengthBetween(8, 24)), + is(false)); + + String index = ".management-beats-agents"; + assertThat(beatsAgentRole.indices().allowedIndicesMatcher("indices:foo").test(index), is(true)); + assertThat(beatsAgentRole.indices().allowedIndicesMatcher("indices:bar").test(index), is(true)); + assertThat(beatsAgentRole.indices().allowedIndicesMatcher(DeleteIndexAction.NAME).test(index), is(false)); + assertThat(beatsAgentRole.indices().allowedIndicesMatcher(CreateIndexAction.NAME).test(index), is(true)); + assertThat(beatsAgentRole.indices().allowedIndicesMatcher(IndexAction.NAME).test(index), is(true)); + assertThat(beatsAgentRole.indices().allowedIndicesMatcher(DeleteAction.NAME).test(index), is(false)); + assertThat(beatsAgentRole.indices().allowedIndicesMatcher(UpdateSettingsAction.NAME).test(index), is(true)); + assertThat(beatsAgentRole.indices().allowedIndicesMatcher(SearchAction.NAME).test(index), is(true)); + assertThat(beatsAgentRole.indices().allowedIndicesMatcher(MultiSearchAction.NAME).test(index), is(true)); + assertThat(beatsAgentRole.indices().allowedIndicesMatcher(GetAction.NAME).test(index), is(true)); + } + + public void testBeatsAdminRole() { + RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("beats_admin"); + assertNotNull(roleDescriptor); + assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); + + Role beatsAdminRole = Role.builder(roleDescriptor, null).build(); + assertThat(beatsAdminRole.cluster().check(ClusterHealthAction.NAME), is(false)); + assertThat(beatsAdminRole.cluster().check(ClusterStateAction.NAME), is(false)); + assertThat(beatsAdminRole.cluster().check(ClusterStatsAction.NAME), is(false)); + assertThat(beatsAdminRole.cluster().check(PutIndexTemplateAction.NAME), is(false)); + assertThat(beatsAdminRole.cluster().check(ClusterRerouteAction.NAME), is(false)); + assertThat(beatsAdminRole.cluster().check(ClusterUpdateSettingsAction.NAME), is(false)); + assertThat(beatsAdminRole.cluster().check(MonitoringBulkAction.NAME), is(false)); + + assertThat(beatsAdminRole.runAs().check(randomAlphaOfLengthBetween(1, 30)), is(false)); + + assertThat(beatsAdminRole.indices().allowedIndicesMatcher("indices:foo").test(randomAlphaOfLengthBetween(8, 24)), + is(false)); + + String index = ".management-beats-*"; + Arrays.asList(".management-beats-admin", ".management-beats-agents").forEach((index) -> { + logger.info("index name [{}]", index); + assertThat(beatsAdminRole.indices().allowedIndicesMatcher("indices:foo").test(index), is(true)); + assertThat(beatsAdminRole.indices().allowedIndicesMatcher("indices:bar").test(index), is(true)); + assertThat(beatsAdminRole.indices().allowedIndicesMatcher(DeleteIndexAction.NAME).test(index), is(true)); + assertThat(beatsAdminRole.indices().allowedIndicesMatcher(CreateIndexAction.NAME).test(index), is(true)); + assertThat(beatsAdminRole.indices().allowedIndicesMatcher(IndexAction.NAME).test(index), is(true)); + assertThat(beatsAdminRole.indices().allowedIndicesMatcher(DeleteAction.NAME).test(index), is(true)); + assertThat(beatsAdminRole.indices().allowedIndicesMatcher(UpdateSettingsAction.NAME).test(index), is(true)); + assertThat(beatsAdminRole.indices().allowedIndicesMatcher(SearchAction.NAME).test(index), is(true)); + assertThat(beatsAdminRole.indices().allowedIndicesMatcher(MultiSearchAction.NAME).test(index), is(true)); + assertThat(beatsAdminRole.indices().allowedIndicesMatcher(GetAction.NAME).test(index), is(true)); + } + } + public void testBeatsSystemRole() { RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor(BeatsSystemUser.ROLE_NAME); assertNotNull(roleDescriptor);