diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ClusterPrivilegeResolver.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ClusterPrivilegeResolver.java index 51833b65776f6..df80d2823b129 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ClusterPrivilegeResolver.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ClusterPrivilegeResolver.java @@ -15,6 +15,9 @@ import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsAction; import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusAction; import org.elasticsearch.action.admin.cluster.state.ClusterStateAction; +import org.elasticsearch.action.admin.indices.template.get.GetComponentTemplateAction; +import org.elasticsearch.action.admin.indices.template.get.GetComposableIndexTemplateAction; +import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesAction; import org.elasticsearch.action.ingest.GetPipelineAction; import org.elasticsearch.action.ingest.SimulatePipelineAction; import org.elasticsearch.common.Strings; @@ -69,7 +72,12 @@ public class ClusterPrivilegeResolver { private static final Set MANAGE_SERVICE_ACCOUNT_PATTERN = Collections.singleton( "cluster:admin/xpack/security/service_account/*" ); - private static final Set MONITOR_PATTERN = Collections.singleton("cluster:monitor/*"); + private static final Set MONITOR_PATTERN = Sets.newHashSet( + "cluster:monitor/*", + GetIndexTemplatesAction.NAME, + GetComponentTemplateAction.NAME, + GetComposableIndexTemplateAction.NAME + ); private static final Set MONITOR_TEXT_STRUCTURE_PATTERN = Collections.singleton("cluster:monitor/text_structure/*"); private static final Set MONITOR_TRANSFORM_PATTERN = Collections.unmodifiableSet( Sets.newHashSet("cluster:monitor/data_frame/*", "cluster:monitor/transform/*") diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/privilege/ClusterPrivilegeTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/privilege/ClusterPrivilegeTests.java index 267d04984fd0c..2159ded00cefa 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/privilege/ClusterPrivilegeTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/privilege/ClusterPrivilegeTests.java @@ -8,16 +8,31 @@ package org.elasticsearch.xpack.core.security.authz.privilege; import org.elasticsearch.action.ActionType; +import org.elasticsearch.action.admin.indices.template.get.GetComponentTemplateAction; +import org.elasticsearch.action.admin.indices.template.get.GetComposableIndexTemplateAction; +import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesAction; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.core.enrich.action.EnrichStatsAction; import org.elasticsearch.xpack.core.security.authz.permission.ClusterPermission; +import java.util.Arrays; + public class ClusterPrivilegeTests extends ESTestCase { public void testMonitorPrivilegeWillGrantActions() { assertGranted(ClusterPrivilegeResolver.MONITOR, EnrichStatsAction.INSTANCE); } + public void testMonitorPrivilegeGrantsGetTemplateActions() { + for (ActionType action : Arrays.asList( + GetComponentTemplateAction.INSTANCE, + GetComposableIndexTemplateAction.INSTANCE, + GetIndexTemplatesAction.INSTANCE + )) { + assertGranted(ClusterPrivilegeResolver.MONITOR, action); + } + } + public static void assertGranted(ClusterPrivilege clusterPrivilege, ActionType actionType) { assertTrue(clusterPrivilege.buildPermission(ClusterPermission.builder()).build().check(actionType.name(), null, null)); } 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 d6872673a597b..046559704da04 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 @@ -1206,7 +1206,7 @@ public void testRemoteMonitoringCollectorRole() { assertThat(remoteMonitoringCollectorRole.cluster().check(ClusterHealthAction.NAME, request, authentication), is(true)); assertThat(remoteMonitoringCollectorRole.cluster().check(ClusterStateAction.NAME, request, authentication), is(true)); assertThat(remoteMonitoringCollectorRole.cluster().check(ClusterStatsAction.NAME, request, authentication), is(true)); - assertThat(remoteMonitoringCollectorRole.cluster().check(GetIndexTemplatesAction.NAME, request, authentication), is(false)); + assertThat(remoteMonitoringCollectorRole.cluster().check(GetIndexTemplatesAction.NAME, request, authentication), is(true)); assertThat(remoteMonitoringCollectorRole.cluster().check(PutIndexTemplateAction.NAME, request, authentication), is(false)); assertThat(remoteMonitoringCollectorRole.cluster().check(DeleteIndexTemplateAction.NAME, request, authentication), is(false)); assertThat(remoteMonitoringCollectorRole.cluster().check(ClusterRerouteAction.NAME, request, authentication), is(false)); diff --git a/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/integration/ClusterPrivilegeIntegrationTests.java b/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/integration/ClusterPrivilegeIntegrationTests.java index 48de739b10d7b..043760d0c02f1 100644 --- a/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/integration/ClusterPrivilegeIntegrationTests.java +++ b/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/integration/ClusterPrivilegeIntegrationTests.java @@ -123,9 +123,17 @@ public void testThatClusterPrivilegesWorkAsExpectedViaHttp() throws Exception { assertAccessIsAllowed("user_b", "GET", "/_nodes/stats"); assertAccessIsAllowed("user_b", "GET", "/_nodes/hot_threads"); assertAccessIsAllowed("user_b", "GET", "/_nodes/infos"); + // monitoring allows template retrieval (because it's implied by having read access to cluster state + assertAccessIsAllowed("user_b", "GET", "/_cat/templates/" + (randomBoolean() ? "" : randomAlphaOfLengthBetween(2, 8))); + assertAccessIsAllowed("user_b", "GET", "/_template/"); + assertAccessIsAllowed("user_b", "GET", "/_index_template/"); + assertAccessIsAllowed("user_b", "GET", "/_component_template/"); // but no admin stuff assertAccessIsDenied("user_b", "POST", "/_cluster/reroute"); assertAccessIsDenied("user_b", "PUT", "/_cluster/settings", "{ \"transient\" : { \"search.default_search_timeout\": \"1m\" } }"); + assertAccessIsDenied("user_b", "DELETE", "/_template/" + randomAlphaOfLengthBetween(2, 8)); + assertAccessIsDenied("user_b", "DELETE", "/_index_template/" + randomAlphaOfLengthBetween(2, 8)); + assertAccessIsDenied("user_b", "DELETE", "/_component_template/" + randomAlphaOfLengthBetween(2, 8)); // sorry user_c, you are not allowed anything assertAccessIsDenied("user_c", "GET", "/_cluster/state");