security: add a reserved role for the ingest feature in Kibana
Closes elastic/elasticsearch#1667 Original commit: elastic/x-pack-elasticsearch@da2f6d9c4e
This commit is contained in:
parent
3638c8639f
commit
836e1d3a28
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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.authz.permission;
|
||||
|
||||
import org.elasticsearch.xpack.security.authz.RoleDescriptor;
|
||||
import org.elasticsearch.xpack.security.authz.privilege.ClusterPrivilege;
|
||||
import org.elasticsearch.xpack.security.authz.privilege.Privilege.Name;
|
||||
|
||||
/**
|
||||
* Role for users that should be allowed to use the Add Data/Ingest features in the UI
|
||||
*/
|
||||
public class IngestAdminRole extends Role {
|
||||
|
||||
private static final String[] CLUSTER_PRIVILEGES = new String[] { "manage_index_templates", "manage_pipeline" };
|
||||
private static final RoleDescriptor.IndicesPrivileges[] INDICES_PRIVILEGES = new RoleDescriptor.IndicesPrivileges[0];
|
||||
|
||||
public static final String NAME = "ingest_admin";
|
||||
public static final RoleDescriptor DESCRIPTOR = new RoleDescriptor(NAME, CLUSTER_PRIVILEGES, INDICES_PRIVILEGES, null);
|
||||
public static final IngestAdminRole INSTANCE = new IngestAdminRole();
|
||||
|
||||
private IngestAdminRole() {
|
||||
super(DESCRIPTOR.getName(),
|
||||
new ClusterPermission.Core(ClusterPrivilege.get(new Name(DESCRIPTOR.getClusterPrivileges()))),
|
||||
new IndicesPermission.Core(Role.Builder.convertFromIndicesPrivileges(DESCRIPTOR.getIndicesPrivileges())),
|
||||
RunAsPermission.Core.NONE);
|
||||
}
|
||||
}
|
|
@ -42,6 +42,7 @@ public class ClusterPrivilege extends AbstractAutomatonPrivilege<ClusterPrivileg
|
|||
new ClusterPrivilege("manage_ingest_pipelines", MANAGE_INGEST_PIPELINE_AUTOMATON);
|
||||
public static final ClusterPrivilege TRANSPORT_CLIENT = new ClusterPrivilege("transport_client", TRANSPORT_CLIENT_AUTOMATON);
|
||||
public static final ClusterPrivilege MANAGE_SECURITY = new ClusterPrivilege("manage_security", MANAGE_SECURITY_AUTOMATON);
|
||||
public static final ClusterPrivilege MANAGE_PIPELINE = new ClusterPrivilege("manage_pipeline", "cluster:admin/ingest/pipeline/*");
|
||||
|
||||
public static final Predicate<String> ACTION_MATCHER = ClusterPrivilege.ALL.predicate();
|
||||
|
||||
|
@ -56,6 +57,7 @@ public class ClusterPrivilege extends AbstractAutomatonPrivilege<ClusterPrivileg
|
|||
values.add(MANAGE_INGEST_PIPELINES);
|
||||
values.add(TRANSPORT_CLIENT);
|
||||
values.add(MANAGE_SECURITY);
|
||||
values.add(MANAGE_PIPELINE);
|
||||
}
|
||||
|
||||
static Set<ClusterPrivilege> values() {
|
||||
|
|
|
@ -14,6 +14,7 @@ import java.util.Set;
|
|||
import org.elasticsearch.common.util.set.Sets;
|
||||
import org.elasticsearch.xpack.security.SecurityContext;
|
||||
import org.elasticsearch.xpack.security.authz.RoleDescriptor;
|
||||
import org.elasticsearch.xpack.security.authz.permission.IngestAdminRole;
|
||||
import org.elasticsearch.xpack.security.authz.permission.KibanaRole;
|
||||
import org.elasticsearch.xpack.security.authz.permission.KibanaUserRole;
|
||||
import org.elasticsearch.xpack.security.authz.permission.MonitoringUserRole;
|
||||
|
@ -48,6 +49,8 @@ public class ReservedRolesStore implements RolesStore {
|
|||
return MonitoringUserRole.INSTANCE;
|
||||
case RemoteMonitoringAgentRole.NAME:
|
||||
return RemoteMonitoringAgentRole.INSTANCE;
|
||||
case IngestAdminRole.NAME:
|
||||
return IngestAdminRole.INSTANCE;
|
||||
case KibanaRole.NAME:
|
||||
// The only user that should know about this role is the kibana user itself (who has this role). The reason we want to hide
|
||||
// this role is that it was created specifically for kibana, with all the permissions that the kibana user needs.
|
||||
|
@ -78,6 +81,8 @@ public class ReservedRolesStore implements RolesStore {
|
|||
return MonitoringUserRole.DESCRIPTOR;
|
||||
case RemoteMonitoringAgentRole.NAME:
|
||||
return RemoteMonitoringAgentRole.DESCRIPTOR;
|
||||
case IngestAdminRole.NAME:
|
||||
return IngestAdminRole.DESCRIPTOR;
|
||||
case KibanaRole.NAME:
|
||||
// The only user that should know about this role is the kibana user itself (who has this role). The reason we want to hide
|
||||
// this role is that it was created specifically for kibana, with all the permissions that the kibana user needs.
|
||||
|
@ -94,15 +99,16 @@ public class ReservedRolesStore implements RolesStore {
|
|||
public Collection<RoleDescriptor> roleDescriptors() {
|
||||
if (KibanaUser.is(securityContext.getUser())) {
|
||||
return Arrays.asList(SuperuserRole.DESCRIPTOR, TransportClientRole.DESCRIPTOR, KibanaUserRole.DESCRIPTOR,
|
||||
KibanaRole.DESCRIPTOR, MonitoringUserRole.DESCRIPTOR, RemoteMonitoringAgentRole.DESCRIPTOR);
|
||||
KibanaRole.DESCRIPTOR, MonitoringUserRole.DESCRIPTOR, RemoteMonitoringAgentRole.DESCRIPTOR,
|
||||
IngestAdminRole.DESCRIPTOR);
|
||||
}
|
||||
return Arrays.asList(SuperuserRole.DESCRIPTOR, TransportClientRole.DESCRIPTOR, KibanaUserRole.DESCRIPTOR,
|
||||
MonitoringUserRole.DESCRIPTOR, RemoteMonitoringAgentRole.DESCRIPTOR);
|
||||
MonitoringUserRole.DESCRIPTOR, RemoteMonitoringAgentRole.DESCRIPTOR, IngestAdminRole.DESCRIPTOR);
|
||||
}
|
||||
|
||||
public static Set<String> names() {
|
||||
return Sets.newHashSet(SuperuserRole.NAME, KibanaRole.NAME, TransportClientRole.NAME, KibanaUserRole.NAME,
|
||||
MonitoringUserRole.NAME, RemoteMonitoringAgentRole.NAME);
|
||||
MonitoringUserRole.NAME, RemoteMonitoringAgentRole.NAME, IngestAdminRole.NAME);
|
||||
}
|
||||
|
||||
public static boolean isReserved(String role) {
|
||||
|
@ -114,6 +120,7 @@ public class ReservedRolesStore implements RolesStore {
|
|||
case MonitoringUserRole.NAME:
|
||||
case RemoteMonitoringAgentRole.NAME:
|
||||
case SystemUser.ROLE_NAME:
|
||||
case IngestAdminRole.NAME:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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.authz.permission;
|
||||
|
||||
import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteAction;
|
||||
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsAction;
|
||||
import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateAction;
|
||||
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesAction;
|
||||
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateAction;
|
||||
import org.elasticsearch.action.get.GetAction;
|
||||
import org.elasticsearch.action.index.IndexAction;
|
||||
import org.elasticsearch.action.ingest.DeletePipelineAction;
|
||||
import org.elasticsearch.action.ingest.GetPipelineAction;
|
||||
import org.elasticsearch.action.ingest.PutPipelineAction;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
import org.elasticsearch.xpack.monitoring.action.MonitoringBulkAction;
|
||||
import org.elasticsearch.xpack.security.authc.Authentication;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class IngestAdminRoleTests extends ESTestCase {
|
||||
|
||||
public void testClusterPermissions() {
|
||||
final TransportRequest request = new TransportRequest.Empty();
|
||||
final Authentication authentication = mock(Authentication.class);
|
||||
assertThat(IngestAdminRole.INSTANCE.cluster().check(PutIndexTemplateAction.NAME, request, authentication), is(true));
|
||||
assertThat(IngestAdminRole.INSTANCE.cluster().check(GetIndexTemplatesAction.NAME, request, authentication), is(true));
|
||||
assertThat(IngestAdminRole.INSTANCE.cluster().check(DeleteIndexTemplateAction.NAME, request, authentication), is(true));
|
||||
assertThat(IngestAdminRole.INSTANCE.cluster().check(PutPipelineAction.NAME, request, authentication), is(true));
|
||||
assertThat(IngestAdminRole.INSTANCE.cluster().check(GetPipelineAction.NAME, request, authentication), is(true));
|
||||
assertThat(IngestAdminRole.INSTANCE.cluster().check(DeletePipelineAction.NAME, request, authentication), is(true));
|
||||
|
||||
|
||||
assertThat(IngestAdminRole.INSTANCE.cluster().check(ClusterRerouteAction.NAME, request, authentication), is(false));
|
||||
assertThat(IngestAdminRole.INSTANCE.cluster().check(ClusterUpdateSettingsAction.NAME, request, authentication), is(false));
|
||||
assertThat(IngestAdminRole.INSTANCE.cluster().check(MonitoringBulkAction.NAME, request, authentication), is(false));
|
||||
}
|
||||
|
||||
public void testNoIndicesPermissions() {
|
||||
assertThat(IngestAdminRole.INSTANCE.indices().allowedIndicesMatcher(IndexAction.NAME).test("foo"), is(false));
|
||||
assertThat(IngestAdminRole.INSTANCE.indices().allowedIndicesMatcher("indices:foo").test(randomAsciiOfLengthBetween(8, 24)),
|
||||
is(false));
|
||||
assertThat(IngestAdminRole.INSTANCE.indices().allowedIndicesMatcher(GetAction.NAME).test(randomAsciiOfLengthBetween(8, 24)),
|
||||
is(false));
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
package org.elasticsearch.xpack.security.authz.store;
|
||||
|
||||
import org.elasticsearch.xpack.security.SecurityContext;
|
||||
import org.elasticsearch.xpack.security.authz.permission.IngestAdminRole;
|
||||
import org.elasticsearch.xpack.security.authz.permission.KibanaRole;
|
||||
import org.elasticsearch.xpack.security.authz.permission.KibanaUserRole;
|
||||
import org.elasticsearch.xpack.security.authz.permission.MonitoringUserRole;
|
||||
|
@ -56,6 +57,9 @@ public class ReservedRolesStoreTests extends ESTestCase {
|
|||
assertThat(reservedRolesStore.role(KibanaUserRole.NAME), sameInstance(KibanaUserRole.INSTANCE));
|
||||
assertThat(reservedRolesStore.roleDescriptor(KibanaUserRole.NAME), sameInstance(KibanaUserRole.DESCRIPTOR));
|
||||
|
||||
assertThat(reservedRolesStore.role(IngestAdminRole.NAME), sameInstance(IngestAdminRole.INSTANCE));
|
||||
assertThat(reservedRolesStore.roleDescriptor(IngestAdminRole.NAME), sameInstance(IngestAdminRole.DESCRIPTOR));
|
||||
|
||||
assertThat(reservedRolesStore.role(MonitoringUserRole.NAME), sameInstance(MonitoringUserRole.INSTANCE));
|
||||
assertThat(reservedRolesStore.roleDescriptor(MonitoringUserRole.NAME), sameInstance(MonitoringUserRole.DESCRIPTOR));
|
||||
|
||||
|
@ -63,7 +67,8 @@ public class ReservedRolesStoreTests extends ESTestCase {
|
|||
assertThat(reservedRolesStore.roleDescriptor(RemoteMonitoringAgentRole.NAME), sameInstance(RemoteMonitoringAgentRole.DESCRIPTOR));
|
||||
|
||||
assertThat(reservedRolesStore.roleDescriptors(), contains(SuperuserRole.DESCRIPTOR, TransportClientRole.DESCRIPTOR,
|
||||
KibanaUserRole.DESCRIPTOR, MonitoringUserRole.DESCRIPTOR, RemoteMonitoringAgentRole.DESCRIPTOR));
|
||||
KibanaUserRole.DESCRIPTOR, MonitoringUserRole.DESCRIPTOR, RemoteMonitoringAgentRole.DESCRIPTOR,
|
||||
IngestAdminRole.DESCRIPTOR));
|
||||
|
||||
assertThat(reservedRolesStore.role(KibanaRole.NAME), nullValue());
|
||||
assertThat(reservedRolesStore.roleDescriptor(KibanaRole.NAME), nullValue());
|
||||
|
@ -82,6 +87,9 @@ public class ReservedRolesStoreTests extends ESTestCase {
|
|||
assertThat(reservedRolesStore.role(KibanaUserRole.NAME), sameInstance(KibanaUserRole.INSTANCE));
|
||||
assertThat(reservedRolesStore.roleDescriptor(KibanaUserRole.NAME), sameInstance(KibanaUserRole.DESCRIPTOR));
|
||||
|
||||
assertThat(reservedRolesStore.role(IngestAdminRole.NAME), sameInstance(IngestAdminRole.INSTANCE));
|
||||
assertThat(reservedRolesStore.roleDescriptor(IngestAdminRole.NAME), sameInstance(IngestAdminRole.DESCRIPTOR));
|
||||
|
||||
assertThat(reservedRolesStore.role(KibanaRole.NAME), sameInstance(KibanaRole.INSTANCE));
|
||||
assertThat(reservedRolesStore.roleDescriptor(KibanaRole.NAME), sameInstance(KibanaRole.DESCRIPTOR));
|
||||
|
||||
|
@ -92,7 +100,8 @@ public class ReservedRolesStoreTests extends ESTestCase {
|
|||
assertThat(reservedRolesStore.roleDescriptor(RemoteMonitoringAgentRole.NAME), sameInstance(RemoteMonitoringAgentRole.DESCRIPTOR));
|
||||
|
||||
assertThat(reservedRolesStore.roleDescriptors(), contains(SuperuserRole.DESCRIPTOR, TransportClientRole.DESCRIPTOR,
|
||||
KibanaUserRole.DESCRIPTOR, KibanaRole.DESCRIPTOR, MonitoringUserRole.DESCRIPTOR, RemoteMonitoringAgentRole.DESCRIPTOR));
|
||||
KibanaUserRole.DESCRIPTOR, KibanaRole.DESCRIPTOR, MonitoringUserRole.DESCRIPTOR, RemoteMonitoringAgentRole.DESCRIPTOR,
|
||||
IngestAdminRole.DESCRIPTOR));
|
||||
|
||||
assertThat(reservedRolesStore.role(SystemUser.ROLE_NAME), nullValue());
|
||||
}
|
||||
|
@ -104,6 +113,7 @@ public class ReservedRolesStoreTests extends ESTestCase {
|
|||
assertThat(ReservedRolesStore.isReserved(SystemUser.ROLE_NAME), is(true));
|
||||
assertThat(ReservedRolesStore.isReserved(TransportClientRole.NAME), is(true));
|
||||
assertThat(ReservedRolesStore.isReserved(KibanaUserRole.NAME), is(true));
|
||||
assertThat(ReservedRolesStore.isReserved(IngestAdminRole.NAME), is(true));
|
||||
assertThat(ReservedRolesStore.isReserved(RemoteMonitoringAgentRole.NAME), is(true));
|
||||
assertThat(ReservedRolesStore.isReserved(MonitoringUserRole.NAME), is(true));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue