From 80fa13faddf8cd68d01f31ec2e1e3c341d4f4610 Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad <yogesh.gaikwad@elastic.co> Date: Wed, 7 Aug 2019 12:42:02 +1000 Subject: [PATCH 1/9] Add support for authentication based predicate for cluster permission Currently, cluster permission checks whether a cluster action is permitted and optionally in the context of a request. There are scenarios where we would want to check whether the cluster action is permitted, optionally in the context of a request and current authentication. For example, management of API keys is only restricted to the API keys owned by the current user. In this case, along with the cluster action and API key request, the check needs to perform whether the currently authenticated user is indeed allowed to operate only on owned API keys. With this commit, we are introducing one more context of the current authentication that can be considered during permission evaluation. Relates: #40031 --- .../authz/permission/ClusterPermission.java | 50 +- .../authz/permission/LimitedRole.java | 10 +- .../core/security/authz/permission/Role.java | 9 +- .../ConfigurableClusterPrivileges.java | 8 +- .../permission/ClusterPermissionTests.java | 74 ++- .../authz/permission/LimitedRoleTests.java | 25 +- .../ManageApplicationPrivilegesTests.java | 20 +- .../authz/privilege/PrivilegeTests.java | 7 +- .../authz/store/ReservedRolesStoreTests.java | 564 +++++++++--------- .../xpack/security/authz/RBACEngine.java | 2 +- .../authc/esnative/NativeRealmIntegTests.java | 6 +- .../authz/AuthorizationServiceTests.java | 5 +- .../authz/store/CompositeRolesStoreTests.java | 19 +- .../authz/store/FileRolesStoreTests.java | 6 +- 14 files changed, 434 insertions(+), 371 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java index 6d6a01684760c..738ff0c895520 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java @@ -8,14 +8,15 @@ import org.apache.lucene.util.automaton.Automaton; import org.apache.lucene.util.automaton.Operations; import org.elasticsearch.transport.TransportRequest; +import org.elasticsearch.xpack.core.security.authc.Authentication; import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilege; -import org.elasticsearch.xpack.core.security.authz.privilege.ConfigurableClusterPrivilege; import org.elasticsearch.xpack.core.security.support.Automatons; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.function.BiPredicate; import java.util.function.Predicate; /** @@ -34,14 +35,16 @@ private ClusterPermission(final Set<ClusterPrivilege> clusterPrivileges, } /** - * Checks permission to a cluster action for a given request. + * Checks permission to a cluster action for a given request in the context of given + * authentication. * * @param action cluster action * @param request {@link TransportRequest} + * @param authentication {@link Authentication} * @return {@code true} if the access is allowed else returns {@code false} */ - public boolean check(final String action, final TransportRequest request) { - return checks.stream().anyMatch(permission -> permission.check(action, request)); + public boolean check(final String action, final TransportRequest request, final Authentication authentication) { + return checks.stream().anyMatch(permission -> permission.check(action, request, authentication)); } /** @@ -90,11 +93,10 @@ public Builder add(final ClusterPrivilege clusterPrivilege, final Set<String> al return this; } - public Builder add(final ConfigurableClusterPrivilege configurableClusterPrivilege, final Predicate<String> actionPredicate, - final Predicate<TransportRequest> requestPredicate) { - return add(configurableClusterPrivilege, new ActionRequestPredicatePermissionCheck(configurableClusterPrivilege, - actionPredicate, - requestPredicate)); + public Builder add(final ClusterPrivilege clusterPrivilege, final Predicate<String> actionPredicate, + final BiPredicate<TransportRequest, Authentication> requestAuthnPredicate) { + return add(clusterPrivilege, new ActionRequestAuthenticationPredicatePermissionCheck(clusterPrivilege, + actionPredicate, requestAuthnPredicate)); } public Builder add(final ClusterPrivilege clusterPrivilege, final PermissionCheck permissionCheck) { @@ -124,13 +126,15 @@ public ClusterPermission build() { */ public interface PermissionCheck { /** - * Checks permission to a cluster action for a given request. + * Checks permission to a cluster action for a given request in the context of given + * authentication. * * @param action action name * @param request {@link TransportRequest} + * @param authentication {@link Authentication} * @return {@code true} if the specified action for given request is allowed else returns {@code false} */ - boolean check(String action, TransportRequest request); + boolean check(String action, TransportRequest request, Authentication authentication); /** * Checks whether specified {@link PermissionCheck} is implied by this {@link PermissionCheck}.<br> @@ -156,7 +160,7 @@ private static class AutomatonPermissionCheck implements PermissionCheck { } @Override - public boolean check(final String action, final TransportRequest request) { + public boolean check(final String action, final TransportRequest request, final Authentication authentication) { return actionPredicate.test(action); } @@ -169,28 +173,30 @@ public boolean implies(final PermissionCheck permissionCheck) { } } - // action and request based permission check - private static class ActionRequestPredicatePermissionCheck implements PermissionCheck { + // action, request and authentication based permission check + private static class ActionRequestAuthenticationPredicatePermissionCheck implements PermissionCheck { private final ClusterPrivilege clusterPrivilege; final Predicate<String> actionPredicate; - final Predicate<TransportRequest> requestPredicate; + final BiPredicate<TransportRequest, Authentication> requestAuthnPredicate; - ActionRequestPredicatePermissionCheck(final ClusterPrivilege clusterPrivilege, final Predicate<String> actionPredicate, - final Predicate<TransportRequest> requestPredicate) { + ActionRequestAuthenticationPredicatePermissionCheck(final ClusterPrivilege clusterPrivilege, + final Predicate<String> actionPredicate, + final BiPredicate<TransportRequest, Authentication> requestAuthnPredicate) { this.clusterPrivilege = clusterPrivilege; this.actionPredicate = actionPredicate; - this.requestPredicate = requestPredicate; + this.requestAuthnPredicate = requestAuthnPredicate; } @Override - public boolean check(final String action, final TransportRequest request) { - return actionPredicate.test(action) && requestPredicate.test(request); + public boolean check(final String action, final TransportRequest request, final Authentication authentication) { + return actionPredicate.test(action) && requestAuthnPredicate.test(request, authentication); } @Override public boolean implies(final PermissionCheck permissionCheck) { - if (permissionCheck instanceof ActionRequestPredicatePermissionCheck) { - final ActionRequestPredicatePermissionCheck otherCheck = (ActionRequestPredicatePermissionCheck) permissionCheck; + if (permissionCheck instanceof ActionRequestAuthenticationPredicatePermissionCheck) { + final ActionRequestAuthenticationPredicatePermissionCheck otherCheck = + (ActionRequestAuthenticationPredicatePermissionCheck) permissionCheck; return this.clusterPrivilege.equals(otherCheck.clusterPrivilege); } return false; diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/LimitedRole.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/LimitedRole.java index 8c7491d0a9a3d..871be8cbc6569 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/LimitedRole.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/LimitedRole.java @@ -9,6 +9,7 @@ import org.apache.lucene.util.automaton.Automaton; import org.elasticsearch.cluster.metadata.AliasOrIndex; import org.elasticsearch.transport.TransportRequest; +import org.elasticsearch.xpack.core.security.authc.Authentication; import org.elasticsearch.xpack.core.security.authz.accesscontrol.IndicesAccessControl; import org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilegeDescriptor; import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilege; @@ -122,15 +123,18 @@ public ResourcePrivilegesMap checkIndicesPrivileges(Set<String> checkForIndexPat } /** - * Check if cluster permissions allow for the given action, also checks whether the limited by role allows the given actions + * Check if cluster permissions allow for the given action, + * also checks whether the limited by role allows the given actions in the context of given + * authentication. * * @param action cluster action * @param request {@link TransportRequest} + * @param authentication {@link Authentication} * @return {@code true} if action is allowed else returns {@code false} */ @Override - public boolean checkClusterAction(String action, TransportRequest request) { - return super.checkClusterAction(action, request) && limitedBy.checkClusterAction(action, request); + public boolean checkClusterAction(String action, TransportRequest request, Authentication authentication) { + return super.checkClusterAction(action, request, authentication) && limitedBy.checkClusterAction(action, request, authentication); } /** diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/Role.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/Role.java index ef898a0876dda..94d583f616787 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/Role.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/Role.java @@ -12,6 +12,7 @@ import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.transport.TransportRequest; +import org.elasticsearch.xpack.core.security.authc.Authentication; import org.elasticsearch.xpack.core.security.authz.RoleDescriptor; import org.elasticsearch.xpack.core.security.authz.accesscontrol.IndicesAccessControl; import org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilege; @@ -121,14 +122,16 @@ public ResourcePrivilegesMap checkIndicesPrivileges(Set<String> checkForIndexPat } /** - * Check if cluster permissions allow for the given action + * Check if cluster permissions allow for the given action in the context of given + * authentication. * * @param action cluster action * @param request {@link TransportRequest} + * @param authentication {@link Authentication} * @return {@code true} if action is allowed else returns {@code false} */ - public boolean checkClusterAction(String action, TransportRequest request) { - return cluster.check(action, request); + public boolean checkClusterAction(String action, TransportRequest request, Authentication authentication) { + return cluster.check(action, request, authentication); } /** diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ConfigurableClusterPrivileges.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ConfigurableClusterPrivileges.java index 22ba4c1f2e33a..68cdfc3d1f836 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ConfigurableClusterPrivileges.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ConfigurableClusterPrivileges.java @@ -17,6 +17,7 @@ import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.transport.TransportRequest; import org.elasticsearch.xpack.core.security.action.privilege.ApplicationPrivilegesRequest; +import org.elasticsearch.xpack.core.security.authc.Authentication; import org.elasticsearch.xpack.core.security.authz.permission.ClusterPermission; import org.elasticsearch.xpack.core.security.authz.privilege.ConfigurableClusterPrivilege.Category; import org.elasticsearch.xpack.core.security.support.Automatons; @@ -30,6 +31,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Set; +import java.util.function.BiPredicate; import java.util.function.Predicate; /** @@ -131,12 +133,12 @@ public static class ManageApplicationPrivileges implements ConfigurableClusterPr private final Set<String> applicationNames; private final Predicate<String> applicationPredicate; - private final Predicate<TransportRequest> requestPredicate; + private final BiPredicate<TransportRequest, Authentication> requestAuthnPredicate; public ManageApplicationPrivileges(Set<String> applicationNames) { this.applicationNames = Collections.unmodifiableSet(applicationNames); this.applicationPredicate = Automatons.predicate(applicationNames); - this.requestPredicate = request -> { + this.requestAuthnPredicate = (request, authn) -> { if (request instanceof ApplicationPrivilegesRequest) { final ApplicationPrivilegesRequest privRequest = (ApplicationPrivilegesRequest) request; final Collection<String> requestApplicationNames = privRequest.getApplicationNames(); @@ -215,7 +217,7 @@ public int hashCode() { @Override public ClusterPermission.Builder buildPermission(final ClusterPermission.Builder builder) { - return builder.add(this, ACTION_PREDICATE, requestPredicate); + return builder.add(this, ACTION_PREDICATE, requestAuthnPredicate); } private interface Fields { diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermissionTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermissionTests.java index 18eb99e97f2f7..4fe368f5e33a1 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermissionTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermissionTests.java @@ -12,23 +12,26 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.transport.TransportRequest; +import org.elasticsearch.xpack.core.security.authc.Authentication; import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilege; import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilegeResolver; import org.elasticsearch.xpack.core.security.authz.privilege.ConfigurableClusterPrivilege; import org.elasticsearch.xpack.core.security.support.Automatons; import org.junit.Before; -import org.mockito.Mockito; import java.io.IOException; import java.util.Objects; import java.util.Set; +import java.util.function.BiPredicate; import java.util.function.Predicate; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.is; +import static org.mockito.Mockito.mock; public class ClusterPermissionTests extends ESTestCase { - private TransportRequest mockTransportRequest = Mockito.mock(TransportRequest.class); + private TransportRequest mockTransportRequest; + private Authentication mockAuthentication; private ClusterPrivilege cpThatDoesNothing = new ClusterPrivilege() { @Override public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { @@ -38,7 +41,8 @@ public ClusterPermission.Builder buildPermission(ClusterPermission.Builder build @Before public void setup() { - mockTransportRequest = Mockito.mock(TransportRequest.class); + mockTransportRequest = mock(TransportRequest.class); + mockAuthentication = mock(Authentication.class); } public void testClusterPermissionBuilder() { @@ -49,9 +53,9 @@ public void testClusterPermissionBuilder() { builder = ClusterPrivilegeResolver.MANAGE_SECURITY.buildPermission(builder); builder = ClusterPrivilegeResolver.MANAGE_ILM.buildPermission(builder); final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege1 = - new MockConfigurableClusterPrivilege(r -> r == mockTransportRequest); + new MockConfigurableClusterPrivilege((r,a) -> r == mockTransportRequest); final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege2 = - new MockConfigurableClusterPrivilege(r -> false); + new MockConfigurableClusterPrivilege((r,a) -> false); builder = mockConfigurableClusterPrivilege1.buildPermission(builder); builder = mockConfigurableClusterPrivilege2.buildPermission(builder); final ClusterPermission clusterPermission = builder.build(); @@ -71,17 +75,19 @@ public void testClusterPermissionCheck() { builder = ClusterPrivilegeResolver.MANAGE_ILM.buildPermission(builder); final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege1 = - new MockConfigurableClusterPrivilege(r -> r == mockTransportRequest); + new MockConfigurableClusterPrivilege((r,a) -> r == mockTransportRequest && a == mockAuthentication); final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege2 = - new MockConfigurableClusterPrivilege(r -> false); + new MockConfigurableClusterPrivilege((r,a) -> false); builder = mockConfigurableClusterPrivilege1.buildPermission(builder); builder = mockConfigurableClusterPrivilege2.buildPermission(builder); final ClusterPermission clusterPermission = builder.build(); - assertThat(clusterPermission.check("cluster:admin/xpack/security/token/invalidate", mockTransportRequest), is(true)); - assertThat(clusterPermission.check("cluster:admin/ilm/stop", mockTransportRequest), is(true)); - assertThat(clusterPermission.check("cluster:admin/xpack/security/privilege/get", mockTransportRequest), is(true)); - assertThat(clusterPermission.check("cluster:admin/snapshot/status", mockTransportRequest), is(false)); + assertThat(clusterPermission.check("cluster:admin/xpack/security/token/invalidate", mockTransportRequest, mockAuthentication), + is(true)); + assertThat(clusterPermission.check("cluster:admin/ilm/stop", mockTransportRequest, mockAuthentication), is(true)); + assertThat(clusterPermission.check("cluster:admin/xpack/security/privilege/get", mockTransportRequest, mockAuthentication), + is(true)); + assertThat(clusterPermission.check("cluster:admin/snapshot/status", mockTransportRequest, mockAuthentication), is(false)); } public void testClusterPermissionCheckWithEmptyActionPatterns() { @@ -89,8 +95,9 @@ public void testClusterPermissionCheckWithEmptyActionPatterns() { builder.add(cpThatDoesNothing, Set.of(), Set.of()); final ClusterPermission clusterPermission = builder.build(); - assertThat(clusterPermission.check("cluster:admin/ilm/start", mockTransportRequest), is(false)); - assertThat(clusterPermission.check("cluster:admin/xpack/security/token/invalidate", mockTransportRequest), is(false)); + assertThat(clusterPermission.check("cluster:admin/ilm/start", mockTransportRequest, mockAuthentication), is(false)); + assertThat(clusterPermission.check("cluster:admin/xpack/security/token/invalidate", mockTransportRequest, mockAuthentication), + is(false)); } public void testClusterPermissionCheckWithExcludeOnlyActionPatterns() { @@ -98,8 +105,9 @@ public void testClusterPermissionCheckWithExcludeOnlyActionPatterns() { builder.add(cpThatDoesNothing, Set.of(), Set.of("cluster:some/thing/to/exclude")); final ClusterPermission clusterPermission = builder.build(); - assertThat(clusterPermission.check("cluster:admin/ilm/start", mockTransportRequest), is(false)); - assertThat(clusterPermission.check("cluster:admin/xpack/security/token/invalidate", mockTransportRequest), is(false)); + assertThat(clusterPermission.check("cluster:admin/ilm/start", mockTransportRequest, mockAuthentication), is(false)); + assertThat(clusterPermission.check("cluster:admin/xpack/security/token/invalidate", mockTransportRequest, mockAuthentication), + is(false)); } public void testClusterPermissionCheckWithActionPatterns() { @@ -107,8 +115,9 @@ public void testClusterPermissionCheckWithActionPatterns() { builder.add(cpThatDoesNothing, Set.of("cluster:admin/*"), Set.of("cluster:admin/ilm/*")); final ClusterPermission clusterPermission = builder.build(); - assertThat(clusterPermission.check("cluster:admin/ilm/start", mockTransportRequest), is(false)); - assertThat(clusterPermission.check("cluster:admin/xpack/security/token/invalidate", mockTransportRequest), is(true)); + assertThat(clusterPermission.check("cluster:admin/ilm/start", mockTransportRequest, mockAuthentication), is(false)); + assertThat(clusterPermission.check("cluster:admin/xpack/security/token/invalidate", mockTransportRequest, mockAuthentication), + is(true)); } public void testClusterPermissionCheckWithActionPatternsAndNoExludePatterns() { @@ -116,8 +125,9 @@ public void testClusterPermissionCheckWithActionPatternsAndNoExludePatterns() { builder.add(cpThatDoesNothing, Set.of("cluster:admin/*"), Set.of()); final ClusterPermission clusterPermission = builder.build(); - assertThat(clusterPermission.check("cluster:admin/ilm/start", mockTransportRequest), is(true)); - assertThat(clusterPermission.check("cluster:admin/xpack/security/token/invalidate", mockTransportRequest), is(true)); + assertThat(clusterPermission.check("cluster:admin/ilm/start", mockTransportRequest, mockAuthentication), is(true)); + assertThat(clusterPermission.check("cluster:admin/xpack/security/token/invalidate", mockTransportRequest, mockAuthentication), + is(true)); } public void testNoneClusterPermissionIsImpliedByNone() { @@ -129,9 +139,9 @@ public void testNoneClusterPermissionIsImpliedByAny() { builder = ClusterPrivilegeResolver.MANAGE_SECURITY.buildPermission(builder); builder = ClusterPrivilegeResolver.MANAGE_ILM.buildPermission(builder); final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege1 = - new MockConfigurableClusterPrivilege(r -> r == mockTransportRequest); + new MockConfigurableClusterPrivilege((r,a) -> r == mockTransportRequest && a == mockAuthentication); final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege2 = - new MockConfigurableClusterPrivilege(r -> false); + new MockConfigurableClusterPrivilege((r,a) -> false); builder = mockConfigurableClusterPrivilege1.buildPermission(builder); builder = mockConfigurableClusterPrivilege2.buildPermission(builder); final ClusterPermission clusterPermission = builder.build(); @@ -144,7 +154,7 @@ public void testClusterPermissionSubsetWithConfigurableClusterPrivilegeIsImplied builder = ClusterPrivilegeResolver.MANAGE_ML.buildPermission(builder); builder = ClusterPrivilegeResolver.MANAGE_ILM.buildPermission(builder); final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege1 = - new MockConfigurableClusterPrivilege(r -> r == mockTransportRequest); + new MockConfigurableClusterPrivilege((r,a) -> r == mockTransportRequest && a == mockAuthentication); builder = mockConfigurableClusterPrivilege1.buildPermission(builder); final ClusterPermission clusterPermission = builder.build(); @@ -161,7 +171,7 @@ public void testClusterPermissionNonSubsetWithConfigurableClusterPrivilegeIsImpl builder = ClusterPrivilegeResolver.MANAGE_ML.buildPermission(builder); builder = ClusterPrivilegeResolver.MANAGE_ILM.buildPermission(builder); final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege1 = - new MockConfigurableClusterPrivilege(r -> r == mockTransportRequest); + new MockConfigurableClusterPrivilege((r,a) -> r == mockTransportRequest && a == mockAuthentication); builder = mockConfigurableClusterPrivilege1.buildPermission(builder); final ClusterPermission clusterPermission = builder.build(); @@ -169,7 +179,7 @@ public void testClusterPermissionNonSubsetWithConfigurableClusterPrivilegeIsImpl builder1 = ClusterPrivilegeResolver.MANAGE_ML.buildPermission(builder1); builder1 = mockConfigurableClusterPrivilege1.buildPermission(builder1); final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege2 = - new MockConfigurableClusterPrivilege(r -> false); + new MockConfigurableClusterPrivilege((r,a) -> false); builder1 = mockConfigurableClusterPrivilege2.buildPermission(builder1); final ClusterPermission otherClusterPermission = builder1.build(); @@ -207,7 +217,7 @@ public void testClusterPermissionIsImpliedBySameClusterPermission() { builder = ClusterPrivilegeResolver.MANAGE_ML.buildPermission(builder); builder = ClusterPrivilegeResolver.MANAGE_ILM.buildPermission(builder); final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege1 = - new MockConfigurableClusterPrivilege(r -> r == mockTransportRequest); + new MockConfigurableClusterPrivilege((r,a) -> r == mockTransportRequest && a == mockAuthentication); builder = mockConfigurableClusterPrivilege1.buildPermission(builder); final ClusterPermission clusterPermission = builder.build(); @@ -224,10 +234,10 @@ public void testClusterPermissionSubsetIsImpliedByAllClusterPermission() { private static class MockConfigurableClusterPrivilege implements ConfigurableClusterPrivilege { static final Predicate<String> ACTION_PREDICATE = Automatons.predicate("cluster:admin/xpack/security/privilege/*"); - private Predicate<TransportRequest> requestPredicate; + private BiPredicate<TransportRequest, Authentication> requestAuthnPredicate; - MockConfigurableClusterPrivilege(Predicate<TransportRequest> requestPredicate) { - this.requestPredicate = requestPredicate; + MockConfigurableClusterPrivilege(BiPredicate<TransportRequest, Authentication> requestPredicate) { + this.requestAuthnPredicate = requestPredicate; } @Override @@ -258,24 +268,24 @@ public boolean equals(Object o) { return false; } final MockConfigurableClusterPrivilege that = (MockConfigurableClusterPrivilege) o; - return requestPredicate.equals(that.requestPredicate); + return requestAuthnPredicate.equals(that.requestAuthnPredicate); } @Override public int hashCode() { - return Objects.hash(requestPredicate); + return Objects.hash(requestAuthnPredicate); } @Override public String toString() { return "MockConfigurableClusterPrivilege{" + - "requestPredicate=" + requestPredicate + + "requestAuthnPredicate=" + requestAuthnPredicate + '}'; } @Override public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { - return builder.add(this, ACTION_PREDICATE, requestPredicate); + return builder.add(this, ACTION_PREDICATE, requestAuthnPredicate); } } } diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/LimitedRoleTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/LimitedRoleTests.java index 4bcc581d072b1..74e06d1cbce25 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/LimitedRoleTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/LimitedRoleTests.java @@ -18,6 +18,7 @@ import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.transport.TransportRequest; +import org.elasticsearch.xpack.core.security.authc.Authentication; import org.elasticsearch.xpack.core.security.authz.accesscontrol.IndicesAccessControl; import org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilege; import org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilegeDescriptor; @@ -128,24 +129,26 @@ public void testAuthorize() { public void testCheckClusterAction() { Role fromRole = Role.builder("a-role").cluster(Collections.singleton("manage_security"), Collections.emptyList()) - .build(); - assertThat(fromRole.checkClusterAction("cluster:admin/xpack/security/x", mock(TransportRequest.class)), is(true)); + .build(); + Authentication authentication = mock(Authentication.class); + assertThat(fromRole.checkClusterAction("cluster:admin/xpack/security/x", mock(TransportRequest.class), authentication), is(true)); { Role limitedByRole = Role.builder("limited-role") - .cluster(Collections.singleton("all"), Collections.emptyList()).build(); - assertThat(limitedByRole.checkClusterAction("cluster:admin/xpack/security/x", mock(TransportRequest.class)), is(true)); - assertThat(limitedByRole.checkClusterAction("cluster:other-action", mock(TransportRequest.class)), is(true)); + .cluster(Collections.singleton("all"), Collections.emptyList()).build(); + assertThat(limitedByRole.checkClusterAction("cluster:admin/xpack/security/x", mock(TransportRequest.class), authentication), + is(true)); + assertThat(limitedByRole.checkClusterAction("cluster:other-action", mock(TransportRequest.class), authentication), is(true)); Role role = LimitedRole.createLimitedRole(fromRole, limitedByRole); - assertThat(role.checkClusterAction("cluster:admin/xpack/security/x", mock(TransportRequest.class)), is(true)); - assertThat(role.checkClusterAction("cluster:other-action", mock(TransportRequest.class)), is(false)); + assertThat(role.checkClusterAction("cluster:admin/xpack/security/x", mock(TransportRequest.class), authentication), is(true)); + assertThat(role.checkClusterAction("cluster:other-action", mock(TransportRequest.class), authentication), is(false)); } { Role limitedByRole = Role.builder("limited-role") - .cluster(Collections.singleton("monitor"), Collections.emptyList()).build(); - assertThat(limitedByRole.checkClusterAction("cluster:monitor/me", mock(TransportRequest.class)), is(true)); + .cluster(Collections.singleton("monitor"), Collections.emptyList()).build(); + assertThat(limitedByRole.checkClusterAction("cluster:monitor/me", mock(TransportRequest.class), authentication), is(true)); Role role = LimitedRole.createLimitedRole(fromRole, limitedByRole); - assertThat(role.checkClusterAction("cluster:monitor/me", mock(TransportRequest.class)), is(false)); - assertThat(role.checkClusterAction("cluster:admin/xpack/security/x", mock(TransportRequest.class)), is(false)); + assertThat(role.checkClusterAction("cluster:monitor/me", mock(TransportRequest.class), authentication), is(false)); + assertThat(role.checkClusterAction("cluster:admin/xpack/security/x", mock(TransportRequest.class), authentication), is(false)); } } diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/privilege/ManageApplicationPrivilegesTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/privilege/ManageApplicationPrivilegesTests.java index dfe1147fb2c43..10eea045aadab 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/privilege/ManageApplicationPrivilegesTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/privilege/ManageApplicationPrivilegesTests.java @@ -24,6 +24,7 @@ import org.elasticsearch.xpack.core.security.action.privilege.DeletePrivilegesRequest; import org.elasticsearch.xpack.core.security.action.privilege.GetPrivilegesRequest; import org.elasticsearch.xpack.core.security.action.privilege.PutPrivilegesRequest; +import org.elasticsearch.xpack.core.security.authc.Authentication; import org.elasticsearch.xpack.core.security.authz.permission.ClusterPermission; import org.elasticsearch.xpack.core.security.authz.privilege.ConfigurableClusterPrivileges.ManageApplicationPrivileges; @@ -40,6 +41,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; +import static org.mockito.Mockito.mock; public class ManageApplicationPrivilegesTests extends ESTestCase { @@ -97,14 +99,15 @@ public void testActionAndRequestPredicate() { assertThat(kibanaAndLogstashPermission, notNullValue()); assertThat(cloudAndSwiftypePermission, notNullValue()); + final Authentication authentication = mock(Authentication.class); final GetPrivilegesRequest getKibana1 = new GetPrivilegesRequest(); getKibana1.application("kibana-1"); - assertTrue(kibanaAndLogstashPermission.check("cluster:admin/xpack/security/privilege/get", getKibana1)); - assertFalse(cloudAndSwiftypePermission.check("cluster:admin/xpack/security/privilege/get", getKibana1)); + assertTrue(kibanaAndLogstashPermission.check("cluster:admin/xpack/security/privilege/get", getKibana1, authentication)); + assertFalse(cloudAndSwiftypePermission.check("cluster:admin/xpack/security/privilege/get", getKibana1, authentication)); final DeletePrivilegesRequest deleteLogstash = new DeletePrivilegesRequest("logstash", new String[]{"all"}); - assertTrue(kibanaAndLogstashPermission.check("cluster:admin/xpack/security/privilege/get", deleteLogstash)); - assertFalse(cloudAndSwiftypePermission.check("cluster:admin/xpack/security/privilege/get", deleteLogstash)); + assertTrue(kibanaAndLogstashPermission.check("cluster:admin/xpack/security/privilege/get", deleteLogstash, authentication)); + assertFalse(cloudAndSwiftypePermission.check("cluster:admin/xpack/security/privilege/get", deleteLogstash, authentication)); final PutPrivilegesRequest putKibana = new PutPrivilegesRequest(); @@ -114,11 +117,12 @@ public void testActionAndRequestPredicate() { randomAlphaOfLengthBetween(3, 6).toLowerCase(Locale.ROOT), Collections.emptySet(), Collections.emptyMap())); } putKibana.setPrivileges(kibanaPrivileges); - assertTrue(kibanaAndLogstashPermission.check("cluster:admin/xpack/security/privilege/get", putKibana)); - assertFalse(cloudAndSwiftypePermission.check("cluster:admin/xpack/security/privilege/get", putKibana)); + assertTrue(kibanaAndLogstashPermission.check("cluster:admin/xpack/security/privilege/get", putKibana, authentication)); + assertFalse(cloudAndSwiftypePermission.check("cluster:admin/xpack/security/privilege/get", putKibana, authentication)); } public void testSecurityForGetAllApplicationPrivileges() { + final Authentication authentication = mock(Authentication.class); final GetPrivilegesRequest getAll = new GetPrivilegesRequest(); getAll.application(null); getAll.privileges(new String[0]); @@ -130,8 +134,8 @@ public void testSecurityForGetAllApplicationPrivileges() { final ClusterPermission kibanaOnlyPermission = kibanaOnly.buildPermission(ClusterPermission.builder()).build(); final ClusterPermission allAppsPermission = allApps.buildPermission(ClusterPermission.builder()).build(); - assertFalse(kibanaOnlyPermission.check("cluster:admin/xpack/security/privilege/get", getAll)); - assertTrue(allAppsPermission.check("cluster:admin/xpack/security/privilege/get", getAll)); + assertFalse(kibanaOnlyPermission.check("cluster:admin/xpack/security/privilege/get", getAll, authentication)); + assertTrue(allAppsPermission.check("cluster:admin/xpack/security/privilege/get", getAll, authentication)); } private ManageApplicationPrivileges clone(ManageApplicationPrivileges original) { diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/privilege/PrivilegeTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/privilege/PrivilegeTests.java index bd64d2112287f..e02c930101694 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/privilege/PrivilegeTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/privilege/PrivilegeTests.java @@ -9,17 +9,18 @@ import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.transport.TransportRequest; +import org.elasticsearch.xpack.core.security.authc.Authentication; import org.elasticsearch.xpack.core.security.authz.permission.ClusterPermission; import org.elasticsearch.xpack.core.security.support.Automatons; import org.junit.Rule; import org.junit.rules.ExpectedException; -import org.mockito.Mockito; import java.util.Set; import java.util.function.Predicate; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; +import static org.mockito.Mockito.mock; public class PrivilegeTests extends ESTestCase { @Rule @@ -35,13 +36,13 @@ public void testSubActionPattern() throws Exception { private void verifyClusterActionAllowed(ClusterPrivilege clusterPrivilege, String... actions) { ClusterPermission clusterPermission = clusterPrivilege.buildPermission(ClusterPermission.builder()).build(); for (String action: actions) { - assertTrue(clusterPermission.check(action, Mockito.mock(TransportRequest.class))); + assertTrue(clusterPermission.check(action, mock(TransportRequest.class), mock(Authentication.class))); } } private void verifyClusterActionDenied(ClusterPrivilege clusterPrivilege, String... actions) { ClusterPermission clusterPermission = clusterPrivilege.buildPermission(ClusterPermission.builder()).build(); for (String action: actions) { - assertFalse(clusterPermission.check(action, Mockito.mock(TransportRequest.class))); + assertFalse(clusterPermission.check(action, mock(TransportRequest.class), mock(Authentication.class))); } } public void testCluster() throws Exception { 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 4433b9d3750e7..4e6509d2ea823 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 @@ -124,6 +124,7 @@ import org.elasticsearch.xpack.core.security.action.token.CreateTokenAction; import org.elasticsearch.xpack.core.security.action.token.InvalidateTokenAction; import org.elasticsearch.xpack.core.security.action.user.PutUserAction; +import org.elasticsearch.xpack.core.security.authc.Authentication; import org.elasticsearch.xpack.core.security.authz.RoleDescriptor; import org.elasticsearch.xpack.core.security.authz.accesscontrol.IndicesAccessControl.IndexAccessControl; import org.elasticsearch.xpack.core.security.authz.permission.FieldPermissionsCache; @@ -200,33 +201,34 @@ public void testIsReserved() { public void testSnapshotUserRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("snapshot_user"); assertNotNull(roleDescriptor); assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); Role snapshotUserRole = Role.builder(roleDescriptor, null).build(); - assertThat(snapshotUserRole.cluster().check(GetRepositoriesAction.NAME, request), is(true)); - assertThat(snapshotUserRole.cluster().check(CreateSnapshotAction.NAME, request), is(true)); - assertThat(snapshotUserRole.cluster().check(SnapshotsStatusAction.NAME, request), is(true)); - assertThat(snapshotUserRole.cluster().check(GetSnapshotsAction.NAME, request), is(true)); - - assertThat(snapshotUserRole.cluster().check(PutRepositoryAction.NAME, request), is(false)); - assertThat(snapshotUserRole.cluster().check(GetIndexTemplatesAction.NAME, request), is(false)); - assertThat(snapshotUserRole.cluster().check(DeleteIndexTemplateAction.NAME, request), is(false)); - assertThat(snapshotUserRole.cluster().check(PutPipelineAction.NAME, request), is(false)); - assertThat(snapshotUserRole.cluster().check(GetPipelineAction.NAME, request), is(false)); - assertThat(snapshotUserRole.cluster().check(DeletePipelineAction.NAME, request), is(false)); - assertThat(snapshotUserRole.cluster().check(ClusterRerouteAction.NAME, request), is(false)); - assertThat(snapshotUserRole.cluster().check(ClusterUpdateSettingsAction.NAME, request), is(false)); - assertThat(snapshotUserRole.cluster().check(MonitoringBulkAction.NAME, request), is(false)); - assertThat(snapshotUserRole.cluster().check(GetWatchAction.NAME, request), is(false)); - assertThat(snapshotUserRole.cluster().check(PutWatchAction.NAME, request), is(false)); - assertThat(snapshotUserRole.cluster().check(DeleteWatchAction.NAME, request), is(false)); - assertThat(snapshotUserRole.cluster().check(ExecuteWatchAction.NAME, request), is(false)); - assertThat(snapshotUserRole.cluster().check(AckWatchAction.NAME, request), is(false)); - assertThat(snapshotUserRole.cluster().check(ActivateWatchAction.NAME, request), is(false)); - assertThat(snapshotUserRole.cluster().check(WatcherServiceAction.NAME, request), is(false)); + assertThat(snapshotUserRole.cluster().check(GetRepositoriesAction.NAME, request, authentication), is(true)); + assertThat(snapshotUserRole.cluster().check(CreateSnapshotAction.NAME, request, authentication), is(true)); + assertThat(snapshotUserRole.cluster().check(SnapshotsStatusAction.NAME, request, authentication), is(true)); + assertThat(snapshotUserRole.cluster().check(GetSnapshotsAction.NAME, request, authentication), is(true)); + + assertThat(snapshotUserRole.cluster().check(PutRepositoryAction.NAME, request, authentication), is(false)); + assertThat(snapshotUserRole.cluster().check(GetIndexTemplatesAction.NAME, request, authentication), is(false)); + assertThat(snapshotUserRole.cluster().check(DeleteIndexTemplateAction.NAME, request, authentication), is(false)); + assertThat(snapshotUserRole.cluster().check(PutPipelineAction.NAME, request, authentication), is(false)); + assertThat(snapshotUserRole.cluster().check(GetPipelineAction.NAME, request, authentication), is(false)); + assertThat(snapshotUserRole.cluster().check(DeletePipelineAction.NAME, request, authentication), is(false)); + assertThat(snapshotUserRole.cluster().check(ClusterRerouteAction.NAME, request, authentication), is(false)); + assertThat(snapshotUserRole.cluster().check(ClusterUpdateSettingsAction.NAME, request, authentication), is(false)); + assertThat(snapshotUserRole.cluster().check(MonitoringBulkAction.NAME, request, authentication), is(false)); + assertThat(snapshotUserRole.cluster().check(GetWatchAction.NAME, request, authentication), is(false)); + assertThat(snapshotUserRole.cluster().check(PutWatchAction.NAME, request, authentication), is(false)); + assertThat(snapshotUserRole.cluster().check(DeleteWatchAction.NAME, request, authentication), is(false)); + assertThat(snapshotUserRole.cluster().check(ExecuteWatchAction.NAME, request, authentication), is(false)); + assertThat(snapshotUserRole.cluster().check(AckWatchAction.NAME, request, authentication), is(false)); + assertThat(snapshotUserRole.cluster().check(ActivateWatchAction.NAME, request, authentication), is(false)); + assertThat(snapshotUserRole.cluster().check(WatcherServiceAction.NAME, request, authentication), is(false)); assertThat(snapshotUserRole.indices().allowedIndicesMatcher(IndexAction.NAME).test(randomAlphaOfLengthBetween(8, 24)), is(false)); assertThat(snapshotUserRole.indices().allowedIndicesMatcher("indices:foo").test(randomAlphaOfLengthBetween(8, 24)), is(false)); @@ -247,22 +249,23 @@ public void testSnapshotUserRole() { public void testIngestAdminRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("ingest_admin"); assertNotNull(roleDescriptor); assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); Role ingestAdminRole = Role.builder(roleDescriptor, null).build(); - assertThat(ingestAdminRole.cluster().check(PutIndexTemplateAction.NAME, request), is(true)); - assertThat(ingestAdminRole.cluster().check(GetIndexTemplatesAction.NAME, request), is(true)); - assertThat(ingestAdminRole.cluster().check(DeleteIndexTemplateAction.NAME, request), is(true)); - assertThat(ingestAdminRole.cluster().check(PutPipelineAction.NAME, request), is(true)); - assertThat(ingestAdminRole.cluster().check(GetPipelineAction.NAME, request), is(true)); - assertThat(ingestAdminRole.cluster().check(DeletePipelineAction.NAME, request), is(true)); + assertThat(ingestAdminRole.cluster().check(PutIndexTemplateAction.NAME, request, authentication), is(true)); + assertThat(ingestAdminRole.cluster().check(GetIndexTemplatesAction.NAME, request, authentication), is(true)); + assertThat(ingestAdminRole.cluster().check(DeleteIndexTemplateAction.NAME, request, authentication), is(true)); + assertThat(ingestAdminRole.cluster().check(PutPipelineAction.NAME, request, authentication), is(true)); + assertThat(ingestAdminRole.cluster().check(GetPipelineAction.NAME, request, authentication), is(true)); + assertThat(ingestAdminRole.cluster().check(DeletePipelineAction.NAME, request, authentication), is(true)); - assertThat(ingestAdminRole.cluster().check(ClusterRerouteAction.NAME, request), is(false)); - assertThat(ingestAdminRole.cluster().check(ClusterUpdateSettingsAction.NAME, request), is(false)); - assertThat(ingestAdminRole.cluster().check(MonitoringBulkAction.NAME, request), is(false)); + assertThat(ingestAdminRole.cluster().check(ClusterRerouteAction.NAME, request, authentication), is(false)); + assertThat(ingestAdminRole.cluster().check(ClusterUpdateSettingsAction.NAME, request, authentication), is(false)); + assertThat(ingestAdminRole.cluster().check(MonitoringBulkAction.NAME, request, authentication), is(false)); assertThat(ingestAdminRole.indices().allowedIndicesMatcher(IndexAction.NAME).test("foo"), is(false)); assertThat(ingestAdminRole.indices().allowedIndicesMatcher("indices:foo").test(randomAlphaOfLengthBetween(8, 24)), @@ -275,39 +278,40 @@ public void testIngestAdminRole() { public void testKibanaSystemRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("kibana_system"); assertNotNull(roleDescriptor); assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); Role kibanaRole = Role.builder(roleDescriptor, null).build(); - assertThat(kibanaRole.cluster().check(ClusterHealthAction.NAME, request), is(true)); - assertThat(kibanaRole.cluster().check(ClusterStateAction.NAME, request), is(true)); - assertThat(kibanaRole.cluster().check(ClusterStatsAction.NAME, request), is(true)); - assertThat(kibanaRole.cluster().check(PutIndexTemplateAction.NAME, request), is(true)); - assertThat(kibanaRole.cluster().check(GetIndexTemplatesAction.NAME, request), is(true)); - assertThat(kibanaRole.cluster().check(ClusterRerouteAction.NAME, request), is(false)); - assertThat(kibanaRole.cluster().check(ClusterUpdateSettingsAction.NAME, request), is(false)); - assertThat(kibanaRole.cluster().check(MonitoringBulkAction.NAME, request), is(true)); + assertThat(kibanaRole.cluster().check(ClusterHealthAction.NAME, request, authentication), is(true)); + assertThat(kibanaRole.cluster().check(ClusterStateAction.NAME, request, authentication), is(true)); + assertThat(kibanaRole.cluster().check(ClusterStatsAction.NAME, request, authentication), is(true)); + assertThat(kibanaRole.cluster().check(PutIndexTemplateAction.NAME, request, authentication), is(true)); + assertThat(kibanaRole.cluster().check(GetIndexTemplatesAction.NAME, request, authentication), is(true)); + assertThat(kibanaRole.cluster().check(ClusterRerouteAction.NAME, request, authentication), is(false)); + assertThat(kibanaRole.cluster().check(ClusterUpdateSettingsAction.NAME, request, authentication), is(false)); + assertThat(kibanaRole.cluster().check(MonitoringBulkAction.NAME, request, authentication), is(true)); // SAML and token - assertThat(kibanaRole.cluster().check(SamlPrepareAuthenticationAction.NAME, request), is(true)); - assertThat(kibanaRole.cluster().check(SamlAuthenticateAction.NAME, request), is(true)); - assertThat(kibanaRole.cluster().check(InvalidateTokenAction.NAME, request), is(true)); - assertThat(kibanaRole.cluster().check(CreateTokenAction.NAME, request), is(true)); + assertThat(kibanaRole.cluster().check(SamlPrepareAuthenticationAction.NAME, request, authentication), is(true)); + assertThat(kibanaRole.cluster().check(SamlAuthenticateAction.NAME, request, authentication), is(true)); + assertThat(kibanaRole.cluster().check(InvalidateTokenAction.NAME, request, authentication), is(true)); + assertThat(kibanaRole.cluster().check(CreateTokenAction.NAME, request, authentication), is(true)); // Application Privileges DeletePrivilegesRequest deleteKibanaPrivileges = new DeletePrivilegesRequest("kibana-.kibana", new String[]{ "all", "read" }); DeletePrivilegesRequest deleteLogstashPrivileges = new DeletePrivilegesRequest("logstash", new String[]{ "all", "read" }); - assertThat(kibanaRole.cluster().check(DeletePrivilegesAction.NAME, deleteKibanaPrivileges), is(true)); - assertThat(kibanaRole.cluster().check(DeletePrivilegesAction.NAME, deleteLogstashPrivileges), is(false)); + assertThat(kibanaRole.cluster().check(DeletePrivilegesAction.NAME, deleteKibanaPrivileges, authentication), is(true)); + assertThat(kibanaRole.cluster().check(DeletePrivilegesAction.NAME, deleteLogstashPrivileges, authentication), is(false)); GetPrivilegesRequest getKibanaPrivileges = new GetPrivilegesRequest(); getKibanaPrivileges.application("kibana-.kibana-sales"); GetPrivilegesRequest getApmPrivileges = new GetPrivilegesRequest(); getApmPrivileges.application("apm"); - assertThat(kibanaRole.cluster().check(GetPrivilegesAction.NAME, getKibanaPrivileges), is(true)); - assertThat(kibanaRole.cluster().check(GetPrivilegesAction.NAME, getApmPrivileges), is(false)); + assertThat(kibanaRole.cluster().check(GetPrivilegesAction.NAME, getKibanaPrivileges, authentication), is(true)); + assertThat(kibanaRole.cluster().check(GetPrivilegesAction.NAME, getApmPrivileges, authentication), is(false)); PutPrivilegesRequest putKibanaPrivileges = new PutPrivilegesRequest(); putKibanaPrivileges.setPrivileges(Collections.singletonList(new ApplicationPrivilegeDescriptor( @@ -315,10 +319,10 @@ public void testKibanaSystemRole() { PutPrivilegesRequest putSwiftypePrivileges = new PutPrivilegesRequest(); putSwiftypePrivileges.setPrivileges(Collections.singletonList(new ApplicationPrivilegeDescriptor( "swiftype-kibana" , "all", Collections.emptySet(), Collections.emptyMap()))); - assertThat(kibanaRole.cluster().check(PutPrivilegesAction.NAME, putKibanaPrivileges), is(true)); - assertThat(kibanaRole.cluster().check(PutPrivilegesAction.NAME, putSwiftypePrivileges), is(false)); + assertThat(kibanaRole.cluster().check(PutPrivilegesAction.NAME, putKibanaPrivileges, authentication), is(true)); + assertThat(kibanaRole.cluster().check(PutPrivilegesAction.NAME, putSwiftypePrivileges, authentication), is(false)); - assertThat(kibanaRole.cluster().check(GetBuiltinPrivilegesAction.NAME, request), is(true)); + assertThat(kibanaRole.cluster().check(GetBuiltinPrivilegesAction.NAME, request, authentication), is(true)); // Everything else assertThat(kibanaRole.runAs().check(randomAlphaOfLengthBetween(1, 12)), is(false)); @@ -378,19 +382,20 @@ public void testKibanaSystemRole() { public void testKibanaUserRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("kibana_user"); assertNotNull(roleDescriptor); assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); Role kibanaUserRole = Role.builder(roleDescriptor, null).build(); - assertThat(kibanaUserRole.cluster().check(ClusterHealthAction.NAME, request), is(false)); - assertThat(kibanaUserRole.cluster().check(ClusterStateAction.NAME, request), is(false)); - assertThat(kibanaUserRole.cluster().check(ClusterStatsAction.NAME, request), is(false)); - assertThat(kibanaUserRole.cluster().check(PutIndexTemplateAction.NAME, request), is(false)); - assertThat(kibanaUserRole.cluster().check(ClusterRerouteAction.NAME, request), is(false)); - assertThat(kibanaUserRole.cluster().check(ClusterUpdateSettingsAction.NAME, request), is(false)); - assertThat(kibanaUserRole.cluster().check(MonitoringBulkAction.NAME, request), is(false)); + assertThat(kibanaUserRole.cluster().check(ClusterHealthAction.NAME, request, authentication), is(false)); + assertThat(kibanaUserRole.cluster().check(ClusterStateAction.NAME, request, authentication), is(false)); + assertThat(kibanaUserRole.cluster().check(ClusterStatsAction.NAME, request, authentication), is(false)); + assertThat(kibanaUserRole.cluster().check(PutIndexTemplateAction.NAME, request, authentication), is(false)); + assertThat(kibanaUserRole.cluster().check(ClusterRerouteAction.NAME, request, authentication), is(false)); + assertThat(kibanaUserRole.cluster().check(ClusterUpdateSettingsAction.NAME, request, authentication), is(false)); + assertThat(kibanaUserRole.cluster().check(MonitoringBulkAction.NAME, request, authentication), is(false)); assertThat(kibanaUserRole.runAs().check(randomAlphaOfLengthBetween(1, 12)), is(false)); @@ -415,21 +420,22 @@ public void testKibanaUserRole() { public void testMonitoringUserRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("monitoring_user"); assertNotNull(roleDescriptor); assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); Role monitoringUserRole = Role.builder(roleDescriptor, null).build(); - assertThat(monitoringUserRole.cluster().check(MainAction.NAME, request), is(true)); - assertThat(monitoringUserRole.cluster().check(XPackInfoAction.NAME, request), is(true)); - assertThat(monitoringUserRole.cluster().check(ClusterHealthAction.NAME, request), is(false)); - assertThat(monitoringUserRole.cluster().check(ClusterStateAction.NAME, request), is(false)); - assertThat(monitoringUserRole.cluster().check(ClusterStatsAction.NAME, request), is(false)); - assertThat(monitoringUserRole.cluster().check(PutIndexTemplateAction.NAME, request), is(false)); - assertThat(monitoringUserRole.cluster().check(ClusterRerouteAction.NAME, request), is(false)); - assertThat(monitoringUserRole.cluster().check(ClusterUpdateSettingsAction.NAME, request), is(false)); - assertThat(monitoringUserRole.cluster().check(MonitoringBulkAction.NAME, request), is(false)); + assertThat(monitoringUserRole.cluster().check(MainAction.NAME, request, authentication), is(true)); + assertThat(monitoringUserRole.cluster().check(XPackInfoAction.NAME, request, authentication), is(true)); + assertThat(monitoringUserRole.cluster().check(ClusterHealthAction.NAME, request, authentication), is(false)); + assertThat(monitoringUserRole.cluster().check(ClusterStateAction.NAME, request, authentication), is(false)); + assertThat(monitoringUserRole.cluster().check(ClusterStatsAction.NAME, request, authentication), is(false)); + assertThat(monitoringUserRole.cluster().check(PutIndexTemplateAction.NAME, request, authentication), is(false)); + assertThat(monitoringUserRole.cluster().check(ClusterRerouteAction.NAME, request, authentication), is(false)); + assertThat(monitoringUserRole.cluster().check(ClusterUpdateSettingsAction.NAME, request, authentication), is(false)); + assertThat(monitoringUserRole.cluster().check(MonitoringBulkAction.NAME, request, authentication), is(false)); assertThat(monitoringUserRole.runAs().check(randomAlphaOfLengthBetween(1, 12)), is(false)); @@ -471,28 +477,29 @@ public void testMonitoringUserRole() { public void testRemoteMonitoringAgentRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("remote_monitoring_agent"); assertNotNull(roleDescriptor); assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); Role remoteMonitoringAgentRole = Role.builder(roleDescriptor, null).build(); - assertThat(remoteMonitoringAgentRole.cluster().check(ClusterHealthAction.NAME, request), is(true)); - assertThat(remoteMonitoringAgentRole.cluster().check(ClusterStateAction.NAME, request), is(true)); - assertThat(remoteMonitoringAgentRole.cluster().check(ClusterStatsAction.NAME, request), is(true)); - assertThat(remoteMonitoringAgentRole.cluster().check(PutIndexTemplateAction.NAME, request), is(true)); - assertThat(remoteMonitoringAgentRole.cluster().check(ClusterRerouteAction.NAME, request), is(false)); - assertThat(remoteMonitoringAgentRole.cluster().check(ClusterUpdateSettingsAction.NAME, request), is(false)); - assertThat(remoteMonitoringAgentRole.cluster().check(MonitoringBulkAction.NAME, request), is(false)); - assertThat(remoteMonitoringAgentRole.cluster().check(GetWatchAction.NAME, request), is(true)); - assertThat(remoteMonitoringAgentRole.cluster().check(PutWatchAction.NAME, request), is(true)); - assertThat(remoteMonitoringAgentRole.cluster().check(DeleteWatchAction.NAME, request), is(true)); - assertThat(remoteMonitoringAgentRole.cluster().check(ExecuteWatchAction.NAME, request), is(false)); - assertThat(remoteMonitoringAgentRole.cluster().check(AckWatchAction.NAME, request), is(false)); - assertThat(remoteMonitoringAgentRole.cluster().check(ActivateWatchAction.NAME, request), is(false)); - assertThat(remoteMonitoringAgentRole.cluster().check(WatcherServiceAction.NAME, request), is(false)); + assertThat(remoteMonitoringAgentRole.cluster().check(ClusterHealthAction.NAME, request, authentication), is(true)); + assertThat(remoteMonitoringAgentRole.cluster().check(ClusterStateAction.NAME, request, authentication), is(true)); + assertThat(remoteMonitoringAgentRole.cluster().check(ClusterStatsAction.NAME, request, authentication), is(true)); + assertThat(remoteMonitoringAgentRole.cluster().check(PutIndexTemplateAction.NAME, request, authentication), is(true)); + assertThat(remoteMonitoringAgentRole.cluster().check(ClusterRerouteAction.NAME, request, authentication), is(false)); + assertThat(remoteMonitoringAgentRole.cluster().check(ClusterUpdateSettingsAction.NAME, request, authentication), is(false)); + assertThat(remoteMonitoringAgentRole.cluster().check(MonitoringBulkAction.NAME, request, authentication), is(false)); + assertThat(remoteMonitoringAgentRole.cluster().check(GetWatchAction.NAME, request, authentication), is(true)); + assertThat(remoteMonitoringAgentRole.cluster().check(PutWatchAction.NAME, request, authentication), is(true)); + assertThat(remoteMonitoringAgentRole.cluster().check(DeleteWatchAction.NAME, request, authentication), is(true)); + assertThat(remoteMonitoringAgentRole.cluster().check(ExecuteWatchAction.NAME, request, authentication), is(false)); + assertThat(remoteMonitoringAgentRole.cluster().check(AckWatchAction.NAME, request, authentication), is(false)); + assertThat(remoteMonitoringAgentRole.cluster().check(ActivateWatchAction.NAME, request, authentication), is(false)); + assertThat(remoteMonitoringAgentRole.cluster().check(WatcherServiceAction.NAME, request, authentication), is(false)); // we get this from the cluster:monitor privilege - assertThat(remoteMonitoringAgentRole.cluster().check(WatcherStatsAction.NAME, request), is(true)); + assertThat(remoteMonitoringAgentRole.cluster().check(WatcherStatsAction.NAME, request, authentication), is(true)); assertThat(remoteMonitoringAgentRole.runAs().check(randomAlphaOfLengthBetween(1, 12)), is(false)); @@ -530,21 +537,22 @@ public void testRemoteMonitoringAgentRole() { public void testRemoteMonitoringCollectorRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("remote_monitoring_collector"); assertNotNull(roleDescriptor); assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); Role remoteMonitoringAgentRole = Role.builder(roleDescriptor, null).build(); - assertThat(remoteMonitoringAgentRole.cluster().check(ClusterHealthAction.NAME, request), is(true)); - assertThat(remoteMonitoringAgentRole.cluster().check(ClusterStateAction.NAME, request), is(true)); - assertThat(remoteMonitoringAgentRole.cluster().check(ClusterStatsAction.NAME, request), is(true)); - assertThat(remoteMonitoringAgentRole.cluster().check(GetIndexTemplatesAction.NAME, request), is(false)); - assertThat(remoteMonitoringAgentRole.cluster().check(PutIndexTemplateAction.NAME, request), is(false)); - assertThat(remoteMonitoringAgentRole.cluster().check(DeleteIndexTemplateAction.NAME, request), is(false)); - assertThat(remoteMonitoringAgentRole.cluster().check(ClusterRerouteAction.NAME, request), is(false)); - assertThat(remoteMonitoringAgentRole.cluster().check(ClusterUpdateSettingsAction.NAME, request), is(false)); - assertThat(remoteMonitoringAgentRole.cluster().check(MonitoringBulkAction.NAME, request), is(false)); + assertThat(remoteMonitoringAgentRole.cluster().check(ClusterHealthAction.NAME, request, authentication), is(true)); + assertThat(remoteMonitoringAgentRole.cluster().check(ClusterStateAction.NAME, request, authentication), is(true)); + assertThat(remoteMonitoringAgentRole.cluster().check(ClusterStatsAction.NAME, request, authentication), is(true)); + assertThat(remoteMonitoringAgentRole.cluster().check(GetIndexTemplatesAction.NAME, request, authentication), is(false)); + assertThat(remoteMonitoringAgentRole.cluster().check(PutIndexTemplateAction.NAME, request, authentication), is(false)); + assertThat(remoteMonitoringAgentRole.cluster().check(DeleteIndexTemplateAction.NAME, request, authentication), is(false)); + assertThat(remoteMonitoringAgentRole.cluster().check(ClusterRerouteAction.NAME, request, authentication), is(false)); + assertThat(remoteMonitoringAgentRole.cluster().check(ClusterUpdateSettingsAction.NAME, request, authentication), is(false)); + assertThat(remoteMonitoringAgentRole.cluster().check(MonitoringBulkAction.NAME, request, authentication), is(false)); assertThat(remoteMonitoringAgentRole.runAs().check(randomAlphaOfLengthBetween(1, 12)), is(false)); @@ -628,19 +636,20 @@ private void assertMonitoringOnRestrictedIndices(Role role) { public void testReportingUserRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("reporting_user"); assertNotNull(roleDescriptor); assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); Role reportingUserRole = Role.builder(roleDescriptor, null).build(); - assertThat(reportingUserRole.cluster().check(ClusterHealthAction.NAME, request), is(false)); - assertThat(reportingUserRole.cluster().check(ClusterStateAction.NAME, request), is(false)); - assertThat(reportingUserRole.cluster().check(ClusterStatsAction.NAME, request), is(false)); - assertThat(reportingUserRole.cluster().check(PutIndexTemplateAction.NAME, request), is(false)); - assertThat(reportingUserRole.cluster().check(ClusterRerouteAction.NAME, request), is(false)); - assertThat(reportingUserRole.cluster().check(ClusterUpdateSettingsAction.NAME, request), is(false)); - assertThat(reportingUserRole.cluster().check(MonitoringBulkAction.NAME, request), is(false)); + assertThat(reportingUserRole.cluster().check(ClusterHealthAction.NAME, request, authentication), is(false)); + assertThat(reportingUserRole.cluster().check(ClusterStateAction.NAME, request, authentication), is(false)); + assertThat(reportingUserRole.cluster().check(ClusterStatsAction.NAME, request, authentication), is(false)); + assertThat(reportingUserRole.cluster().check(PutIndexTemplateAction.NAME, request, authentication), is(false)); + assertThat(reportingUserRole.cluster().check(ClusterRerouteAction.NAME, request, authentication), is(false)); + assertThat(reportingUserRole.cluster().check(ClusterUpdateSettingsAction.NAME, request, authentication), is(false)); + assertThat(reportingUserRole.cluster().check(MonitoringBulkAction.NAME, request, authentication), is(false)); assertThat(reportingUserRole.runAs().check(randomAlphaOfLengthBetween(1, 12)), is(false)); @@ -668,19 +677,20 @@ public void testReportingUserRole() { public void testKibanaDashboardOnlyUserRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("kibana_dashboard_only_user"); assertNotNull(roleDescriptor); assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); Role dashboardsOnlyUserRole = Role.builder(roleDescriptor, null).build(); - assertThat(dashboardsOnlyUserRole.cluster().check(ClusterHealthAction.NAME, request), is(false)); - assertThat(dashboardsOnlyUserRole.cluster().check(ClusterStateAction.NAME, request), is(false)); - assertThat(dashboardsOnlyUserRole.cluster().check(ClusterStatsAction.NAME, request), is(false)); - assertThat(dashboardsOnlyUserRole.cluster().check(PutIndexTemplateAction.NAME, request), is(false)); - assertThat(dashboardsOnlyUserRole.cluster().check(ClusterRerouteAction.NAME, request), is(false)); - assertThat(dashboardsOnlyUserRole.cluster().check(ClusterUpdateSettingsAction.NAME, request), is(false)); - assertThat(dashboardsOnlyUserRole.cluster().check(MonitoringBulkAction.NAME, request), is(false)); + assertThat(dashboardsOnlyUserRole.cluster().check(ClusterHealthAction.NAME, request, authentication), is(false)); + assertThat(dashboardsOnlyUserRole.cluster().check(ClusterStateAction.NAME, request, authentication), is(false)); + assertThat(dashboardsOnlyUserRole.cluster().check(ClusterStatsAction.NAME, request, authentication), is(false)); + assertThat(dashboardsOnlyUserRole.cluster().check(PutIndexTemplateAction.NAME, request, authentication), is(false)); + assertThat(dashboardsOnlyUserRole.cluster().check(ClusterRerouteAction.NAME, request, authentication), is(false)); + assertThat(dashboardsOnlyUserRole.cluster().check(ClusterUpdateSettingsAction.NAME, request, authentication), is(false)); + assertThat(dashboardsOnlyUserRole.cluster().check(MonitoringBulkAction.NAME, request, authentication), is(false)); assertThat(dashboardsOnlyUserRole.runAs().check(randomAlphaOfLengthBetween(1, 12)), is(false)); @@ -702,18 +712,19 @@ public void testKibanaDashboardOnlyUserRole() { public void testSuperuserRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("superuser"); assertNotNull(roleDescriptor); assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); Role superuserRole = Role.builder(roleDescriptor, null).build(); - assertThat(superuserRole.cluster().check(ClusterHealthAction.NAME, request), is(true)); - assertThat(superuserRole.cluster().check(ClusterUpdateSettingsAction.NAME, request), is(true)); - assertThat(superuserRole.cluster().check(PutUserAction.NAME, request), is(true)); - assertThat(superuserRole.cluster().check(PutRoleAction.NAME, request), is(true)); - assertThat(superuserRole.cluster().check(PutIndexTemplateAction.NAME, request), is(true)); - assertThat(superuserRole.cluster().check("internal:admin/foo", request), is(false)); + assertThat(superuserRole.cluster().check(ClusterHealthAction.NAME, request, authentication), is(true)); + assertThat(superuserRole.cluster().check(ClusterUpdateSettingsAction.NAME, request, authentication), is(true)); + assertThat(superuserRole.cluster().check(PutUserAction.NAME, request, authentication), is(true)); + assertThat(superuserRole.cluster().check(PutRoleAction.NAME, request, authentication), is(true)); + assertThat(superuserRole.cluster().check(PutIndexTemplateAction.NAME, request, authentication), is(true)); + assertThat(superuserRole.cluster().check("internal:admin/foo", request, authentication), is(false)); final Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build(); final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_6, @@ -772,19 +783,20 @@ public void testSuperuserRole() { public void testLogstashSystemRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("logstash_system"); assertNotNull(roleDescriptor); assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); Role logstashSystemRole = Role.builder(roleDescriptor, null).build(); - assertThat(logstashSystemRole.cluster().check(ClusterHealthAction.NAME, request), is(true)); - assertThat(logstashSystemRole.cluster().check(ClusterStateAction.NAME, request), is(true)); - assertThat(logstashSystemRole.cluster().check(ClusterStatsAction.NAME, request), is(true)); - assertThat(logstashSystemRole.cluster().check(PutIndexTemplateAction.NAME, request), is(false)); - assertThat(logstashSystemRole.cluster().check(ClusterRerouteAction.NAME, request), is(false)); - assertThat(logstashSystemRole.cluster().check(ClusterUpdateSettingsAction.NAME, request), is(false)); - assertThat(logstashSystemRole.cluster().check(MonitoringBulkAction.NAME, request), is(true)); + assertThat(logstashSystemRole.cluster().check(ClusterHealthAction.NAME, request, authentication), is(true)); + assertThat(logstashSystemRole.cluster().check(ClusterStateAction.NAME, request, authentication), is(true)); + assertThat(logstashSystemRole.cluster().check(ClusterStatsAction.NAME, request, authentication), is(true)); + assertThat(logstashSystemRole.cluster().check(PutIndexTemplateAction.NAME, request, authentication), is(false)); + assertThat(logstashSystemRole.cluster().check(ClusterRerouteAction.NAME, request, authentication), is(false)); + assertThat(logstashSystemRole.cluster().check(ClusterUpdateSettingsAction.NAME, request, authentication), is(false)); + assertThat(logstashSystemRole.cluster().check(MonitoringBulkAction.NAME, request, authentication), is(true)); assertThat(logstashSystemRole.runAs().check(randomAlphaOfLengthBetween(1, 30)), is(false)); @@ -798,6 +810,7 @@ public void testLogstashSystemRole() { public void testBeatsAdminRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); final RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("beats_admin"); assertNotNull(roleDescriptor); @@ -805,13 +818,13 @@ public void testBeatsAdminRole() { final Role beatsAdminRole = Role.builder(roleDescriptor, null).build(); - assertThat(beatsAdminRole.cluster().check(ClusterHealthAction.NAME, request), is(false)); - assertThat(beatsAdminRole.cluster().check(ClusterStateAction.NAME, request), is(false)); - assertThat(beatsAdminRole.cluster().check(ClusterStatsAction.NAME, request), is(false)); - assertThat(beatsAdminRole.cluster().check(PutIndexTemplateAction.NAME, request), is(false)); - assertThat(beatsAdminRole.cluster().check(ClusterRerouteAction.NAME, request), is(false)); - assertThat(beatsAdminRole.cluster().check(ClusterUpdateSettingsAction.NAME, request), is(false)); - assertThat(beatsAdminRole.cluster().check(MonitoringBulkAction.NAME, request), is(false)); + assertThat(beatsAdminRole.cluster().check(ClusterHealthAction.NAME, request, authentication), is(false)); + assertThat(beatsAdminRole.cluster().check(ClusterStateAction.NAME, request, authentication), is(false)); + assertThat(beatsAdminRole.cluster().check(ClusterStatsAction.NAME, request, authentication), is(false)); + assertThat(beatsAdminRole.cluster().check(PutIndexTemplateAction.NAME, request, authentication), is(false)); + assertThat(beatsAdminRole.cluster().check(ClusterRerouteAction.NAME, request, authentication), is(false)); + assertThat(beatsAdminRole.cluster().check(ClusterUpdateSettingsAction.NAME, request, authentication), is(false)); + assertThat(beatsAdminRole.cluster().check(MonitoringBulkAction.NAME, request, authentication), is(false)); assertThat(beatsAdminRole.runAs().check(randomAlphaOfLengthBetween(1, 30)), is(false)); @@ -836,19 +849,20 @@ public void testBeatsAdminRole() { public void testBeatsSystemRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor(BeatsSystemUser.ROLE_NAME); assertNotNull(roleDescriptor); assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); Role beatsSystemRole = Role.builder(roleDescriptor, null).build(); - assertThat(beatsSystemRole.cluster().check(ClusterHealthAction.NAME, request), is(true)); - assertThat(beatsSystemRole.cluster().check(ClusterStateAction.NAME, request), is(true)); - assertThat(beatsSystemRole.cluster().check(ClusterStatsAction.NAME, request), is(true)); - assertThat(beatsSystemRole.cluster().check(PutIndexTemplateAction.NAME, request), is(false)); - assertThat(beatsSystemRole.cluster().check(ClusterRerouteAction.NAME, request), is(false)); - assertThat(beatsSystemRole.cluster().check(ClusterUpdateSettingsAction.NAME, request), is(false)); - assertThat(beatsSystemRole.cluster().check(MonitoringBulkAction.NAME, request), is(true)); + assertThat(beatsSystemRole.cluster().check(ClusterHealthAction.NAME, request, authentication), is(true)); + assertThat(beatsSystemRole.cluster().check(ClusterStateAction.NAME, request, authentication), is(true)); + assertThat(beatsSystemRole.cluster().check(ClusterStatsAction.NAME, request, authentication), is(true)); + assertThat(beatsSystemRole.cluster().check(PutIndexTemplateAction.NAME, request, authentication), is(false)); + assertThat(beatsSystemRole.cluster().check(ClusterRerouteAction.NAME, request, authentication), is(false)); + assertThat(beatsSystemRole.cluster().check(ClusterUpdateSettingsAction.NAME, request, authentication), is(false)); + assertThat(beatsSystemRole.cluster().check(MonitoringBulkAction.NAME, request, authentication), is(true)); assertThat(beatsSystemRole.runAs().check(randomAlphaOfLengthBetween(1, 30)), is(false)); @@ -869,19 +883,20 @@ public void testBeatsSystemRole() { public void testAPMSystemRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor(APMSystemUser.ROLE_NAME); assertNotNull(roleDescriptor); assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); Role APMSystemRole = Role.builder(roleDescriptor, null).build(); - assertThat(APMSystemRole.cluster().check(ClusterHealthAction.NAME, request), is(true)); - assertThat(APMSystemRole.cluster().check(ClusterStateAction.NAME, request), is(true)); - assertThat(APMSystemRole.cluster().check(ClusterStatsAction.NAME, request), is(true)); - assertThat(APMSystemRole.cluster().check(PutIndexTemplateAction.NAME, request), is(false)); - assertThat(APMSystemRole.cluster().check(ClusterRerouteAction.NAME, request), is(false)); - assertThat(APMSystemRole.cluster().check(ClusterUpdateSettingsAction.NAME, request), is(false)); - assertThat(APMSystemRole.cluster().check(MonitoringBulkAction.NAME, request), is(true)); + assertThat(APMSystemRole.cluster().check(ClusterHealthAction.NAME, request, authentication), is(true)); + assertThat(APMSystemRole.cluster().check(ClusterStateAction.NAME, request, authentication), is(true)); + assertThat(APMSystemRole.cluster().check(ClusterStatsAction.NAME, request, authentication), is(true)); + assertThat(APMSystemRole.cluster().check(PutIndexTemplateAction.NAME, request, authentication), is(false)); + assertThat(APMSystemRole.cluster().check(ClusterRerouteAction.NAME, request, authentication), is(false)); + assertThat(APMSystemRole.cluster().check(ClusterUpdateSettingsAction.NAME, request, authentication), is(false)); + assertThat(APMSystemRole.cluster().check(MonitoringBulkAction.NAME, request, authentication), is(true)); assertThat(APMSystemRole.runAs().check(randomAlphaOfLengthBetween(1, 30)), is(false)); @@ -912,62 +927,63 @@ public void testAPMUserRole() { public void testMachineLearningAdminRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("machine_learning_admin"); assertNotNull(roleDescriptor); assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); Role role = Role.builder(roleDescriptor, null).build(); - assertThat(role.cluster().check(CloseJobAction.NAME, request), is(true)); - assertThat(role.cluster().check(DeleteCalendarAction.NAME, request), is(true)); - assertThat(role.cluster().check(DeleteCalendarEventAction.NAME, request), is(true)); - assertThat(role.cluster().check(DeleteDatafeedAction.NAME, request), is(true)); - assertThat(role.cluster().check(DeleteExpiredDataAction.NAME, request), is(true)); - assertThat(role.cluster().check(DeleteFilterAction.NAME, request), is(true)); - assertThat(role.cluster().check(DeleteForecastAction.NAME, request), is(true)); - assertThat(role.cluster().check(DeleteJobAction.NAME, request), is(true)); - assertThat(role.cluster().check(DeleteModelSnapshotAction.NAME, request), is(true)); - assertThat(role.cluster().check(FinalizeJobExecutionAction.NAME, request), is(false)); // internal use only - assertThat(role.cluster().check(FindFileStructureAction.NAME, request), is(true)); - assertThat(role.cluster().check(FlushJobAction.NAME, request), is(true)); - assertThat(role.cluster().check(ForecastJobAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetBucketsAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetCalendarEventsAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetCalendarsAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetCategoriesAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetDatafeedsAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetDatafeedsStatsAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetFiltersAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetInfluencersAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetJobsAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetJobsStatsAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetModelSnapshotsAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetOverallBucketsAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetRecordsAction.NAME, request), is(true)); - assertThat(role.cluster().check(IsolateDatafeedAction.NAME, request), is(false)); // internal use only - assertThat(role.cluster().check(KillProcessAction.NAME, request), is(false)); // internal use only - assertThat(role.cluster().check(MlInfoAction.NAME, request), is(true)); - assertThat(role.cluster().check(OpenJobAction.NAME, request), is(true)); - assertThat(role.cluster().check(PersistJobAction.NAME, request), is(true)); - assertThat(role.cluster().check(PostCalendarEventsAction.NAME, request), is(true)); - assertThat(role.cluster().check(PostDataAction.NAME, request), is(true)); - assertThat(role.cluster().check(PreviewDatafeedAction.NAME, request), is(true)); - assertThat(role.cluster().check(PutCalendarAction.NAME, request), is(true)); - assertThat(role.cluster().check(PutDatafeedAction.NAME, request), is(true)); - assertThat(role.cluster().check(PutFilterAction.NAME, request), is(true)); - assertThat(role.cluster().check(PutJobAction.NAME, request), is(true)); - assertThat(role.cluster().check(RevertModelSnapshotAction.NAME, request), is(true)); - assertThat(role.cluster().check(SetUpgradeModeAction.NAME, request), is(true)); - assertThat(role.cluster().check(StartDatafeedAction.NAME, request), is(true)); - assertThat(role.cluster().check(StopDatafeedAction.NAME, request), is(true)); - assertThat(role.cluster().check(UpdateCalendarJobAction.NAME, request), is(true)); - assertThat(role.cluster().check(UpdateDatafeedAction.NAME, request), is(true)); - assertThat(role.cluster().check(UpdateFilterAction.NAME, request), is(true)); - assertThat(role.cluster().check(UpdateJobAction.NAME, request), is(true)); - assertThat(role.cluster().check(UpdateModelSnapshotAction.NAME, request), is(true)); - assertThat(role.cluster().check(UpdateProcessAction.NAME, request), is(false)); // internal use only - assertThat(role.cluster().check(ValidateDetectorAction.NAME, request), is(true)); - assertThat(role.cluster().check(ValidateJobConfigAction.NAME, request), is(true)); + assertThat(role.cluster().check(CloseJobAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(DeleteCalendarAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(DeleteCalendarEventAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(DeleteDatafeedAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(DeleteExpiredDataAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(DeleteFilterAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(DeleteForecastAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(DeleteJobAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(DeleteModelSnapshotAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(FinalizeJobExecutionAction.NAME, request, authentication), is(false)); // internal use only + assertThat(role.cluster().check(FindFileStructureAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(FlushJobAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(ForecastJobAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetBucketsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetCalendarEventsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetCalendarsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetCategoriesAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetDatafeedsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetDatafeedsStatsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetFiltersAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetInfluencersAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetJobsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetJobsStatsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetModelSnapshotsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetOverallBucketsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetRecordsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(IsolateDatafeedAction.NAME, request, authentication), is(false)); // internal use only + assertThat(role.cluster().check(KillProcessAction.NAME, request, authentication), is(false)); // internal use only + assertThat(role.cluster().check(MlInfoAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(OpenJobAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(PersistJobAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(PostCalendarEventsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(PostDataAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(PreviewDatafeedAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(PutCalendarAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(PutDatafeedAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(PutFilterAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(PutJobAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(RevertModelSnapshotAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(SetUpgradeModeAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(StartDatafeedAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(StopDatafeedAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(UpdateCalendarJobAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(UpdateDatafeedAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(UpdateFilterAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(UpdateJobAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(UpdateModelSnapshotAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(UpdateProcessAction.NAME, request, authentication), is(false)); // internal use only + assertThat(role.cluster().check(ValidateDetectorAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(ValidateJobConfigAction.NAME, request, authentication), is(true)); assertThat(role.runAs().check(randomAlphaOfLengthBetween(1, 30)), is(false)); assertNoAccessAllowed(role, "foo"); @@ -995,62 +1011,63 @@ public void testMachineLearningAdminRole() { public void testMachineLearningUserRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("machine_learning_user"); assertNotNull(roleDescriptor); assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); Role role = Role.builder(roleDescriptor, null).build(); - assertThat(role.cluster().check(CloseJobAction.NAME, request), is(false)); - assertThat(role.cluster().check(DeleteCalendarAction.NAME, request), is(false)); - assertThat(role.cluster().check(DeleteCalendarEventAction.NAME, request), is(false)); - assertThat(role.cluster().check(DeleteDatafeedAction.NAME, request), is(false)); - assertThat(role.cluster().check(DeleteExpiredDataAction.NAME, request), is(false)); - assertThat(role.cluster().check(DeleteFilterAction.NAME, request), is(false)); - assertThat(role.cluster().check(DeleteForecastAction.NAME, request), is(false)); - assertThat(role.cluster().check(DeleteJobAction.NAME, request), is(false)); - assertThat(role.cluster().check(DeleteModelSnapshotAction.NAME, request), is(false)); - assertThat(role.cluster().check(FinalizeJobExecutionAction.NAME, request), is(false)); - assertThat(role.cluster().check(FindFileStructureAction.NAME, request), is(true)); - assertThat(role.cluster().check(FlushJobAction.NAME, request), is(false)); - assertThat(role.cluster().check(ForecastJobAction.NAME, request), is(false)); - assertThat(role.cluster().check(GetBucketsAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetCalendarEventsAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetCalendarsAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetCategoriesAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetDatafeedsAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetDatafeedsStatsAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetFiltersAction.NAME, request), is(false)); - assertThat(role.cluster().check(GetInfluencersAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetJobsAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetJobsStatsAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetModelSnapshotsAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetOverallBucketsAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetRecordsAction.NAME, request), is(true)); - assertThat(role.cluster().check(IsolateDatafeedAction.NAME, request), is(false)); - assertThat(role.cluster().check(KillProcessAction.NAME, request), is(false)); - assertThat(role.cluster().check(MlInfoAction.NAME, request), is(true)); - assertThat(role.cluster().check(OpenJobAction.NAME, request), is(false)); - assertThat(role.cluster().check(PersistJobAction.NAME, request), is(false)); - assertThat(role.cluster().check(PostCalendarEventsAction.NAME, request), is(false)); - assertThat(role.cluster().check(PostDataAction.NAME, request), is(false)); - assertThat(role.cluster().check(PreviewDatafeedAction.NAME, request), is(false)); - assertThat(role.cluster().check(PutCalendarAction.NAME, request), is(false)); - assertThat(role.cluster().check(PutDatafeedAction.NAME, request), is(false)); - assertThat(role.cluster().check(PutFilterAction.NAME, request), is(false)); - assertThat(role.cluster().check(PutJobAction.NAME, request), is(false)); - assertThat(role.cluster().check(RevertModelSnapshotAction.NAME, request), is(false)); - assertThat(role.cluster().check(SetUpgradeModeAction.NAME, request), is(false)); - assertThat(role.cluster().check(StartDatafeedAction.NAME, request), is(false)); - assertThat(role.cluster().check(StopDatafeedAction.NAME, request), is(false)); - assertThat(role.cluster().check(UpdateCalendarJobAction.NAME, request), is(false)); - assertThat(role.cluster().check(UpdateDatafeedAction.NAME, request), is(false)); - assertThat(role.cluster().check(UpdateFilterAction.NAME, request), is(false)); - assertThat(role.cluster().check(UpdateJobAction.NAME, request), is(false)); - assertThat(role.cluster().check(UpdateModelSnapshotAction.NAME, request), is(false)); - assertThat(role.cluster().check(UpdateProcessAction.NAME, request), is(false)); - assertThat(role.cluster().check(ValidateDetectorAction.NAME, request), is(false)); - assertThat(role.cluster().check(ValidateJobConfigAction.NAME, request), is(false)); + assertThat(role.cluster().check(CloseJobAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(DeleteCalendarAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(DeleteCalendarEventAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(DeleteDatafeedAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(DeleteExpiredDataAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(DeleteFilterAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(DeleteForecastAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(DeleteJobAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(DeleteModelSnapshotAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(FinalizeJobExecutionAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(FindFileStructureAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(FlushJobAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(ForecastJobAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(GetBucketsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetCalendarEventsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetCalendarsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetCategoriesAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetDatafeedsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetDatafeedsStatsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetFiltersAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(GetInfluencersAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetJobsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetJobsStatsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetModelSnapshotsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetOverallBucketsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetRecordsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(IsolateDatafeedAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(KillProcessAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(MlInfoAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(OpenJobAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(PersistJobAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(PostCalendarEventsAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(PostDataAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(PreviewDatafeedAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(PutCalendarAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(PutDatafeedAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(PutFilterAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(PutJobAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(RevertModelSnapshotAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(SetUpgradeModeAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(StartDatafeedAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(StopDatafeedAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(UpdateCalendarJobAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(UpdateDatafeedAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(UpdateFilterAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(UpdateJobAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(UpdateModelSnapshotAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(UpdateProcessAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(ValidateDetectorAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(ValidateJobConfigAction.NAME, request, authentication), is(false)); assertThat(role.runAs().check(randomAlphaOfLengthBetween(1, 30)), is(false)); assertNoAccessAllowed(role, "foo"); @@ -1079,19 +1096,20 @@ public void testMachineLearningUserRole() { public void testDataFrameTransformsAdminRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("data_frame_transforms_admin"); assertNotNull(roleDescriptor); assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); Role role = Role.builder(roleDescriptor, null).build(); - assertThat(role.cluster().check(DeleteDataFrameTransformAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetDataFrameTransformsAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetDataFrameTransformsStatsAction.NAME, request), is(true)); - assertThat(role.cluster().check(PreviewDataFrameTransformAction.NAME, request), is(true)); - assertThat(role.cluster().check(PutDataFrameTransformAction.NAME, request), is(true)); - assertThat(role.cluster().check(StartDataFrameTransformAction.NAME, request), is(true)); - assertThat(role.cluster().check(StopDataFrameTransformAction.NAME, request), is(true)); + assertThat(role.cluster().check(DeleteDataFrameTransformAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetDataFrameTransformsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetDataFrameTransformsStatsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(PreviewDataFrameTransformAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(PutDataFrameTransformAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(StartDataFrameTransformAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(StopDataFrameTransformAction.NAME, request, authentication), is(true)); assertThat(role.runAs().check(randomAlphaOfLengthBetween(1, 30)), is(false)); assertOnlyReadAllowed(role, ".data-frame-notifications-1"); @@ -1115,19 +1133,20 @@ public void testDataFrameTransformsAdminRole() { public void testDataFrameTransformsUserRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("data_frame_transforms_user"); assertNotNull(roleDescriptor); assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); Role role = Role.builder(roleDescriptor, null).build(); - assertThat(role.cluster().check(DeleteDataFrameTransformAction.NAME, request), is(false)); - assertThat(role.cluster().check(GetDataFrameTransformsAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetDataFrameTransformsStatsAction.NAME, request), is(true)); - assertThat(role.cluster().check(PreviewDataFrameTransformAction.NAME, request), is(false)); - assertThat(role.cluster().check(PutDataFrameTransformAction.NAME, request), is(false)); - assertThat(role.cluster().check(StartDataFrameTransformAction.NAME, request), is(false)); - assertThat(role.cluster().check(StopDataFrameTransformAction.NAME, request), is(false)); + assertThat(role.cluster().check(DeleteDataFrameTransformAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(GetDataFrameTransformsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetDataFrameTransformsStatsAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(PreviewDataFrameTransformAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(PutDataFrameTransformAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(StartDataFrameTransformAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(StopDataFrameTransformAction.NAME, request, authentication), is(false)); assertThat(role.runAs().check(randomAlphaOfLengthBetween(1, 30)), is(false)); assertOnlyReadAllowed(role, ".data-frame-notifications-1"); @@ -1151,20 +1170,21 @@ public void testDataFrameTransformsUserRole() { public void testWatcherAdminRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("watcher_admin"); assertNotNull(roleDescriptor); assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); Role role = Role.builder(roleDescriptor, null).build(); - assertThat(role.cluster().check(PutWatchAction.NAME, request), is(true)); - assertThat(role.cluster().check(GetWatchAction.NAME, request), is(true)); - assertThat(role.cluster().check(DeleteWatchAction.NAME, request), is(true)); - assertThat(role.cluster().check(ExecuteWatchAction.NAME, request), is(true)); - assertThat(role.cluster().check(AckWatchAction.NAME, request), is(true)); - assertThat(role.cluster().check(ActivateWatchAction.NAME, request), is(true)); - assertThat(role.cluster().check(WatcherServiceAction.NAME, request), is(true)); - assertThat(role.cluster().check(WatcherStatsAction.NAME, request), is(true)); + assertThat(role.cluster().check(PutWatchAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(GetWatchAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(DeleteWatchAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(ExecuteWatchAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(AckWatchAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(ActivateWatchAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(WatcherServiceAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(WatcherStatsAction.NAME, request, authentication), is(true)); assertThat(role.runAs().check(randomAlphaOfLengthBetween(1, 30)), is(false)); assertThat(role.indices().allowedIndicesMatcher(IndexAction.NAME).test("foo"), is(false)); @@ -1180,20 +1200,21 @@ public void testWatcherAdminRole() { public void testWatcherUserRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("watcher_user"); assertNotNull(roleDescriptor); assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); Role role = Role.builder(roleDescriptor, null).build(); - assertThat(role.cluster().check(PutWatchAction.NAME, request), is(false)); - assertThat(role.cluster().check(GetWatchAction.NAME, request), is(true)); - assertThat(role.cluster().check(DeleteWatchAction.NAME, request), is(false)); - assertThat(role.cluster().check(ExecuteWatchAction.NAME, request), is(false)); - assertThat(role.cluster().check(AckWatchAction.NAME, request), is(false)); - assertThat(role.cluster().check(ActivateWatchAction.NAME, request), is(false)); - assertThat(role.cluster().check(WatcherServiceAction.NAME, request), is(false)); - assertThat(role.cluster().check(WatcherStatsAction.NAME, request), is(true)); + assertThat(role.cluster().check(PutWatchAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(GetWatchAction.NAME, request, authentication), is(true)); + assertThat(role.cluster().check(DeleteWatchAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(ExecuteWatchAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(AckWatchAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(ActivateWatchAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(WatcherServiceAction.NAME, request, authentication), is(false)); + assertThat(role.cluster().check(WatcherStatsAction.NAME, request, authentication), is(true)); assertThat(role.runAs().check(randomAlphaOfLengthBetween(1, 30)), is(false)); assertThat(role.indices().allowedIndicesMatcher(IndexAction.NAME).test("foo"), is(false)); @@ -1252,16 +1273,17 @@ private void assertNoAccessAllowed(Role role, String index) { public void testLogstashAdminRole() { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); RoleDescriptor roleDescriptor = new ReservedRolesStore().roleDescriptor("logstash_admin"); assertNotNull(roleDescriptor); assertThat(roleDescriptor.getMetadata(), hasEntry("_reserved", true)); Role logstashAdminRole = Role.builder(roleDescriptor, null).build(); - assertThat(logstashAdminRole.cluster().check(ClusterHealthAction.NAME, request), is(false)); - assertThat(logstashAdminRole.cluster().check(PutIndexTemplateAction.NAME, request), is(false)); - assertThat(logstashAdminRole.cluster().check(ClusterRerouteAction.NAME, request), is(false)); - assertThat(logstashAdminRole.cluster().check(ClusterUpdateSettingsAction.NAME, request), is(false)); + assertThat(logstashAdminRole.cluster().check(ClusterHealthAction.NAME, request, authentication), is(false)); + assertThat(logstashAdminRole.cluster().check(PutIndexTemplateAction.NAME, request, authentication), is(false)); + assertThat(logstashAdminRole.cluster().check(ClusterRerouteAction.NAME, request, authentication), is(false)); + assertThat(logstashAdminRole.cluster().check(ClusterUpdateSettingsAction.NAME, request, authentication), is(false)); assertThat(logstashAdminRole.runAs().check(randomAlphaOfLengthBetween(1, 30)), is(false)); diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/RBACEngine.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/RBACEngine.java index df00474f6d69d..78ff3140871c3 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/RBACEngine.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/RBACEngine.java @@ -137,7 +137,7 @@ public void authorizeClusterAction(RequestInfo requestInfo, AuthorizationInfo au ActionListener<AuthorizationResult> listener) { if (authorizationInfo instanceof RBACAuthorizationInfo) { final Role role = ((RBACAuthorizationInfo) authorizationInfo).getRole(); - if (role.checkClusterAction(requestInfo.getAction(), requestInfo.getRequest())) { + if (role.checkClusterAction(requestInfo.getAction(), requestInfo.getRequest(), requestInfo.getAuthentication())) { listener.onResponse(AuthorizationResult.granted()); } else if (checkSameUserPermissions(requestInfo.getAction(), requestInfo.getRequest(), requestInfo.getAuthentication())) { listener.onResponse(AuthorizationResult.granted()); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmIntegTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmIntegTests.java index 36c9b79538272..64d6cfd938f81 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmIntegTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmIntegTests.java @@ -49,6 +49,7 @@ import org.elasticsearch.xpack.core.security.action.user.GetUsersResponse; import org.elasticsearch.xpack.core.security.action.user.PutUserRequestBuilder; import org.elasticsearch.xpack.core.security.action.user.SetEnabledRequestBuilder; +import org.elasticsearch.xpack.core.security.authc.Authentication; import org.elasticsearch.xpack.core.security.authc.support.Hasher; import org.elasticsearch.xpack.core.security.authz.RoleDescriptor; import org.elasticsearch.xpack.core.security.authz.permission.Role; @@ -369,10 +370,11 @@ public void testCreateAndUpdateRole() { } } else { final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); GetRolesResponse getRolesResponse = new GetRolesRequestBuilder(client()).names("test_role").get(); assertTrue("test_role does not exist!", getRolesResponse.hasRoles()); assertTrue("any cluster permission should be authorized", - Role.builder(getRolesResponse.roles()[0], null).build().cluster().check("cluster:admin/foo", request)); + Role.builder(getRolesResponse.roles()[0], null).build().cluster().check("cluster:admin/foo", request, authentication)); preparePutRole("test_role") .cluster("none") @@ -383,7 +385,7 @@ public void testCreateAndUpdateRole() { assertTrue("test_role does not exist!", getRolesResponse.hasRoles()); assertFalse("no cluster permission should be authorized", - Role.builder(getRolesResponse.roles()[0], null).build().cluster().check("cluster:admin/bar", request)); + Role.builder(getRolesResponse.roles()[0], null).build().cluster().check("cluster:admin/bar", request, authentication)); } } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java index d7f3252dd95a5..89c68fec5e281 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java @@ -151,6 +151,7 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.CountDownLatch; +import java.util.function.BiPredicate; import java.util.function.Predicate; import static java.util.Arrays.asList; @@ -320,7 +321,7 @@ public void testAuthorizeUsingConditionalPrivileges() throws IOException { final ConfigurableClusterPrivilege configurableClusterPrivilege = new MockConfigurableClusterPrivilege() { @Override public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { - final Predicate<TransportRequest> requestPredicate = r -> r == request; + final BiPredicate<TransportRequest, Authentication> requestPredicate = (r,a) -> r == request; final Predicate<String> actionPredicate = Automatons.predicate(((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns()); builder.add(this, actionPredicate, requestPredicate); @@ -347,7 +348,7 @@ public void testAuthorizationDeniedWhenConditionalPrivilegesDoNotMatch() throws final ConfigurableClusterPrivilege configurableClusterPrivilege = new MockConfigurableClusterPrivilege() { @Override public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { - final Predicate<TransportRequest> requestPredicate = r -> false; + final BiPredicate<TransportRequest, Authentication> requestPredicate = (r,a) -> false; final Predicate<String> actionPredicate = Automatons.predicate(((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns()); builder.add(this, actionPredicate,requestPredicate); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java index 4ab525a43da2f..ffe76d3475650 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java @@ -546,13 +546,14 @@ public void testMergingBasicRoles() { final TransportRequest request1 = mock(TransportRequest.class); final TransportRequest request2 = mock(TransportRequest.class); final TransportRequest request3 = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); ConfigurableClusterPrivilege ccp1 = new MockConfigurableClusterPrivilege() { @Override public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { Predicate<String> predicate1 = Automatons.predicate(((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns()); - builder.add(this, predicate1, req -> req == request1); + builder.add(this, predicate1, (req, authn) -> req == request1); return builder; } }; @@ -584,7 +585,7 @@ public ClusterPermission.Builder buildPermission(ClusterPermission.Builder build public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { Predicate<String> predicate2 = Automatons.predicate(((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns()); - builder.add(this, predicate2, req -> req == request2); + builder.add(this, predicate2, (req, authn) -> req == request2); return builder; } }; @@ -626,12 +627,14 @@ public ClusterPermission.Builder buildPermission(ClusterPermission.Builder build CompositeRolesStore.buildRoleFromDescriptors(Sets.newHashSet(role1, role2), cache, privilegeStore, future); Role role = future.actionGet(); - assertThat(role.cluster().check(ClusterStateAction.NAME, randomFrom(request1, request2, request3)), equalTo(true)); - assertThat(role.cluster().check(SamlAuthenticateAction.NAME, randomFrom(request1, request2, request3)), equalTo(true)); - assertThat(role.cluster().check(ClusterUpdateSettingsAction.NAME, randomFrom(request1, request2, request3)), equalTo(false)); + assertThat(role.cluster().check(ClusterStateAction.NAME, randomFrom(request1, request2, request3), authentication), equalTo(true)); + assertThat(role.cluster().check(SamlAuthenticateAction.NAME, randomFrom(request1, request2, request3), authentication), + equalTo(true)); + assertThat(role.cluster().check(ClusterUpdateSettingsAction.NAME, randomFrom(request1, request2, request3), authentication), + equalTo(false)); - assertThat(role.cluster().check(PutUserAction.NAME, randomFrom(request1, request2)), equalTo(true)); - assertThat(role.cluster().check(PutUserAction.NAME, request3), equalTo(false)); + assertThat(role.cluster().check(PutUserAction.NAME, randomFrom(request1, request2), authentication), equalTo(true)); + assertThat(role.cluster().check(PutUserAction.NAME, request3, authentication), equalTo(false)); final Predicate<String> allowedRead = role.indices().allowedIndicesMatcher(GetAction.NAME); assertThat(allowedRead.test("abc-123"), equalTo(true)); @@ -1076,7 +1079,7 @@ public void testApiKeyAuthUsesApiKeyServiceWithScopedRole() throws IOException { PlainActionFuture<Role> roleFuture = new PlainActionFuture<>(); compositeRolesStore.getRoles(authentication.getUser(), authentication, roleFuture); Role role = roleFuture.actionGet(); - assertThat(role.checkClusterAction("cluster:admin/foo", Empty.INSTANCE), is(false)); + assertThat(role.checkClusterAction("cluster:admin/foo", Empty.INSTANCE, mock(Authentication.class)), is(false)); assertThat(effectiveRoleDescriptors.get(), is(nullValue())); verify(apiKeyService).getRoleForApiKey(eq(authentication), any(ActionListener.class)); } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/FileRolesStoreTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/FileRolesStoreTests.java index 6555dbd882377..3a2c30891008e 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/FileRolesStoreTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/FileRolesStoreTests.java @@ -20,6 +20,7 @@ import org.elasticsearch.watcher.ResourceWatcherService; import org.elasticsearch.xpack.core.XPackSettings; import org.elasticsearch.xpack.core.security.audit.logfile.CapturingLogger; +import org.elasticsearch.xpack.core.security.authc.Authentication; import org.elasticsearch.xpack.core.security.authz.RoleDescriptor; import org.elasticsearch.xpack.core.security.authz.permission.ClusterPermission; import org.elasticsearch.xpack.core.security.authz.permission.IndicesPermission; @@ -351,14 +352,15 @@ public void testAutoReload() throws Exception { assertEquals(1, modifiedRoles.size()); assertTrue(modifiedRoles.contains("role5")); final TransportRequest request = mock(TransportRequest.class); + final Authentication authentication = mock(Authentication.class); descriptors = store.roleDescriptors(Collections.singleton("role5")); assertThat(descriptors, notNullValue()); assertEquals(1, descriptors.size()); Role role = Role.builder(descriptors.iterator().next(), null).build(); assertThat(role, notNullValue()); assertThat(role.names(), equalTo(new String[] { "role5" })); - assertThat(role.cluster().check("cluster:monitor/foo/bar", request), is(true)); - assertThat(role.cluster().check("cluster:admin/foo/bar", request), is(false)); + assertThat(role.cluster().check("cluster:monitor/foo/bar", request, authentication), is(true)); + assertThat(role.cluster().check("cluster:admin/foo/bar", request, authentication), is(false)); // truncate to remove some final Set<String> truncatedFileRolesModified = new HashSet<>(); From 1af13084f969b205635647ba89f5f21d762612a6 Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad <yogesh.gaikwad@elastic.co> Date: Tue, 20 Aug 2019 13:36:06 +1000 Subject: [PATCH 2/9] address review comments The permission checks that are dependent on actions and optionally on request and/or on authentication, now have a way to specify the predicates. By default the implementation will tests all the predicates to be successful for the operation to be allowed. In case customization is required one has option to implement `PermissionCheck`. - Adds a permission check predicate interface that also allows implementers to specify behavior for `implies`. --- .../authz/permission/ClusterPermission.java | 84 ++++++++++---- .../ConfigurableClusterPrivileges.java | 55 ++++++--- .../permission/ClusterPermissionTests.java | 105 ++++-------------- .../authz/AuthorizationServiceTests.java | 35 ++++-- .../authz/store/CompositeRolesStoreTests.java | 33 ++++-- 5 files changed, 171 insertions(+), 141 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java index 738ff0c895520..76e00723f0e0d 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java @@ -16,7 +16,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.function.BiPredicate; import java.util.function.Predicate; /** @@ -93,10 +92,21 @@ public Builder add(final ClusterPrivilege clusterPrivilege, final Set<String> al return this; } - public Builder add(final ClusterPrivilege clusterPrivilege, final Predicate<String> actionPredicate, - final BiPredicate<TransportRequest, Authentication> requestAuthnPredicate) { - return add(clusterPrivilege, new ActionRequestAuthenticationPredicatePermissionCheck(clusterPrivilege, - actionPredicate, requestAuthnPredicate)); + public Builder add(final ClusterPrivilege clusterPrivilege, final Set<String> allowedActionPatterns, + final Set<String> excludeActionPatterns, final PermissionCheckPredicate<TransportRequest> requestPredicate) { + return add(clusterPrivilege, allowedActionPatterns, excludeActionPatterns, requestPredicate, + new AllowAllPermissionCheckPredicate()); + } + + public Builder add(final ClusterPrivilege clusterPrivilege, final Set<String> allowedActionPatterns, + final Set<String> excludeActionPatterns, final PermissionCheckPredicate<TransportRequest> requestPredicate, + final PermissionCheckPredicate<Authentication> authenticationPredicate) { + final Automaton allowedAutomaton = Automatons.patterns(allowedActionPatterns); + final Automaton excludedAutomaton = Automatons.patterns(excludeActionPatterns); + final Automaton actionAutomaton = Automatons.minusAndMinimize(allowedAutomaton, excludedAutomaton); + + return add(clusterPrivilege, new ActionRequestAuthenticationBasedPermissionCheck(actionAutomaton, requestPredicate, + authenticationPredicate)); } public Builder add(final ClusterPrivilege clusterPrivilege, final PermissionCheck permissionCheck) { @@ -120,6 +130,35 @@ public ClusterPermission build() { } } + /** + * A {@link Predicate} which also can determine if the other {@link PermissionCheckPredicate} + * is implied by it. + */ + public interface PermissionCheckPredicate<T> extends Predicate<T> { + /** + * Checks whether specified {@link PermissionCheckPredicate} is implied by this {@link PermissionCheckPredicate}.<br> + * This is important method to be considered during implementation as it compares {@link PermissionCheckPredicate}s. + * If {@code permissionCheckPredicate.implies(otherPermissionCheckPredicate)}, that means all the operations allowed + * by {@code otherPermissionCheckPredicate} are also allowed by {@code permissionCheckPredicate}. + * + * @param otherPermissionCheckPredicate {@link PermissionCheckPredicate} + * @return {@code true} if the specified permission check predicate is implied by this + * {@link PermissionCheckPredicate} else returns {@code false} + */ + boolean implies(PermissionCheckPredicate<T> otherPermissionCheckPredicate); + } + + private static final class AllowAllPermissionCheckPredicate<T> implements PermissionCheckPredicate<T> { + @Override + public boolean implies(PermissionCheckPredicate<T> otherPermissionCheckPredicate) { + return true; + } + @Override + public boolean test(T t) { + return true; + } + } + /** * Evaluates whether the cluster actions (optionally for a given request) * is permitted by this permission. @@ -174,30 +213,33 @@ public boolean implies(final PermissionCheck permissionCheck) { } // action, request and authentication based permission check - private static class ActionRequestAuthenticationPredicatePermissionCheck implements PermissionCheck { - private final ClusterPrivilege clusterPrivilege; - final Predicate<String> actionPredicate; - final BiPredicate<TransportRequest, Authentication> requestAuthnPredicate; - - ActionRequestAuthenticationPredicatePermissionCheck(final ClusterPrivilege clusterPrivilege, - final Predicate<String> actionPredicate, - final BiPredicate<TransportRequest, Authentication> requestAuthnPredicate) { - this.clusterPrivilege = clusterPrivilege; - this.actionPredicate = actionPredicate; - this.requestAuthnPredicate = requestAuthnPredicate; + private static class ActionRequestAuthenticationBasedPermissionCheck extends AutomatonPermissionCheck { + private final PermissionCheckPredicate<TransportRequest> requestPredicate; + private final PermissionCheckPredicate<Authentication> authenticationPredicate; + + ActionRequestAuthenticationBasedPermissionCheck(final Automaton automaton, + final PermissionCheckPredicate<TransportRequest> requestPredicate, + final PermissionCheckPredicate<Authentication> authenticationPredicate) { + super(automaton); + this.requestPredicate = requestPredicate; + this.authenticationPredicate = authenticationPredicate; } @Override public boolean check(final String action, final TransportRequest request, final Authentication authentication) { - return actionPredicate.test(action) && requestAuthnPredicate.test(request, authentication); + return super.check(action, request, authentication) && requestPredicate.test(request) && authenticationPredicate.test( + authentication); } @Override public boolean implies(final PermissionCheck permissionCheck) { - if (permissionCheck instanceof ActionRequestAuthenticationPredicatePermissionCheck) { - final ActionRequestAuthenticationPredicatePermissionCheck otherCheck = - (ActionRequestAuthenticationPredicatePermissionCheck) permissionCheck; - return this.clusterPrivilege.equals(otherCheck.clusterPrivilege); + if (super.implies(permissionCheck)) { + if (permissionCheck instanceof ActionRequestAuthenticationBasedPermissionCheck) { + final ActionRequestAuthenticationBasedPermissionCheck otherCheck = + (ActionRequestAuthenticationBasedPermissionCheck) permissionCheck; + return this.requestPredicate.implies(otherCheck.requestPredicate) && + this.authenticationPredicate.implies(otherCheck.authenticationPredicate); + } } return false; } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ConfigurableClusterPrivileges.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ConfigurableClusterPrivileges.java index 68cdfc3d1f836..b98654787e682 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ConfigurableClusterPrivileges.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ConfigurableClusterPrivileges.java @@ -6,6 +6,8 @@ package org.elasticsearch.xpack.core.security.authz.privilege; +import org.apache.lucene.util.automaton.Automaton; +import org.apache.lucene.util.automaton.Operations; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.Strings; import org.elasticsearch.common.io.stream.StreamInput; @@ -15,9 +17,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParseException; import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.transport.TransportRequest; import org.elasticsearch.xpack.core.security.action.privilege.ApplicationPrivilegesRequest; -import org.elasticsearch.xpack.core.security.authc.Authentication; import org.elasticsearch.xpack.core.security.authz.permission.ClusterPermission; import org.elasticsearch.xpack.core.security.authz.privilege.ConfigurableClusterPrivilege.Category; import org.elasticsearch.xpack.core.security.support.Automatons; @@ -31,7 +31,6 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Set; -import java.util.function.BiPredicate; import java.util.function.Predicate; /** @@ -127,26 +126,12 @@ private static void expectFieldName(XContentParser parser, ParseField... fields) * of applications (identified by a wildcard-aware application-name). */ public static class ManageApplicationPrivileges implements ConfigurableClusterPrivilege { - - private static final Predicate<String> ACTION_PREDICATE = Automatons.predicate("cluster:admin/xpack/security/privilege/*"); public static final String WRITEABLE_NAME = "manage-application-privileges"; private final Set<String> applicationNames; - private final Predicate<String> applicationPredicate; - private final BiPredicate<TransportRequest, Authentication> requestAuthnPredicate; public ManageApplicationPrivileges(Set<String> applicationNames) { this.applicationNames = Collections.unmodifiableSet(applicationNames); - this.applicationPredicate = Automatons.predicate(applicationNames); - this.requestAuthnPredicate = (request, authn) -> { - if (request instanceof ApplicationPrivilegesRequest) { - final ApplicationPrivilegesRequest privRequest = (ApplicationPrivilegesRequest) request; - final Collection<String> requestApplicationNames = privRequest.getApplicationNames(); - return requestApplicationNames.isEmpty() ? this.applicationNames.contains("*") - : requestApplicationNames.stream().allMatch(application -> applicationPredicate.test(application)); - } - return false; - }; } @Override @@ -217,12 +202,46 @@ public int hashCode() { @Override public ClusterPermission.Builder buildPermission(final ClusterPermission.Builder builder) { - return builder.add(this, ACTION_PREDICATE, requestAuthnPredicate); + return builder.add(this, Set.of("cluster:admin/xpack/security/privilege/*"), Set.of(), + new RequestPermissionCheckPredicate(applicationNames)); } private interface Fields { ParseField MANAGE = new ParseField("manage"); ParseField APPLICATIONS = new ParseField("applications"); } + + private static class RequestPermissionCheckPredicate<TransportRequest> + implements ClusterPermission.PermissionCheckPredicate<TransportRequest> { + private final Automaton applicationNamesAutomaton; + private final Set<String> applicationNames; + private final Predicate<String> applicationPredicate; + + RequestPermissionCheckPredicate(Set<String> applicationNames) { + this.applicationNamesAutomaton = Automatons.patterns(applicationNames); + this.applicationNames = applicationNames; + this.applicationPredicate = Automatons.predicate(applicationNamesAutomaton); + } + + @Override + public boolean implies(ClusterPermission.PermissionCheckPredicate<TransportRequest> otherPermissionCheckPredicate) { + if (otherPermissionCheckPredicate instanceof RequestPermissionCheckPredicate) { + return Operations.subsetOf(((RequestPermissionCheckPredicate) otherPermissionCheckPredicate).applicationNamesAutomaton, + this.applicationNamesAutomaton); + } + return false; + } + + @Override + public boolean test(TransportRequest transportRequest) { + if (transportRequest instanceof ApplicationPrivilegesRequest) { + final ApplicationPrivilegesRequest privRequest = (ApplicationPrivilegesRequest) transportRequest; + final Collection<String> requestApplicationNames = privRequest.getApplicationNames(); + return requestApplicationNames.isEmpty() ? this.applicationNames.contains("*") + : requestApplicationNames.stream().allMatch(application -> applicationPredicate.test(application)); + } + return false; + } + } } } diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermissionTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermissionTests.java index 4fe368f5e33a1..a28931b060f14 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermissionTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermissionTests.java @@ -8,22 +8,15 @@ package org.elasticsearch.xpack.core.security.authz.permission; -import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.transport.TransportRequest; import org.elasticsearch.xpack.core.security.authc.Authentication; import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilege; import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilegeResolver; -import org.elasticsearch.xpack.core.security.authz.privilege.ConfigurableClusterPrivilege; -import org.elasticsearch.xpack.core.security.support.Automatons; +import org.elasticsearch.xpack.core.security.authz.privilege.ConfigurableClusterPrivileges; import org.junit.Before; -import java.io.IOException; -import java.util.Objects; import java.util.Set; -import java.util.function.BiPredicate; -import java.util.function.Predicate; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.is; @@ -52,10 +45,10 @@ public void testClusterPermissionBuilder() { builder = ClusterPrivilegeResolver.MANAGE_SECURITY.buildPermission(builder); builder = ClusterPrivilegeResolver.MANAGE_ILM.buildPermission(builder); - final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege1 = - new MockConfigurableClusterPrivilege((r,a) -> r == mockTransportRequest); - final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege2 = - new MockConfigurableClusterPrivilege((r,a) -> false); + final ConfigurableClusterPrivileges.ManageApplicationPrivileges mockConfigurableClusterPrivilege1 = + new ConfigurableClusterPrivileges.ManageApplicationPrivileges(Set.of("application-1")); + final ConfigurableClusterPrivileges.ManageApplicationPrivileges mockConfigurableClusterPrivilege2 = + new ConfigurableClusterPrivileges.ManageApplicationPrivileges(Set.of("application-1", "application-2")); builder = mockConfigurableClusterPrivilege1.buildPermission(builder); builder = mockConfigurableClusterPrivilege2.buildPermission(builder); final ClusterPermission clusterPermission = builder.build(); @@ -74,10 +67,10 @@ public void testClusterPermissionCheck() { builder = ClusterPrivilegeResolver.MANAGE_SECURITY.buildPermission(builder); builder = ClusterPrivilegeResolver.MANAGE_ILM.buildPermission(builder); - final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege1 = - new MockConfigurableClusterPrivilege((r,a) -> r == mockTransportRequest && a == mockAuthentication); - final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege2 = - new MockConfigurableClusterPrivilege((r,a) -> false); + final ConfigurableClusterPrivileges.ManageApplicationPrivileges mockConfigurableClusterPrivilege1 = + new ConfigurableClusterPrivileges.ManageApplicationPrivileges(Set.of("application-1")); + final ConfigurableClusterPrivileges.ManageApplicationPrivileges mockConfigurableClusterPrivilege2 = + new ConfigurableClusterPrivileges.ManageApplicationPrivileges(Set.of("application-1", "application-2")); builder = mockConfigurableClusterPrivilege1.buildPermission(builder); builder = mockConfigurableClusterPrivilege2.buildPermission(builder); final ClusterPermission clusterPermission = builder.build(); @@ -138,10 +131,10 @@ public void testNoneClusterPermissionIsImpliedByAny() { ClusterPermission.Builder builder = ClusterPermission.builder(); builder = ClusterPrivilegeResolver.MANAGE_SECURITY.buildPermission(builder); builder = ClusterPrivilegeResolver.MANAGE_ILM.buildPermission(builder); - final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege1 = - new MockConfigurableClusterPrivilege((r,a) -> r == mockTransportRequest && a == mockAuthentication); - final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege2 = - new MockConfigurableClusterPrivilege((r,a) -> false); + final ConfigurableClusterPrivileges.ManageApplicationPrivileges mockConfigurableClusterPrivilege1 = + new ConfigurableClusterPrivileges.ManageApplicationPrivileges(Set.of("application-1")); + final ConfigurableClusterPrivileges.ManageApplicationPrivileges mockConfigurableClusterPrivilege2 = + new ConfigurableClusterPrivileges.ManageApplicationPrivileges(Set.of("application-1", "application-2")); builder = mockConfigurableClusterPrivilege1.buildPermission(builder); builder = mockConfigurableClusterPrivilege2.buildPermission(builder); final ClusterPermission clusterPermission = builder.build(); @@ -153,8 +146,8 @@ public void testClusterPermissionSubsetWithConfigurableClusterPrivilegeIsImplied ClusterPermission.Builder builder = ClusterPermission.builder(); builder = ClusterPrivilegeResolver.MANAGE_ML.buildPermission(builder); builder = ClusterPrivilegeResolver.MANAGE_ILM.buildPermission(builder); - final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege1 = - new MockConfigurableClusterPrivilege((r,a) -> r == mockTransportRequest && a == mockAuthentication); + final ConfigurableClusterPrivileges.ManageApplicationPrivileges mockConfigurableClusterPrivilege1 = + new ConfigurableClusterPrivileges.ManageApplicationPrivileges(Set.of("application-1")); builder = mockConfigurableClusterPrivilege1.buildPermission(builder); final ClusterPermission clusterPermission = builder.build(); @@ -170,16 +163,16 @@ public void testClusterPermissionNonSubsetWithConfigurableClusterPrivilegeIsImpl ClusterPermission.Builder builder = ClusterPermission.builder(); builder = ClusterPrivilegeResolver.MANAGE_ML.buildPermission(builder); builder = ClusterPrivilegeResolver.MANAGE_ILM.buildPermission(builder); - final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege1 = - new MockConfigurableClusterPrivilege((r,a) -> r == mockTransportRequest && a == mockAuthentication); + final ConfigurableClusterPrivileges.ManageApplicationPrivileges mockConfigurableClusterPrivilege1 = + new ConfigurableClusterPrivileges.ManageApplicationPrivileges(Set.of("application-1")); builder = mockConfigurableClusterPrivilege1.buildPermission(builder); final ClusterPermission clusterPermission = builder.build(); ClusterPermission.Builder builder1 = ClusterPermission.builder(); builder1 = ClusterPrivilegeResolver.MANAGE_ML.buildPermission(builder1); builder1 = mockConfigurableClusterPrivilege1.buildPermission(builder1); - final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege2 = - new MockConfigurableClusterPrivilege((r,a) -> false); + final ConfigurableClusterPrivileges.ManageApplicationPrivileges mockConfigurableClusterPrivilege2 = + new ConfigurableClusterPrivileges.ManageApplicationPrivileges(Set.of("application-1", "application-2")); builder1 = mockConfigurableClusterPrivilege2.buildPermission(builder1); final ClusterPermission otherClusterPermission = builder1.build(); @@ -216,8 +209,8 @@ public void testClusterPermissionIsImpliedBySameClusterPermission() { ClusterPermission.Builder builder = ClusterPermission.builder(); builder = ClusterPrivilegeResolver.MANAGE_ML.buildPermission(builder); builder = ClusterPrivilegeResolver.MANAGE_ILM.buildPermission(builder); - final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege1 = - new MockConfigurableClusterPrivilege((r,a) -> r == mockTransportRequest && a == mockAuthentication); + final ConfigurableClusterPrivileges.ManageApplicationPrivileges mockConfigurableClusterPrivilege1 = + new ConfigurableClusterPrivileges.ManageApplicationPrivileges(Set.of("application-1")); builder = mockConfigurableClusterPrivilege1.buildPermission(builder); final ClusterPermission clusterPermission = builder.build(); @@ -232,60 +225,4 @@ public void testClusterPermissionSubsetIsImpliedByAllClusterPermission() { assertThat(allClusterPermission.implies(otherClusterPermission), is(true)); } - private static class MockConfigurableClusterPrivilege implements ConfigurableClusterPrivilege { - static final Predicate<String> ACTION_PREDICATE = Automatons.predicate("cluster:admin/xpack/security/privilege/*"); - private BiPredicate<TransportRequest, Authentication> requestAuthnPredicate; - - MockConfigurableClusterPrivilege(BiPredicate<TransportRequest, Authentication> requestPredicate) { - this.requestAuthnPredicate = requestPredicate; - } - - @Override - public Category getCategory() { - return Category.APPLICATION; - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - return builder; - } - - @Override - public String getWriteableName() { - return "mock-ccp"; - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - final MockConfigurableClusterPrivilege that = (MockConfigurableClusterPrivilege) o; - return requestAuthnPredicate.equals(that.requestAuthnPredicate); - } - - @Override - public int hashCode() { - return Objects.hash(requestAuthnPredicate); - } - - @Override - public String toString() { - return "MockConfigurableClusterPrivilege{" + - "requestAuthnPredicate=" + requestAuthnPredicate + - '}'; - } - - @Override - public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { - return builder.add(this, ACTION_PREDICATE, requestAuthnPredicate); - } - } } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java index 89c68fec5e281..0bb076332d689 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java @@ -119,7 +119,6 @@ import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilegeResolver; import org.elasticsearch.xpack.core.security.authz.privilege.ConfigurableClusterPrivilege; import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore; -import org.elasticsearch.xpack.core.security.support.Automatons; import org.elasticsearch.xpack.core.security.user.AnonymousUser; import org.elasticsearch.xpack.core.security.user.ElasticUser; import org.elasticsearch.xpack.core.security.user.KibanaUser; @@ -151,8 +150,6 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.CountDownLatch; -import java.util.function.BiPredicate; -import java.util.function.Predicate; import static java.util.Arrays.asList; import static org.elasticsearch.test.SecurityTestsUtils.assertAuthenticationException; @@ -321,10 +318,18 @@ public void testAuthorizeUsingConditionalPrivileges() throws IOException { final ConfigurableClusterPrivilege configurableClusterPrivilege = new MockConfigurableClusterPrivilege() { @Override public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { - final BiPredicate<TransportRequest, Authentication> requestPredicate = (r,a) -> r == request; - final Predicate<String> actionPredicate = - Automatons.predicate(((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns()); - builder.add(this, actionPredicate, requestPredicate); + builder.add(this, ((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns(), Set.of(), + new ClusterPermission.PermissionCheckPredicate<TransportRequest>() { + @Override + public boolean implies(ClusterPermission.PermissionCheckPredicate<TransportRequest> otherPermissionCheckPredicate) { + return this.equals(otherPermissionCheckPredicate); + } + + @Override + public boolean test(TransportRequest r) { + return r == request; + } + }); return builder; } }; @@ -348,10 +353,18 @@ public void testAuthorizationDeniedWhenConditionalPrivilegesDoNotMatch() throws final ConfigurableClusterPrivilege configurableClusterPrivilege = new MockConfigurableClusterPrivilege() { @Override public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { - final BiPredicate<TransportRequest, Authentication> requestPredicate = (r,a) -> false; - final Predicate<String> actionPredicate = - Automatons.predicate(((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns()); - builder.add(this, actionPredicate,requestPredicate); + builder.add(this,((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns(), Set.of(), + new ClusterPermission.PermissionCheckPredicate<TransportRequest>() { + @Override + public boolean implies(ClusterPermission.PermissionCheckPredicate<TransportRequest> otherPermissionCheckPredicate) { + return this.equals(otherPermissionCheckPredicate); + } + + @Override + public boolean test(TransportRequest r) { + return false; + } + }); return builder; } }; diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java index ffe76d3475650..d7c84926ecb8c 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java @@ -51,7 +51,6 @@ import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore; import org.elasticsearch.xpack.core.security.authz.store.RoleRetrievalResult; import org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames; -import org.elasticsearch.xpack.core.security.support.Automatons; import org.elasticsearch.xpack.core.security.user.AnonymousUser; import org.elasticsearch.xpack.core.security.user.SystemUser; import org.elasticsearch.xpack.core.security.user.User; @@ -551,9 +550,19 @@ public void testMergingBasicRoles() { ConfigurableClusterPrivilege ccp1 = new MockConfigurableClusterPrivilege() { @Override public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { - Predicate<String> predicate1 = - Automatons.predicate(((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns()); - builder.add(this, predicate1, (req, authn) -> req == request1); + builder.add(this, ((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns(), + Set.of(), new ClusterPermission.PermissionCheckPredicate<TransportRequest>() { + + @Override + public boolean test(TransportRequest r) { + return r == request1; + } + + @Override + public boolean implies(ClusterPermission.PermissionCheckPredicate<TransportRequest> permissionCheckPredicate) { + return this.equals(permissionCheckPredicate); + } + }); return builder; } }; @@ -583,9 +592,19 @@ public ClusterPermission.Builder buildPermission(ClusterPermission.Builder build ConfigurableClusterPrivilege ccp2 = new MockConfigurableClusterPrivilege() { @Override public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { - Predicate<String> predicate2 = - Automatons.predicate(((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns()); - builder.add(this, predicate2, (req, authn) -> req == request2); + builder.add(this, ((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns(), + Set.of(), new ClusterPermission.PermissionCheckPredicate<TransportRequest>() { + + @Override + public boolean test(TransportRequest r) { + return r == request2; + } + + @Override + public boolean implies(ClusterPermission.PermissionCheckPredicate<TransportRequest> permissionCheckPredicate) { + return this.equals(permissionCheckPredicate); + } + }); return builder; } }; From 8896dcd8b8a64168a8bca655aad69777f7568424 Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad <yogesh.gaikwad@elastic.co> Date: Tue, 20 Aug 2019 14:25:07 +1000 Subject: [PATCH 3/9] remove unwanted code --- .../authz/permission/ClusterPermission.java | 44 +++++-------------- 1 file changed, 10 insertions(+), 34 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java index 76e00723f0e0d..34caf46ee885b 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java @@ -94,19 +94,11 @@ public Builder add(final ClusterPrivilege clusterPrivilege, final Set<String> al public Builder add(final ClusterPrivilege clusterPrivilege, final Set<String> allowedActionPatterns, final Set<String> excludeActionPatterns, final PermissionCheckPredicate<TransportRequest> requestPredicate) { - return add(clusterPrivilege, allowedActionPatterns, excludeActionPatterns, requestPredicate, - new AllowAllPermissionCheckPredicate()); - } - - public Builder add(final ClusterPrivilege clusterPrivilege, final Set<String> allowedActionPatterns, - final Set<String> excludeActionPatterns, final PermissionCheckPredicate<TransportRequest> requestPredicate, - final PermissionCheckPredicate<Authentication> authenticationPredicate) { final Automaton allowedAutomaton = Automatons.patterns(allowedActionPatterns); final Automaton excludedAutomaton = Automatons.patterns(excludeActionPatterns); final Automaton actionAutomaton = Automatons.minusAndMinimize(allowedAutomaton, excludedAutomaton); - return add(clusterPrivilege, new ActionRequestAuthenticationBasedPermissionCheck(actionAutomaton, requestPredicate, - authenticationPredicate)); + return add(clusterPrivilege, new ActionRequestBasedPermissionCheck(actionAutomaton, requestPredicate)); } public Builder add(final ClusterPrivilege clusterPrivilege, final PermissionCheck permissionCheck) { @@ -148,17 +140,6 @@ public interface PermissionCheckPredicate<T> extends Predicate<T> { boolean implies(PermissionCheckPredicate<T> otherPermissionCheckPredicate); } - private static final class AllowAllPermissionCheckPredicate<T> implements PermissionCheckPredicate<T> { - @Override - public boolean implies(PermissionCheckPredicate<T> otherPermissionCheckPredicate) { - return true; - } - @Override - public boolean test(T t) { - return true; - } - } - /** * Evaluates whether the cluster actions (optionally for a given request) * is permitted by this permission. @@ -212,33 +193,28 @@ public boolean implies(final PermissionCheck permissionCheck) { } } - // action, request and authentication based permission check - private static class ActionRequestAuthenticationBasedPermissionCheck extends AutomatonPermissionCheck { + // action, request based permission check + private static class ActionRequestBasedPermissionCheck extends AutomatonPermissionCheck { private final PermissionCheckPredicate<TransportRequest> requestPredicate; - private final PermissionCheckPredicate<Authentication> authenticationPredicate; - ActionRequestAuthenticationBasedPermissionCheck(final Automaton automaton, - final PermissionCheckPredicate<TransportRequest> requestPredicate, - final PermissionCheckPredicate<Authentication> authenticationPredicate) { + ActionRequestBasedPermissionCheck(final Automaton automaton, + final PermissionCheckPredicate<TransportRequest> requestPredicate) { super(automaton); this.requestPredicate = requestPredicate; - this.authenticationPredicate = authenticationPredicate; } @Override public boolean check(final String action, final TransportRequest request, final Authentication authentication) { - return super.check(action, request, authentication) && requestPredicate.test(request) && authenticationPredicate.test( - authentication); + return super.check(action, request, authentication) && requestPredicate.test(request); } @Override public boolean implies(final PermissionCheck permissionCheck) { if (super.implies(permissionCheck)) { - if (permissionCheck instanceof ActionRequestAuthenticationBasedPermissionCheck) { - final ActionRequestAuthenticationBasedPermissionCheck otherCheck = - (ActionRequestAuthenticationBasedPermissionCheck) permissionCheck; - return this.requestPredicate.implies(otherCheck.requestPredicate) && - this.authenticationPredicate.implies(otherCheck.authenticationPredicate); + if (permissionCheck instanceof ActionRequestBasedPermissionCheck) { + final ActionRequestBasedPermissionCheck otherCheck = + (ActionRequestBasedPermissionCheck) permissionCheck; + return this.requestPredicate.implies(otherCheck.requestPredicate); } } return false; From 4976d7828c3224b731d3856e957efc8955eee8cc Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad <yogesh.gaikwad@elastic.co> Date: Tue, 20 Aug 2019 15:51:00 +1000 Subject: [PATCH 4/9] remove unwanted code change, raise a separate pr for it --- .../authz/permission/ClusterPermission.java | 32 ++---- .../ConfigurableClusterPrivileges.java | 50 +++------ .../permission/ClusterPermissionTests.java | 102 ++++++++++++++---- 3 files changed, 104 insertions(+), 80 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java index 34caf46ee885b..ec9d9e1014d27 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java @@ -93,12 +93,12 @@ public Builder add(final ClusterPrivilege clusterPrivilege, final Set<String> al } public Builder add(final ClusterPrivilege clusterPrivilege, final Set<String> allowedActionPatterns, - final Set<String> excludeActionPatterns, final PermissionCheckPredicate<TransportRequest> requestPredicate) { + final Set<String> excludeActionPatterns, final Predicate<TransportRequest> requestPredicate) { final Automaton allowedAutomaton = Automatons.patterns(allowedActionPatterns); final Automaton excludedAutomaton = Automatons.patterns(excludeActionPatterns); final Automaton actionAutomaton = Automatons.minusAndMinimize(allowedAutomaton, excludedAutomaton); - return add(clusterPrivilege, new ActionRequestBasedPermissionCheck(actionAutomaton, requestPredicate)); + return add(clusterPrivilege, new ActionRequestBasedPermissionCheck(clusterPrivilege, actionAutomaton, requestPredicate)); } public Builder add(final ClusterPrivilege clusterPrivilege, final PermissionCheck permissionCheck) { @@ -122,24 +122,6 @@ public ClusterPermission build() { } } - /** - * A {@link Predicate} which also can determine if the other {@link PermissionCheckPredicate} - * is implied by it. - */ - public interface PermissionCheckPredicate<T> extends Predicate<T> { - /** - * Checks whether specified {@link PermissionCheckPredicate} is implied by this {@link PermissionCheckPredicate}.<br> - * This is important method to be considered during implementation as it compares {@link PermissionCheckPredicate}s. - * If {@code permissionCheckPredicate.implies(otherPermissionCheckPredicate)}, that means all the operations allowed - * by {@code otherPermissionCheckPredicate} are also allowed by {@code permissionCheckPredicate}. - * - * @param otherPermissionCheckPredicate {@link PermissionCheckPredicate} - * @return {@code true} if the specified permission check predicate is implied by this - * {@link PermissionCheckPredicate} else returns {@code false} - */ - boolean implies(PermissionCheckPredicate<T> otherPermissionCheckPredicate); - } - /** * Evaluates whether the cluster actions (optionally for a given request) * is permitted by this permission. @@ -195,12 +177,14 @@ public boolean implies(final PermissionCheck permissionCheck) { // action, request based permission check private static class ActionRequestBasedPermissionCheck extends AutomatonPermissionCheck { - private final PermissionCheckPredicate<TransportRequest> requestPredicate; + private final ClusterPrivilege clusterPrivilege; + private final Predicate<TransportRequest> requestPredicate; - ActionRequestBasedPermissionCheck(final Automaton automaton, - final PermissionCheckPredicate<TransportRequest> requestPredicate) { + ActionRequestBasedPermissionCheck(ClusterPrivilege clusterPrivilege, final Automaton automaton, + final Predicate<TransportRequest> requestPredicate) { super(automaton); this.requestPredicate = requestPredicate; + this.clusterPrivilege = clusterPrivilege; } @Override @@ -214,7 +198,7 @@ public boolean implies(final PermissionCheck permissionCheck) { if (permissionCheck instanceof ActionRequestBasedPermissionCheck) { final ActionRequestBasedPermissionCheck otherCheck = (ActionRequestBasedPermissionCheck) permissionCheck; - return this.requestPredicate.implies(otherCheck.requestPredicate); + return this.clusterPrivilege.equals(otherCheck.clusterPrivilege); } } return false; diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ConfigurableClusterPrivileges.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ConfigurableClusterPrivileges.java index b98654787e682..8632cda623d4c 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ConfigurableClusterPrivileges.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ConfigurableClusterPrivileges.java @@ -17,6 +17,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParseException; import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.transport.TransportRequest; import org.elasticsearch.xpack.core.security.action.privilege.ApplicationPrivilegesRequest; import org.elasticsearch.xpack.core.security.authz.permission.ClusterPermission; import org.elasticsearch.xpack.core.security.authz.privilege.ConfigurableClusterPrivilege.Category; @@ -129,9 +130,22 @@ public static class ManageApplicationPrivileges implements ConfigurableClusterPr public static final String WRITEABLE_NAME = "manage-application-privileges"; private final Set<String> applicationNames; + private final Predicate<String> applicationPredicate; + private final Predicate<TransportRequest> requestPredicate; public ManageApplicationPrivileges(Set<String> applicationNames) { this.applicationNames = Collections.unmodifiableSet(applicationNames); + this.applicationPredicate = Automatons.predicate(applicationNames); + this.requestPredicate = request -> { + if (request instanceof ApplicationPrivilegesRequest) { + final ApplicationPrivilegesRequest privRequest = (ApplicationPrivilegesRequest) request; + final Collection<String> requestApplicationNames = privRequest.getApplicationNames(); + return requestApplicationNames.isEmpty() ? this.applicationNames.contains("*") + : requestApplicationNames.stream().allMatch(application -> applicationPredicate.test(application)); + } + return false; + }; + } @Override @@ -202,46 +216,12 @@ public int hashCode() { @Override public ClusterPermission.Builder buildPermission(final ClusterPermission.Builder builder) { - return builder.add(this, Set.of("cluster:admin/xpack/security/privilege/*"), Set.of(), - new RequestPermissionCheckPredicate(applicationNames)); + return builder.add(this, Set.of("cluster:admin/xpack/security/privilege/*"), Set.of(), requestPredicate); } private interface Fields { ParseField MANAGE = new ParseField("manage"); ParseField APPLICATIONS = new ParseField("applications"); } - - private static class RequestPermissionCheckPredicate<TransportRequest> - implements ClusterPermission.PermissionCheckPredicate<TransportRequest> { - private final Automaton applicationNamesAutomaton; - private final Set<String> applicationNames; - private final Predicate<String> applicationPredicate; - - RequestPermissionCheckPredicate(Set<String> applicationNames) { - this.applicationNamesAutomaton = Automatons.patterns(applicationNames); - this.applicationNames = applicationNames; - this.applicationPredicate = Automatons.predicate(applicationNamesAutomaton); - } - - @Override - public boolean implies(ClusterPermission.PermissionCheckPredicate<TransportRequest> otherPermissionCheckPredicate) { - if (otherPermissionCheckPredicate instanceof RequestPermissionCheckPredicate) { - return Operations.subsetOf(((RequestPermissionCheckPredicate) otherPermissionCheckPredicate).applicationNamesAutomaton, - this.applicationNamesAutomaton); - } - return false; - } - - @Override - public boolean test(TransportRequest transportRequest) { - if (transportRequest instanceof ApplicationPrivilegesRequest) { - final ApplicationPrivilegesRequest privRequest = (ApplicationPrivilegesRequest) transportRequest; - final Collection<String> requestApplicationNames = privRequest.getApplicationNames(); - return requestApplicationNames.isEmpty() ? this.applicationNames.contains("*") - : requestApplicationNames.stream().allMatch(application -> applicationPredicate.test(application)); - } - return false; - } - } } } diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermissionTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermissionTests.java index a28931b060f14..7801ae7647387 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermissionTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermissionTests.java @@ -8,15 +8,20 @@ package org.elasticsearch.xpack.core.security.authz.permission; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.transport.TransportRequest; import org.elasticsearch.xpack.core.security.authc.Authentication; import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilege; import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilegeResolver; -import org.elasticsearch.xpack.core.security.authz.privilege.ConfigurableClusterPrivileges; +import org.elasticsearch.xpack.core.security.authz.privilege.ConfigurableClusterPrivilege; import org.junit.Before; +import java.io.IOException; +import java.util.Objects; import java.util.Set; +import java.util.function.Predicate; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.is; @@ -45,10 +50,10 @@ public void testClusterPermissionBuilder() { builder = ClusterPrivilegeResolver.MANAGE_SECURITY.buildPermission(builder); builder = ClusterPrivilegeResolver.MANAGE_ILM.buildPermission(builder); - final ConfigurableClusterPrivileges.ManageApplicationPrivileges mockConfigurableClusterPrivilege1 = - new ConfigurableClusterPrivileges.ManageApplicationPrivileges(Set.of("application-1")); - final ConfigurableClusterPrivileges.ManageApplicationPrivileges mockConfigurableClusterPrivilege2 = - new ConfigurableClusterPrivileges.ManageApplicationPrivileges(Set.of("application-1", "application-2")); + final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege1 = + new MockConfigurableClusterPrivilege(r -> r == mockTransportRequest); + final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege2 = + new MockConfigurableClusterPrivilege(r -> false); builder = mockConfigurableClusterPrivilege1.buildPermission(builder); builder = mockConfigurableClusterPrivilege2.buildPermission(builder); final ClusterPermission clusterPermission = builder.build(); @@ -67,10 +72,10 @@ public void testClusterPermissionCheck() { builder = ClusterPrivilegeResolver.MANAGE_SECURITY.buildPermission(builder); builder = ClusterPrivilegeResolver.MANAGE_ILM.buildPermission(builder); - final ConfigurableClusterPrivileges.ManageApplicationPrivileges mockConfigurableClusterPrivilege1 = - new ConfigurableClusterPrivileges.ManageApplicationPrivileges(Set.of("application-1")); - final ConfigurableClusterPrivileges.ManageApplicationPrivileges mockConfigurableClusterPrivilege2 = - new ConfigurableClusterPrivileges.ManageApplicationPrivileges(Set.of("application-1", "application-2")); + final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege1 = + new MockConfigurableClusterPrivilege(r -> r == mockTransportRequest); + final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege2 = + new MockConfigurableClusterPrivilege(r -> false); builder = mockConfigurableClusterPrivilege1.buildPermission(builder); builder = mockConfigurableClusterPrivilege2.buildPermission(builder); final ClusterPermission clusterPermission = builder.build(); @@ -131,10 +136,10 @@ public void testNoneClusterPermissionIsImpliedByAny() { ClusterPermission.Builder builder = ClusterPermission.builder(); builder = ClusterPrivilegeResolver.MANAGE_SECURITY.buildPermission(builder); builder = ClusterPrivilegeResolver.MANAGE_ILM.buildPermission(builder); - final ConfigurableClusterPrivileges.ManageApplicationPrivileges mockConfigurableClusterPrivilege1 = - new ConfigurableClusterPrivileges.ManageApplicationPrivileges(Set.of("application-1")); - final ConfigurableClusterPrivileges.ManageApplicationPrivileges mockConfigurableClusterPrivilege2 = - new ConfigurableClusterPrivileges.ManageApplicationPrivileges(Set.of("application-1", "application-2")); + final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege1 = + new MockConfigurableClusterPrivilege(r -> r == mockTransportRequest); + final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege2 = + new MockConfigurableClusterPrivilege(r -> false); builder = mockConfigurableClusterPrivilege1.buildPermission(builder); builder = mockConfigurableClusterPrivilege2.buildPermission(builder); final ClusterPermission clusterPermission = builder.build(); @@ -146,8 +151,8 @@ public void testClusterPermissionSubsetWithConfigurableClusterPrivilegeIsImplied ClusterPermission.Builder builder = ClusterPermission.builder(); builder = ClusterPrivilegeResolver.MANAGE_ML.buildPermission(builder); builder = ClusterPrivilegeResolver.MANAGE_ILM.buildPermission(builder); - final ConfigurableClusterPrivileges.ManageApplicationPrivileges mockConfigurableClusterPrivilege1 = - new ConfigurableClusterPrivileges.ManageApplicationPrivileges(Set.of("application-1")); + final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege1 = + new MockConfigurableClusterPrivilege(r -> r == mockTransportRequest); builder = mockConfigurableClusterPrivilege1.buildPermission(builder); final ClusterPermission clusterPermission = builder.build(); @@ -163,16 +168,16 @@ public void testClusterPermissionNonSubsetWithConfigurableClusterPrivilegeIsImpl ClusterPermission.Builder builder = ClusterPermission.builder(); builder = ClusterPrivilegeResolver.MANAGE_ML.buildPermission(builder); builder = ClusterPrivilegeResolver.MANAGE_ILM.buildPermission(builder); - final ConfigurableClusterPrivileges.ManageApplicationPrivileges mockConfigurableClusterPrivilege1 = - new ConfigurableClusterPrivileges.ManageApplicationPrivileges(Set.of("application-1")); + final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege1 = + new MockConfigurableClusterPrivilege(r -> r == mockTransportRequest); builder = mockConfigurableClusterPrivilege1.buildPermission(builder); final ClusterPermission clusterPermission = builder.build(); ClusterPermission.Builder builder1 = ClusterPermission.builder(); builder1 = ClusterPrivilegeResolver.MANAGE_ML.buildPermission(builder1); builder1 = mockConfigurableClusterPrivilege1.buildPermission(builder1); - final ConfigurableClusterPrivileges.ManageApplicationPrivileges mockConfigurableClusterPrivilege2 = - new ConfigurableClusterPrivileges.ManageApplicationPrivileges(Set.of("application-1", "application-2")); + final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege2 = + new MockConfigurableClusterPrivilege(r -> false); builder1 = mockConfigurableClusterPrivilege2.buildPermission(builder1); final ClusterPermission otherClusterPermission = builder1.build(); @@ -209,8 +214,8 @@ public void testClusterPermissionIsImpliedBySameClusterPermission() { ClusterPermission.Builder builder = ClusterPermission.builder(); builder = ClusterPrivilegeResolver.MANAGE_ML.buildPermission(builder); builder = ClusterPrivilegeResolver.MANAGE_ILM.buildPermission(builder); - final ConfigurableClusterPrivileges.ManageApplicationPrivileges mockConfigurableClusterPrivilege1 = - new ConfigurableClusterPrivileges.ManageApplicationPrivileges(Set.of("application-1")); + final MockConfigurableClusterPrivilege mockConfigurableClusterPrivilege1 = + new MockConfigurableClusterPrivilege(r -> r == mockTransportRequest); builder = mockConfigurableClusterPrivilege1.buildPermission(builder); final ClusterPermission clusterPermission = builder.build(); @@ -225,4 +230,59 @@ public void testClusterPermissionSubsetIsImpliedByAllClusterPermission() { assertThat(allClusterPermission.implies(otherClusterPermission), is(true)); } + private static class MockConfigurableClusterPrivilege implements ConfigurableClusterPrivilege { + private Predicate<TransportRequest> requestPredicate; + + MockConfigurableClusterPrivilege(Predicate<TransportRequest> requestPredicate) { + this.requestPredicate = requestPredicate; + } + + @Override + public Category getCategory() { + return Category.APPLICATION; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + return builder; + } + + @Override + public String getWriteableName() { + return "mock-ccp"; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final MockConfigurableClusterPrivilege that = (MockConfigurableClusterPrivilege) o; + return requestPredicate.equals(that.requestPredicate); + } + + @Override + public int hashCode() { + return Objects.hash(requestPredicate); + } + + @Override + public String toString() { + return "MockConfigurableClusterPrivilege{" + + "requestAuthnPredicate=" + requestPredicate + + '}'; + } + + @Override + public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { + return builder.add(this, Set.of("cluster:admin/xpack/security/privilege/*"), Set.of(), requestPredicate); + } + } } From 54490a7c203e075609c2a0512ae20812f7932b75 Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad <yogesh.gaikwad@elastic.co> Date: Tue, 20 Aug 2019 15:58:46 +1000 Subject: [PATCH 5/9] fix tests --- .../authz/AuthorizationServiceTests.java | 30 +++++-------------- .../authz/store/CompositeRolesStoreTests.java | 28 ++--------------- 2 files changed, 10 insertions(+), 48 deletions(-) diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java index 0bb076332d689..e442172a5e642 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java @@ -119,6 +119,7 @@ import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilegeResolver; import org.elasticsearch.xpack.core.security.authz.privilege.ConfigurableClusterPrivilege; import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore; +import org.elasticsearch.xpack.core.security.support.Automatons; import org.elasticsearch.xpack.core.security.user.AnonymousUser; import org.elasticsearch.xpack.core.security.user.ElasticUser; import org.elasticsearch.xpack.core.security.user.KibanaUser; @@ -150,6 +151,7 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.CountDownLatch; +import java.util.function.Predicate; import static java.util.Arrays.asList; import static org.elasticsearch.test.SecurityTestsUtils.assertAuthenticationException; @@ -318,18 +320,9 @@ public void testAuthorizeUsingConditionalPrivileges() throws IOException { final ConfigurableClusterPrivilege configurableClusterPrivilege = new MockConfigurableClusterPrivilege() { @Override public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { + final Predicate<TransportRequest> requestPredicate = r -> r == request; builder.add(this, ((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns(), Set.of(), - new ClusterPermission.PermissionCheckPredicate<TransportRequest>() { - @Override - public boolean implies(ClusterPermission.PermissionCheckPredicate<TransportRequest> otherPermissionCheckPredicate) { - return this.equals(otherPermissionCheckPredicate); - } - - @Override - public boolean test(TransportRequest r) { - return r == request; - } - }); + requestPredicate); return builder; } }; @@ -353,18 +346,9 @@ public void testAuthorizationDeniedWhenConditionalPrivilegesDoNotMatch() throws final ConfigurableClusterPrivilege configurableClusterPrivilege = new MockConfigurableClusterPrivilege() { @Override public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { - builder.add(this,((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns(), Set.of(), - new ClusterPermission.PermissionCheckPredicate<TransportRequest>() { - @Override - public boolean implies(ClusterPermission.PermissionCheckPredicate<TransportRequest> otherPermissionCheckPredicate) { - return this.equals(otherPermissionCheckPredicate); - } - - @Override - public boolean test(TransportRequest r) { - return false; - } - }); + final Predicate<TransportRequest> requestPredicate = r -> false; + builder.add(this, ((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns(), Set.of() + , requestPredicate); return builder; } }; diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java index d7c84926ecb8c..53c8f82361f13 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java @@ -550,19 +550,8 @@ public void testMergingBasicRoles() { ConfigurableClusterPrivilege ccp1 = new MockConfigurableClusterPrivilege() { @Override public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { - builder.add(this, ((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns(), - Set.of(), new ClusterPermission.PermissionCheckPredicate<TransportRequest>() { - - @Override - public boolean test(TransportRequest r) { - return r == request1; - } - - @Override - public boolean implies(ClusterPermission.PermissionCheckPredicate<TransportRequest> permissionCheckPredicate) { - return this.equals(permissionCheckPredicate); - } - }); + builder.add(this, ((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns(), Set.of(), + req -> req == request1); return builder; } }; @@ -593,18 +582,7 @@ public boolean implies(ClusterPermission.PermissionCheckPredicate<TransportReque @Override public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { builder.add(this, ((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns(), - Set.of(), new ClusterPermission.PermissionCheckPredicate<TransportRequest>() { - - @Override - public boolean test(TransportRequest r) { - return r == request2; - } - - @Override - public boolean implies(ClusterPermission.PermissionCheckPredicate<TransportRequest> permissionCheckPredicate) { - return this.equals(permissionCheckPredicate); - } - }); + Set.of(), req -> req == request2); return builder; } }; From 90339969ee251af1e5889e012da498e610df5d81 Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad <yogesh.gaikwad@elastic.co> Date: Tue, 20 Aug 2019 17:47:31 +1000 Subject: [PATCH 6/9] precommit error --- .../xpack/security/authz/AuthorizationServiceTests.java | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java index e442172a5e642..b5b137a74bda0 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java @@ -119,7 +119,6 @@ import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilegeResolver; import org.elasticsearch.xpack.core.security.authz.privilege.ConfigurableClusterPrivilege; import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore; -import org.elasticsearch.xpack.core.security.support.Automatons; import org.elasticsearch.xpack.core.security.user.AnonymousUser; import org.elasticsearch.xpack.core.security.user.ElasticUser; import org.elasticsearch.xpack.core.security.user.KibanaUser; From 541cfadc517910cf7499d24fc53b29d8551ec8f3 Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad <yogesh.gaikwad@elastic.co> Date: Tue, 20 Aug 2019 18:03:31 +1000 Subject: [PATCH 7/9] oh precommit, ran build on another branch, fixed it --- .../security/authz/privilege/ConfigurableClusterPrivileges.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ConfigurableClusterPrivileges.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ConfigurableClusterPrivileges.java index 8632cda623d4c..8b4840f2d504f 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ConfigurableClusterPrivileges.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ConfigurableClusterPrivileges.java @@ -6,8 +6,6 @@ package org.elasticsearch.xpack.core.security.authz.privilege; -import org.apache.lucene.util.automaton.Automaton; -import org.apache.lucene.util.automaton.Operations; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.Strings; import org.elasticsearch.common.io.stream.StreamInput; From 96661a2485e6f2137dd578c95291fee9074d9040 Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad <yogesh.gaikwad@elastic.co> Date: Thu, 22 Aug 2019 12:47:21 +1000 Subject: [PATCH 8/9] address review comments --- .../authz/permission/ClusterPermission.java | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java index ec9d9e1014d27..d8c116dd8da28 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java @@ -82,22 +82,14 @@ public static class Builder { public Builder add(final ClusterPrivilege clusterPrivilege, final Set<String> allowedActionPatterns, final Set<String> excludeActionPatterns) { this.clusterPrivileges.add(clusterPrivilege); - if (allowedActionPatterns.isEmpty() && excludeActionPatterns.isEmpty()) { - this.actionAutomatons.add(Automatons.EMPTY); - } else { - final Automaton allowedAutomaton = Automatons.patterns(allowedActionPatterns); - final Automaton excludedAutomaton = Automatons.patterns(excludeActionPatterns); - this.actionAutomatons.add(Automatons.minusAndMinimize(allowedAutomaton, excludedAutomaton)); - } + final Automaton actionAutomaton = createAutomaton(allowedActionPatterns, excludeActionPatterns); + this.actionAutomatons.add(actionAutomaton); return this; } public Builder add(final ClusterPrivilege clusterPrivilege, final Set<String> allowedActionPatterns, final Set<String> excludeActionPatterns, final Predicate<TransportRequest> requestPredicate) { - final Automaton allowedAutomaton = Automatons.patterns(allowedActionPatterns); - final Automaton excludedAutomaton = Automatons.patterns(excludeActionPatterns); - final Automaton actionAutomaton = Automatons.minusAndMinimize(allowedAutomaton, excludedAutomaton); - + final Automaton actionAutomaton = createAutomaton(allowedActionPatterns, excludeActionPatterns); return add(clusterPrivilege, new ActionRequestBasedPermissionCheck(clusterPrivilege, actionAutomaton, requestPredicate)); } @@ -120,6 +112,21 @@ public ClusterPermission build() { } return new ClusterPermission(this.clusterPrivileges, checks); } + + private static Automaton createAutomaton(Set<String> allowedActionPatterns, Set<String> excludeActionPatterns) { + allowedActionPatterns = (allowedActionPatterns == null) ? Set.of() : allowedActionPatterns; + excludeActionPatterns = (excludeActionPatterns == null) ? Set.of() : excludeActionPatterns; + + if (allowedActionPatterns.isEmpty()) { + return Automatons.EMPTY; + } else if (excludeActionPatterns.isEmpty()) { + return Automatons.patterns(allowedActionPatterns); + } else { + final Automaton allowedAutomaton = Automatons.patterns(allowedActionPatterns); + final Automaton excludedAutomaton = Automatons.patterns(excludeActionPatterns); + return Automatons.minusAndMinimize(allowedAutomaton, excludedAutomaton); + } + } } /** From cf18cf0a85eca552dee84040afe9f1d77ee83916 Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad <yogesh.gaikwad@elastic.co> Date: Thu, 22 Aug 2019 12:52:52 +1000 Subject: [PATCH 9/9] address review comments --- .../core/security/authz/permission/ClusterPermission.java | 4 ++-- .../authz/privilege/ConfigurableClusterPrivileges.java | 2 +- .../security/authz/permission/ClusterPermissionTests.java | 2 +- .../xpack/security/authz/AuthorizationServiceTests.java | 6 +++--- .../security/authz/store/CompositeRolesStoreTests.java | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java index d8c116dd8da28..9d32ee9909c75 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java @@ -88,8 +88,8 @@ public Builder add(final ClusterPrivilege clusterPrivilege, final Set<String> al } public Builder add(final ClusterPrivilege clusterPrivilege, final Set<String> allowedActionPatterns, - final Set<String> excludeActionPatterns, final Predicate<TransportRequest> requestPredicate) { - final Automaton actionAutomaton = createAutomaton(allowedActionPatterns, excludeActionPatterns); + final Predicate<TransportRequest> requestPredicate) { + final Automaton actionAutomaton = createAutomaton(allowedActionPatterns, Set.of()); return add(clusterPrivilege, new ActionRequestBasedPermissionCheck(clusterPrivilege, actionAutomaton, requestPredicate)); } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ConfigurableClusterPrivileges.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ConfigurableClusterPrivileges.java index 8b4840f2d504f..a5ec573d5c988 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ConfigurableClusterPrivileges.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ConfigurableClusterPrivileges.java @@ -214,7 +214,7 @@ public int hashCode() { @Override public ClusterPermission.Builder buildPermission(final ClusterPermission.Builder builder) { - return builder.add(this, Set.of("cluster:admin/xpack/security/privilege/*"), Set.of(), requestPredicate); + return builder.add(this, Set.of("cluster:admin/xpack/security/privilege/*"), requestPredicate); } private interface Fields { diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermissionTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermissionTests.java index 7801ae7647387..fe08db0d2e2e0 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermissionTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermissionTests.java @@ -282,7 +282,7 @@ public String toString() { @Override public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { - return builder.add(this, Set.of("cluster:admin/xpack/security/privilege/*"), Set.of(), requestPredicate); + return builder.add(this, Set.of("cluster:admin/xpack/security/privilege/*"), requestPredicate); } } } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java index b5b137a74bda0..600cc6531fa4e 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java @@ -320,7 +320,7 @@ public void testAuthorizeUsingConditionalPrivileges() throws IOException { @Override public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { final Predicate<TransportRequest> requestPredicate = r -> r == request; - builder.add(this, ((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns(), Set.of(), + builder.add(this, ((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns(), requestPredicate); return builder; } @@ -346,8 +346,8 @@ public void testAuthorizationDeniedWhenConditionalPrivilegesDoNotMatch() throws @Override public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { final Predicate<TransportRequest> requestPredicate = r -> false; - builder.add(this, ((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns(), Set.of() - , requestPredicate); + builder.add(this, ((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns(), + requestPredicate); return builder; } }; diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java index 53c8f82361f13..58d19ed2c97e1 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java @@ -550,7 +550,7 @@ public void testMergingBasicRoles() { ConfigurableClusterPrivilege ccp1 = new MockConfigurableClusterPrivilege() { @Override public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { - builder.add(this, ((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns(), Set.of(), + builder.add(this, ((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns(), req -> req == request1); return builder; } @@ -582,7 +582,7 @@ public ClusterPermission.Builder buildPermission(ClusterPermission.Builder build @Override public ClusterPermission.Builder buildPermission(ClusterPermission.Builder builder) { builder.add(this, ((ActionClusterPrivilege) ClusterPrivilegeResolver.MANAGE_SECURITY).getAllowedActionPatterns(), - Set.of(), req -> req == request2); + req -> req == request2); return builder; } };