| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.jackrabbit.oak.security.authorization.composite; |
| |
| import java.lang.reflect.Field; |
| import java.security.Principal; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import javax.jcr.Session; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableMap; |
| import com.google.common.collect.ImmutableSet; |
| import org.apache.jackrabbit.api.JackrabbitSession; |
| import org.apache.jackrabbit.oak.api.ContentSession; |
| import org.apache.jackrabbit.oak.api.Tree; |
| import org.apache.jackrabbit.oak.commons.PathUtils; |
| import org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration; |
| import org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider; |
| import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider; |
| import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions; |
| import org.apache.jackrabbit.oak.spi.security.authorization.permission.RepositoryPermission; |
| import org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission; |
| import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal; |
| import org.apache.jackrabbit.oak.spi.state.NodeState; |
| import org.junit.Test; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertTrue; |
| |
| /** |
| * Test the effect of the combination of |
| * |
| * - default permission provider |
| * - custom provider that doesn't support any permissions nowhere |
| * |
| * The tests are executed both for the set of principals associated with the test |
| * user and with the admin session. |
| * The expected outcome is that the composite provider behaves exactly like the |
| * default provider (i.e. the {@code NotSupportingProvider} is never respected |
| * during evaluation). |
| * |
| * While there is no real use in such a {@link AggregatedPermissionProvider}, that |
| * is never called, is is used here to verify that the composite provider doesn't |
| * introduce any regressions compared to the default provider implementation. |
| */ |
| public class CompositeProviderNoScopeTest extends AbstractCompositeProviderTest { |
| |
| private CompositePermissionProvider cppTestUser; |
| private PermissionProvider defTestUser; |
| |
| private CompositePermissionProvider cppAdminUser; |
| private PermissionProvider defAdminUser; |
| |
| |
| @Override |
| public void before() throws Exception { |
| super.before(); |
| |
| ContentSession cs = root.getContentSession(); |
| |
| Set<Principal> testPrincipals = ImmutableSet.of(getTestUser().getPrincipal(), EveryonePrincipal.getInstance()); |
| cppTestUser = createPermissionProvider(testPrincipals); |
| defTestUser = getConfig(AuthorizationConfiguration.class).getPermissionProvider(root, cs.getWorkspaceName(), testPrincipals); |
| |
| Set<Principal> adminPrincipals = cs.getAuthInfo().getPrincipals(); |
| cppAdminUser = createPermissionProvider(adminPrincipals); |
| defAdminUser = getConfig(AuthorizationConfiguration.class).getPermissionProvider(root, cs.getWorkspaceName(), adminPrincipals); |
| } |
| |
| @Override |
| protected AggregatedPermissionProvider getTestPermissionProvider() { |
| return new NoScopeProvider(root); |
| } |
| |
| @Override |
| @Test |
| public void testGetTreePermissionInstance() throws Exception { |
| PermissionProvider pp = createPermissionProviderOR(); |
| TreePermission parentPermission = TreePermission.EMPTY; |
| |
| for (String path : TP_PATHS) { |
| Tree t = readOnlyRoot.getTree(path); |
| TreePermission tp = pp.getTreePermission(t, parentPermission); |
| assertCompositeTreePermission(t.isRoot(), tp); |
| parentPermission = tp; |
| } |
| } |
| |
| @Override |
| @Test |
| public void testGetTreePermissionInstanceOR() throws Exception { |
| PermissionProvider pp = createPermissionProvider(); |
| TreePermission parentPermission = TreePermission.EMPTY; |
| |
| for (String path : TP_PATHS) { |
| Tree t = readOnlyRoot.getTree(path); |
| TreePermission tp = pp.getTreePermission(t, parentPermission); |
| assertCompositeTreePermission(t.isRoot(), tp); |
| parentPermission = tp; |
| } |
| } |
| |
| @Override |
| @Test |
| public void testTreePermissionGetChild() throws Exception { |
| List<String> childNames = ImmutableList.of("test", "a", "b", "c", "nonexisting"); |
| |
| Tree rootTree = readOnlyRoot.getTree(ROOT_PATH); |
| NodeState ns = getTreeProvider().asNodeState(rootTree); |
| TreePermission tp = createPermissionProvider().getTreePermission(rootTree, TreePermission.EMPTY); |
| assertCompositeTreePermission(tp); |
| |
| for (String cName : childNames) { |
| ns = ns.getChildNode(cName); |
| tp = tp.getChildPermission(cName, ns); |
| assertCompositeTreePermission(false, tp); |
| } |
| } |
| |
| @Override |
| @Test |
| public void testTreePermissionGetChildOR() throws Exception { |
| List<String> childNames = ImmutableList.of("test", "a", "b", "c", "nonexisting"); |
| |
| Tree rootTree = readOnlyRoot.getTree(ROOT_PATH); |
| NodeState ns = getTreeProvider().asNodeState(rootTree); |
| TreePermission tp = createPermissionProviderOR().getTreePermission(rootTree, TreePermission.EMPTY); |
| assertCompositeTreePermission(tp); |
| |
| for (String cName : childNames) { |
| ns = ns.getChildNode(cName); |
| tp = tp.getChildPermission(cName, ns); |
| assertCompositeTreePermission(false, tp); |
| } |
| } |
| |
| @Test |
| public void testGetPrivileges() throws Exception { |
| for (String p : defPrivileges.keySet()) { |
| Set<String> expected = defPrivileges.get(p); |
| Tree tree = readOnlyRoot.getTree(p); |
| |
| assertEquals(p, expected, cppTestUser.getPrivileges(tree)); |
| assertEquals(p, defTestUser.getPrivileges(tree), cppTestUser.getPrivileges(tree)); |
| } |
| } |
| |
| @Test |
| public void testGetPrivilegesAdmin() throws Exception { |
| Set<String> expected = ImmutableSet.of(JCR_ALL); |
| for (String p : NODE_PATHS) { |
| Tree tree = readOnlyRoot.getTree(p); |
| |
| assertEquals(p, expected, cppAdminUser.getPrivileges(tree)); |
| assertEquals(p, defAdminUser.getPrivileges(tree), cppAdminUser.getPrivileges(tree)); |
| } |
| } |
| |
| @Test |
| public void testGetPrivilegesOnRepo() throws Exception { |
| Set<String> expected = ImmutableSet.of(JCR_NAMESPACE_MANAGEMENT, JCR_NODE_TYPE_DEFINITION_MANAGEMENT); |
| |
| assertEquals(expected, cppTestUser.getPrivileges(null)); |
| assertEquals(defTestUser.getPrivileges(null), cppTestUser.getPrivileges(null)); |
| } |
| |
| @Test |
| public void testGetPrivilegesOnRepoAdmin() throws Exception { |
| Set<String> expected = ImmutableSet.of(JCR_ALL); |
| |
| assertEquals(expected, cppAdminUser.getPrivileges(null)); |
| assertEquals(defAdminUser.getPrivileges(null), cppAdminUser.getPrivileges(null)); |
| } |
| |
| |
| @Test |
| public void testHasPrivileges() throws Exception { |
| for (String p : defPrivileges.keySet()) { |
| Set<String> expected = defPrivileges.get(p); |
| Tree tree = readOnlyRoot.getTree(p); |
| |
| String[] privNames = expected.toArray(new String[expected.size()]); |
| assertTrue(p, cppTestUser.hasPrivileges(tree, privNames)); |
| assertEquals(p, defTestUser.hasPrivileges(tree, privNames), cppTestUser.hasPrivileges(tree, privNames)); |
| } |
| } |
| |
| @Test |
| public void testHasPrivilegesAdmin() throws Exception { |
| for (String p : NODE_PATHS) { |
| Tree tree = readOnlyRoot.getTree(p); |
| |
| assertTrue(p, cppAdminUser.hasPrivileges(tree, JCR_ALL)); |
| assertTrue(p, defAdminUser.hasPrivileges(tree, JCR_ALL)); |
| } |
| } |
| |
| @Test |
| public void testHasPrivilegesOnRepo() throws Exception { |
| assertTrue(cppTestUser.hasPrivileges(null, JCR_NAMESPACE_MANAGEMENT, JCR_NODE_TYPE_DEFINITION_MANAGEMENT)); |
| assertTrue(defTestUser.hasPrivileges(null, JCR_NAMESPACE_MANAGEMENT, JCR_NODE_TYPE_DEFINITION_MANAGEMENT)); |
| |
| assertTrue(cppTestUser.hasPrivileges(null)); |
| assertTrue(defTestUser.hasPrivileges(null)); |
| } |
| |
| @Test |
| public void testHasPrivilegeOnRepoAdminUser() throws Exception { |
| assertTrue(cppAdminUser.hasPrivileges(null, JCR_ALL)); |
| assertTrue(defAdminUser.hasPrivileges(null, JCR_ALL)); |
| |
| assertTrue(cppAdminUser.hasPrivileges(null)); |
| assertTrue(defAdminUser.hasPrivileges(null)); |
| } |
| |
| @Test |
| public void testIsGranted() throws Exception { |
| for (String p : defPermissions.keySet()) { |
| long expected = defPermissions.get(p); |
| Tree tree = readOnlyRoot.getTree(p); |
| |
| assertTrue(p, cppTestUser.isGranted(tree, null, expected)); |
| assertTrue(p, defTestUser.isGranted(tree, null, expected)); |
| } |
| } |
| |
| @Test |
| public void testIsGrantedAdmin() throws Exception { |
| for (String p : defPermissions.keySet()) { |
| Tree tree = readOnlyRoot.getTree(p); |
| |
| assertTrue(p, cppAdminUser.isGranted(tree, null, Permissions.ALL)); |
| assertTrue(p, defAdminUser.isGranted(tree, null, Permissions.ALL)); |
| } |
| } |
| |
| @Test |
| public void testIsGrantedProperty() throws Exception { |
| for (String p : defPermissions.keySet()) { |
| long expected = defPermissions.get(p); |
| Tree tree = readOnlyRoot.getTree(p); |
| |
| assertTrue(p, cppTestUser.isGranted(tree, PROPERTY_STATE, expected)); |
| assertTrue(p, defTestUser.isGranted(tree, PROPERTY_STATE, expected)); |
| } |
| } |
| |
| @Test |
| public void testIsGrantedPropertyAdmin() throws Exception { |
| for (String p : defPermissions.keySet()) { |
| Tree tree = readOnlyRoot.getTree(p); |
| |
| assertTrue(p, cppAdminUser.isGranted(tree, PROPERTY_STATE, Permissions.ALL)); |
| assertTrue(p, defAdminUser.isGranted(tree, PROPERTY_STATE, Permissions.ALL)); |
| } |
| } |
| |
| @Test |
| public void testIsGrantedAction() throws Exception { |
| for (String p : defActionsGranted.keySet()) { |
| String actions = getActionString(defActionsGranted.get(p)); |
| assertTrue(p + " : " + actions, cppTestUser.isGranted(p, actions)); |
| assertTrue(p + " : " + actions, defTestUser.isGranted(p, actions)); |
| } |
| } |
| |
| @Test |
| public void testIsGrantedAction2() throws Exception { |
| Map<String, String[]> noAccess = ImmutableMap.<String, String[]>builder(). |
| put(ROOT_PATH, new String[] {Session.ACTION_READ}). |
| put(ROOT_PATH + "jcr:primaryType", new String[] {Session.ACTION_READ, Session.ACTION_SET_PROPERTY}). |
| put("/nonexisting", new String[] {Session.ACTION_READ, Session.ACTION_ADD_NODE}). |
| put(TEST_PATH_2, new String[] {Session.ACTION_READ, Session.ACTION_REMOVE}). |
| put(TEST_PATH_2 + "/jcr:primaryType", new String[] {Session.ACTION_READ, Session.ACTION_SET_PROPERTY}). |
| put(TEST_A_B_C_PATH, new String[] {Session.ACTION_READ, Session.ACTION_REMOVE}). |
| put(TEST_A_B_C_PATH + "/noneExisting", new String[] {Session.ACTION_READ, JackrabbitSession.ACTION_REMOVE_NODE}). |
| put(TEST_A_B_C_PATH + "/jcr:primaryType", new String[] {JackrabbitSession.ACTION_REMOVE_PROPERTY}).build(); |
| |
| for (String p : noAccess.keySet()) { |
| String actions = getActionString(noAccess.get(p)); |
| assertFalse(p, cppTestUser.isGranted(p, actions)); |
| assertFalse(p, defTestUser.isGranted(p, actions)); |
| } |
| } |
| |
| @Test |
| public void testIsGrantedActionAdmin() throws Exception { |
| String allActions = getActionString(ALL_ACTIONS); |
| for (String p : defActionsGranted.keySet()) { |
| assertTrue(p + " : " + allActions, cppAdminUser.isGranted(p, allActions)); |
| assertTrue(p + " : " + allActions, defAdminUser.isGranted(p, allActions)); |
| } |
| } |
| |
| @Test |
| public void testRepositoryPermissionIsGranted() throws Exception { |
| RepositoryPermission rp = cppTestUser.getRepositoryPermission(); |
| |
| assertTrue(rp.isGranted(Permissions.NAMESPACE_MANAGEMENT)); |
| assertTrue(rp.isGranted(Permissions.NODE_TYPE_DEFINITION_MANAGEMENT)); |
| assertTrue(rp.isGranted(Permissions.NAMESPACE_MANAGEMENT | Permissions.NODE_TYPE_DEFINITION_MANAGEMENT)); |
| } |
| |
| @Test |
| public void testRepositoryPermissionIsGrantedAdminUser() throws Exception { |
| RepositoryPermission rp = cppAdminUser.getRepositoryPermission(); |
| |
| assertTrue(rp.isGranted(Permissions.ALL)); |
| } |
| |
| @Test |
| public void testTreePermissionIsGranted() throws Exception { |
| TreePermission parentPermission = TreePermission.EMPTY; |
| |
| for (String path : TP_PATHS) { |
| TreePermission tp = cppTestUser.getTreePermission(readOnlyRoot.getTree(path), parentPermission); |
| Long toTest = (defPermissions.containsKey(path)) ? defPermissions.get(path) : defPermissions.get(PathUtils.getAncestorPath(path, 1)); |
| if (toTest != null) { |
| assertTrue(tp.isGranted(toTest)); |
| } |
| parentPermission = tp; |
| } |
| } |
| |
| @Test |
| public void testTreePermissionIsGrantedProperty() throws Exception { |
| TreePermission parentPermission = TreePermission.EMPTY; |
| |
| for (String path : TP_PATHS) { |
| TreePermission tp = cppTestUser.getTreePermission(readOnlyRoot.getTree(path), parentPermission); |
| Long toTest = (defPermissions.containsKey(path)) ? defPermissions.get(path) : defPermissions.get(PathUtils.getAncestorPath(path, 1)); |
| if (toTest != null) { |
| assertTrue(tp.isGranted(toTest, PROPERTY_STATE)); |
| } |
| parentPermission = tp; |
| } |
| } |
| |
| @Test |
| public void testTreePermissionCanRead() throws Exception { |
| Map<String, Boolean> readMap = ImmutableMap.<String, Boolean>builder(). |
| put(ROOT_PATH, false). |
| put(TEST_PATH, true). |
| put(TEST_A_PATH, true). |
| put(TEST_A_B_PATH, true). |
| put(TEST_A_B_C_PATH, false). |
| put(TEST_A_B_C_PATH + "/nonexisting", false). |
| build(); |
| |
| TreePermission parentPermission = TreePermission.EMPTY; |
| TreePermission parentPermission2 = TreePermission.EMPTY; |
| for (String nodePath : readMap.keySet()) { |
| Tree tree = readOnlyRoot.getTree(nodePath); |
| TreePermission tp = cppTestUser.getTreePermission(tree, parentPermission); |
| TreePermission tp2 = defTestUser.getTreePermission(tree, parentPermission2); |
| |
| boolean expectedResult = readMap.get(nodePath); |
| assertEquals(nodePath, expectedResult, tp.canRead()); |
| assertEquals(nodePath + "(default)", expectedResult, tp2.canRead()); |
| |
| parentPermission = tp; |
| parentPermission2 = tp2; |
| } |
| } |
| |
| @Test |
| public void testTreePermissionCanReadProperty() throws Exception { |
| Map<String, Boolean> readMap = ImmutableMap.<String, Boolean>builder(). |
| put(ROOT_PATH, false). |
| put(TEST_PATH, true). |
| put(TEST_A_PATH, true). |
| put(TEST_A_B_PATH, true). |
| put(TEST_A_B_C_PATH, true). |
| put(TEST_A_B_C_PATH + "/nonexisting", true). |
| build(); |
| |
| TreePermission parentPermission = TreePermission.EMPTY; |
| TreePermission parentPermission2 = TreePermission.EMPTY; |
| for (String nodePath : readMap.keySet()) { |
| Tree tree = readOnlyRoot.getTree(nodePath); |
| |
| TreePermission tp = cppTestUser.getTreePermission(tree, parentPermission); |
| TreePermission tp2 = defTestUser.getTreePermission(tree, parentPermission2); |
| |
| boolean expectedResult = readMap.get(nodePath); |
| assertEquals(nodePath, expectedResult, tp.canRead(PROPERTY_STATE)); |
| assertEquals(nodePath + "(default)", expectedResult, tp2.canRead(PROPERTY_STATE)); |
| |
| parentPermission = tp; |
| parentPermission2 = tp2; |
| } |
| } |
| |
| @Test |
| public void testTreePermissionCanReadAdmin() { |
| TreePermission parentPermission = TreePermission.EMPTY; |
| TreePermission parentPermission2 = TreePermission.EMPTY; |
| |
| for (String nodePath : TP_PATHS) { |
| Tree tree = readOnlyRoot.getTree(nodePath); |
| |
| TreePermission tp = cppAdminUser.getTreePermission(tree, parentPermission); |
| TreePermission tp2 = defAdminUser.getTreePermission(tree, parentPermission2); |
| |
| assertTrue(nodePath, tp.canRead()); |
| assertTrue(nodePath, tp.canRead(PROPERTY_STATE)); |
| |
| assertTrue(nodePath + "(default)", tp2.canRead()); |
| assertTrue(nodePath + "(default)", tp2.canRead(PROPERTY_STATE)); |
| |
| parentPermission = tp; |
| parentPermission2 = tp2; |
| } |
| } |
| |
| @Test |
| public void testTreePermissionSize() throws Exception { |
| Field tpField = CompositeTreePermission.class.getDeclaredField("treePermissions"); |
| tpField.setAccessible(true); |
| |
| |
| Tree rootTree = readOnlyRoot.getTree(ROOT_PATH); |
| NodeState ns = getTreeProvider().asNodeState(rootTree); |
| TreePermission tp = cppTestUser.getTreePermission(rootTree, TreePermission.EMPTY); |
| assertEquals(2, ((TreePermission[]) tpField.get(tp)).length); |
| |
| List<String> childNames = ImmutableList.of("test", "a", "b", "c", "nonexisting"); |
| for (String cName : childNames) { |
| ns = ns.getChildNode(cName); |
| tp = tp.getChildPermission(cName, ns); |
| |
| assertCompositeTreePermission(false, tp); |
| } |
| } |
| } |