| /* |
| * 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.spi.security.authorization.principalbased.impl; |
| |
| import com.google.common.collect.ImmutableMap; |
| import com.google.common.collect.ImmutableSet; |
| import org.apache.jackrabbit.oak.api.PropertyState; |
| import org.apache.jackrabbit.oak.api.Tree; |
| import org.apache.jackrabbit.oak.commons.PathUtils; |
| import org.apache.jackrabbit.oak.namepath.NamePathMapper; |
| import org.apache.jackrabbit.oak.plugins.memory.PropertyStates; |
| import org.apache.jackrabbit.oak.plugins.tree.TreeType; |
| import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions; |
| import org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission; |
| import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| import javax.jcr.Value; |
| import java.security.Principal; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import static org.apache.jackrabbit.oak.api.Type.STRING; |
| import static org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants.REP_GLOB; |
| import static org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.Constants.REP_EFFECTIVE_PATH; |
| import static org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.Constants.REP_PRINCIPAL_POLICY; |
| import static org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.Constants.REP_PRIVILEGES; |
| import static org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.Constants.REP_RESTRICTIONS; |
| import static org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants.JCR_MODIFY_ACCESS_CONTROL; |
| import static org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants.JCR_READ; |
| import static org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants.JCR_READ_ACCESS_CONTROL; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertSame; |
| import static org.junit.Assert.assertTrue; |
| |
| public class PermissionProviderAccessControlTest extends AbstractPrincipalBasedTest { |
| |
| private Principal testPrincipal; |
| private PrincipalBasedPermissionProvider permissionProvider; |
| |
| private String contentPath; |
| private String childPath; |
| private String grandchildPath; |
| |
| private String child2Path; |
| |
| private String accessControlledPath; |
| |
| @Before |
| public void before() throws Exception { |
| super.before(); |
| |
| testPrincipal = getTestSystemUser().getPrincipal(); |
| setupContentTrees(TEST_OAK_PATH); |
| setupContentTrees("/oak:content/child2/grandchild2"); |
| |
| contentPath = PathUtils.getAncestorPath(TEST_OAK_PATH, 3); |
| childPath = PathUtils.getAncestorPath(TEST_OAK_PATH, 2); |
| grandchildPath = PathUtils.getAncestorPath(TEST_OAK_PATH, 1); |
| |
| child2Path = "/oak:content/child2"; |
| |
| PrincipalPolicyImpl policy = setupPrincipalBasedAccessControl(testPrincipal, getNamePathMapper().getJcrPath(contentPath), JCR_READ); |
| addPrincipalBasedEntry(policy, getNamePathMapper().getJcrPath(childPath), PrivilegeConstants.JCR_READ_ACCESS_CONTROL); |
| addPrincipalBasedEntry(policy, getNamePathMapper().getJcrPath(child2Path), PrivilegeConstants.JCR_MODIFY_ACCESS_CONTROL); |
| accessControlledPath = policy.getOakPath(); |
| root.commit(); |
| |
| permissionProvider = createPermissionProvider(root, testPrincipal); |
| } |
| |
| @Override |
| protected NamePathMapper getNamePathMapper() { |
| return NamePathMapper.DEFAULT; |
| } |
| |
| @Test |
| public void testGetTreePermission() throws Exception { |
| String oakPath = PathUtils.concat(accessControlledPath, REP_PRINCIPAL_POLICY); |
| Tree tree = root.getTree(PathUtils.ROOT_PATH); |
| TreePermission tp = permissionProvider.getTreePermission(tree, TreePermission.EMPTY); |
| for (String elem : PathUtils.elements(oakPath)) { |
| tree = tree.getChild(elem); |
| tp = permissionProvider.getTreePermission(tree, tp); |
| } |
| |
| assertTrue(tp instanceof AbstractTreePermission); |
| assertSame(TreeType.ACCESS_CONTROL, ((AbstractTreePermission) tp).getType()); |
| } |
| |
| @Test |
| public void testIsGrantedOnAccessControlledTree() throws Exception { |
| Tree accessControlledTree = root.getTree(getNamePathMapper().getOakPath(accessControlledPath)); |
| assertFalse(permissionProvider.isGranted(accessControlledTree, null, Permissions.READ)); |
| assertFalse(permissionProvider.isGranted(accessControlledTree, null, Permissions.READ_ACCESS_CONTROL)); |
| |
| setupPrincipalBasedAccessControl(testPrincipal, accessControlledPath, JCR_READ); |
| root.commit(); |
| permissionProvider.refresh(); |
| |
| assertTrue(permissionProvider.isGranted(accessControlledTree, null, Permissions.READ)); |
| |
| } |
| |
| @Test |
| public void testIsGrantedOnPolicyTree() throws Exception { |
| Tree policyTree = root.getTree(PathUtils.concat(accessControlledPath, REP_PRINCIPAL_POLICY)); |
| assertFalse(permissionProvider.isGranted(policyTree, null, Permissions.READ)); |
| assertFalse(permissionProvider.isGranted(policyTree, null, Permissions.READ_ACCESS_CONTROL)); |
| assertFalse(permissionProvider.isGranted(policyTree, null, Permissions.READ_ACCESS_CONTROL|Permissions.MODIFY_ACCESS_CONTROL)); |
| assertFalse(permissionProvider.isGranted(policyTree, null, Permissions.WRITE)); |
| } |
| |
| @Test |
| public void testIsGrantedOnPolicyTreePrincipalReadable() throws Exception { |
| setupPrincipalBasedAccessControl(testPrincipal, accessControlledPath, JCR_READ); |
| root.commit(); |
| permissionProvider.refresh(); |
| |
| Tree policyTree = root.getTree(PathUtils.concat(accessControlledPath, REP_PRINCIPAL_POLICY)); |
| assertTrue(permissionProvider.isGranted(policyTree, null, Permissions.READ)); |
| assertFalse(permissionProvider.isGranted(policyTree, null, Permissions.READ_ACCESS_CONTROL)); |
| assertFalse(permissionProvider.isGranted(policyTree, null, Permissions.READ_ACCESS_CONTROL|Permissions.MODIFY_ACCESS_CONTROL)); |
| assertFalse(permissionProvider.isGranted(policyTree, null, Permissions.WRITE)); |
| } |
| |
| @Test |
| public void testIsGrantedOnPolicyTreePrincipalAccessControlReadable() throws Exception { |
| setupPrincipalBasedAccessControl(testPrincipal, accessControlledPath, JCR_READ, JCR_READ_ACCESS_CONTROL); |
| root.commit(); |
| permissionProvider.refresh(); |
| |
| Tree policyTree = root.getTree(PathUtils.concat(accessControlledPath, REP_PRINCIPAL_POLICY)); |
| assertTrue(permissionProvider.isGranted(policyTree, null, Permissions.READ)); |
| assertTrue(permissionProvider.isGranted(policyTree, null, Permissions.READ_ACCESS_CONTROL)); |
| assertFalse(permissionProvider.isGranted(policyTree, null, Permissions.READ_ACCESS_CONTROL|Permissions.MODIFY_ACCESS_CONTROL)); |
| assertFalse(permissionProvider.isGranted(policyTree, null, Permissions.WRITE)); |
| } |
| |
| @Test |
| public void testIsGrantedOnEntryTree() throws Exception { |
| setupPrincipalBasedAccessControl(testPrincipal, accessControlledPath, JCR_READ, JCR_READ_ACCESS_CONTROL); |
| root.commit(); |
| permissionProvider.refresh(); |
| |
| Tree policyTree = root.getTree(PathUtils.concat(accessControlledPath, REP_PRINCIPAL_POLICY)); |
| for (Tree child : policyTree.getChildren()) { |
| assertTrue(permissionProvider.isGranted(child, null, Permissions.READ|Permissions.READ_ACCESS_CONTROL)); |
| assertFalse(permissionProvider.isGranted(child, null, Permissions.MODIFY_ACCESS_CONTROL)); |
| } |
| } |
| |
| @Test |
| public void testIsGrantedOnEntryTreeAccessControlModifiable() throws Exception { |
| setupPrincipalBasedAccessControl(testPrincipal, accessControlledPath, JCR_READ, JCR_MODIFY_ACCESS_CONTROL); |
| root.commit(); |
| permissionProvider.refresh(); |
| |
| Tree policyTree = root.getTree(PathUtils.concat(accessControlledPath, REP_PRINCIPAL_POLICY)); |
| for (Tree child : policyTree.getChildren()) { |
| assertTrue(permissionProvider.isGranted(child, null, Permissions.READ)); |
| |
| String effectivePath = child.getProperty(REP_EFFECTIVE_PATH).getValue(STRING); |
| if (contentPath.equals(effectivePath)) { |
| assertFalse(permissionProvider.isGranted(child, null, Permissions.READ_ACCESS_CONTROL)); |
| assertFalse(permissionProvider.isGranted(child, null, Permissions.MODIFY_ACCESS_CONTROL)); |
| } else if (childPath.equals(effectivePath)) { |
| assertFalse(permissionProvider.isGranted(child, null, Permissions.READ_ACCESS_CONTROL)); |
| assertFalse(permissionProvider.isGranted(child, null, Permissions.MODIFY_ACCESS_CONTROL)); |
| } else if (child2Path.equals(effectivePath)) { |
| assertFalse(permissionProvider.isGranted(child, null, Permissions.READ_ACCESS_CONTROL)); |
| assertTrue(permissionProvider.isGranted(child, null, Permissions.MODIFY_ACCESS_CONTROL)); |
| } |
| } |
| } |
| |
| @Test |
| public void testIsGrantedOnEntryTreeAccessMgt() throws Exception { |
| setupPrincipalBasedAccessControl(testPrincipal, accessControlledPath, JCR_READ, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL); |
| root.commit(); |
| permissionProvider.refresh(); |
| |
| Tree policyTree = root.getTree(PathUtils.concat(accessControlledPath, REP_PRINCIPAL_POLICY)); |
| for (Tree child : policyTree.getChildren()) { |
| assertTrue(permissionProvider.isGranted(child, null, Permissions.READ|Permissions.READ_ACCESS_CONTROL)); |
| assertTrue(permissionProvider.isGranted(child, child.getProperty(REP_EFFECTIVE_PATH), Permissions.READ_ACCESS_CONTROL)); |
| assertTrue(permissionProvider.isGranted(child, child.getProperty(REP_PRIVILEGES), Permissions.READ_ACCESS_CONTROL)); |
| |
| String effectivePath = child.getProperty(REP_EFFECTIVE_PATH).getValue(STRING); |
| if (contentPath.equals(effectivePath)) { |
| assertFalse(permissionProvider.isGranted(child, null, Permissions.MODIFY_ACCESS_CONTROL)); |
| } else if (childPath.equals(effectivePath)) { |
| assertFalse(permissionProvider.isGranted(child, null, Permissions.MODIFY_ACCESS_CONTROL)); |
| } else if (child2Path.equals(effectivePath)) { |
| assertTrue(permissionProvider.isGranted(child, null, Permissions.MODIFY_ACCESS_CONTROL)); |
| } |
| } |
| } |
| |
| @Test |
| public void testIsGrantedOnNonExistingRestrictionTree() throws Exception { |
| setupPrincipalBasedAccessControl(testPrincipal, accessControlledPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL); |
| root.commit(); |
| permissionProvider.refresh(); |
| |
| Tree policyTree = root.getTree(PathUtils.concat(accessControlledPath, REP_PRINCIPAL_POLICY)); |
| for (Tree child : policyTree.getChildren()) { |
| Tree restr = child.getChild(REP_RESTRICTIONS); |
| PropertyState propertyState = PropertyStates.createProperty(REP_GLOB, "any"); |
| |
| assertFalse(permissionProvider.isGranted(restr, null, Permissions.READ)); |
| |
| String effectivePath = child.getProperty(REP_EFFECTIVE_PATH).getValue(STRING); |
| if (contentPath.equals(effectivePath)) { |
| assertTrue(permissionProvider.isGranted(restr, null, Permissions.READ_ACCESS_CONTROL)); |
| assertTrue(permissionProvider.isGranted(restr, propertyState, Permissions.READ_ACCESS_CONTROL)); |
| assertFalse(permissionProvider.isGranted(restr, null, Permissions.MODIFY_ACCESS_CONTROL)); |
| } else if (childPath.equals(effectivePath)) { |
| assertTrue(permissionProvider.isGranted(restr, null, Permissions.READ_ACCESS_CONTROL)); |
| assertTrue(permissionProvider.isGranted(restr, propertyState, Permissions.READ_ACCESS_CONTROL)); |
| assertFalse(permissionProvider.isGranted(restr, null, Permissions.MODIFY_ACCESS_CONTROL)); |
| } else if (child2Path.equals(effectivePath)) { |
| assertTrue(permissionProvider.isGranted(restr, null, Permissions.READ_ACCESS_CONTROL|Permissions.MODIFY_ACCESS_CONTROL)); |
| assertTrue(permissionProvider.isGranted(restr, propertyState, Permissions.READ_ACCESS_CONTROL|Permissions.MODIFY_ACCESS_CONTROL)); |
| } |
| } |
| } |
| |
| @Test |
| public void testIsGrantedOnRestrictionTree() throws Exception { |
| PrincipalPolicyImpl policy = getPrincipalPolicyImpl(testPrincipal, getAccessControlManager(root)); |
| Map<String, Value> restr = ImmutableMap.of(getNamePathMapper().getJcrName(REP_GLOB), getValueFactory(root).createValue(REP_RESTRICTIONS + "*")); |
| policy.addEntry(accessControlledPath, privilegesFromNames(JCR_READ_ACCESS_CONTROL), restr, ImmutableMap.of()); |
| root.commit(); |
| permissionProvider.refresh(); |
| |
| Tree policyTree = root.getTree(PathUtils.concat(accessControlledPath, REP_PRINCIPAL_POLICY)); |
| for (Tree child : policyTree.getChildren()) { |
| assertFalse(permissionProvider.isGranted(child, null, Permissions.READ)); |
| if (child.hasChild(REP_RESTRICTIONS)) { |
| Tree restrTree = child.getChild(REP_RESTRICTIONS); |
| assertTrue(permissionProvider.isGranted(restrTree, null, Permissions.READ_ACCESS_CONTROL)); |
| assertFalse(permissionProvider.isGranted(restrTree, null, Permissions.READ)); |
| assertFalse(permissionProvider.isGranted(restrTree, null, Permissions.READ_ACCESS_CONTROL|Permissions.MODIFY_ACCESS_CONTROL)); |
| for (PropertyState ps : restrTree.getProperties()) { |
| assertTrue(permissionProvider.isGranted(restrTree, ps, Permissions.READ_ACCESS_CONTROL)); |
| } |
| break; |
| } |
| } |
| } |
| |
| @Test |
| public void testIsGrantedByPath() throws Exception { |
| setupPrincipalBasedAccessControl(testPrincipal, accessControlledPath, JCR_READ, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL); |
| root.commit(); |
| permissionProvider.refresh(); |
| |
| assertTrue(permissionProvider.isGranted(accessControlledPath, Permissions.getString(Permissions.READ|Permissions.READ_ACCESS_CONTROL|Permissions.MODIFY_ACCESS_CONTROL))); |
| assertFalse(permissionProvider.isGranted(accessControlledPath, Permissions.getString(Permissions.READ|Permissions.WRITE))); |
| |
| String policyPath = PathUtils.concat(accessControlledPath, REP_PRINCIPAL_POLICY); |
| assertTrue(permissionProvider.isGranted(policyPath, Permissions.getString(Permissions.READ_PROPERTY|Permissions.READ_NODE|Permissions.READ_ACCESS_CONTROL|Permissions.MODIFY_ACCESS_CONTROL))); |
| |
| for (Tree child : root.getTree(policyPath).getChildren()) { |
| String childPath = child.getPath(); |
| String effectivePath = child.getProperty(REP_EFFECTIVE_PATH).getValue(STRING); |
| if (contentPath.equals(effectivePath)) { |
| assertTrue(permissionProvider.isGranted(childPath, Permissions.getString(Permissions.READ|Permissions.READ_ACCESS_CONTROL))); |
| assertFalse(permissionProvider.isGranted(childPath, Permissions.getString(Permissions.MODIFY_ACCESS_CONTROL))); |
| } else if (childPath.equals(effectivePath)) { |
| assertTrue(permissionProvider.isGranted(childPath, Permissions.getString(Permissions.READ|Permissions.READ_ACCESS_CONTROL))); |
| assertFalse(permissionProvider.isGranted(childPath, Permissions.getString(Permissions.READ|Permissions.MODIFY_ACCESS_CONTROL))); |
| } else if (child2Path.equals(effectivePath)) { |
| assertTrue(permissionProvider.isGranted(childPath, Permissions.getString(Permissions.READ|Permissions.READ_ACCESS_CONTROL))); |
| assertTrue(permissionProvider.isGranted(childPath, Permissions.getString(Permissions.READ|Permissions.MODIFY_ACCESS_CONTROL))); |
| } |
| } |
| } |
| |
| @Test |
| public void testGetPrivileges() throws Exception { |
| assertTrue(permissionProvider.getPrivileges(root.getTree(accessControlledPath)).isEmpty()); |
| Tree policyTree = root.getTree(PathUtils.concat(accessControlledPath, REP_PRINCIPAL_POLICY)); |
| assertTrue(permissionProvider.getPrivileges(policyTree).isEmpty()); |
| for (Tree child : policyTree.getChildren()) { |
| assertTrue(permissionProvider.getPrivileges(policyTree).isEmpty()); |
| } |
| |
| setupPrincipalBasedAccessControl(testPrincipal, accessControlledPath, JCR_READ); |
| root.commit(); |
| permissionProvider.refresh(); |
| |
| Set<String> expectedPrivNames = ImmutableSet.of(JCR_READ); |
| assertEquals(expectedPrivNames, permissionProvider.getPrivileges(root.getTree(accessControlledPath))); |
| policyTree = root.getTree(PathUtils.concat(accessControlledPath, REP_PRINCIPAL_POLICY)); |
| assertEquals(expectedPrivNames, permissionProvider.getPrivileges(policyTree)); |
| for (Tree child : policyTree.getChildren()) { |
| assertEquals(expectedPrivNames, permissionProvider.getPrivileges(policyTree)); |
| } |
| |
| setupPrincipalBasedAccessControl(testPrincipal, accessControlledPath, JCR_READ_ACCESS_CONTROL); |
| root.commit(); |
| permissionProvider.refresh(); |
| |
| expectedPrivNames = ImmutableSet.of(JCR_READ, JCR_READ_ACCESS_CONTROL); |
| assertEquals(expectedPrivNames, permissionProvider.getPrivileges(root.getTree(accessControlledPath))); |
| policyTree = root.getTree(PathUtils.concat(accessControlledPath, REP_PRINCIPAL_POLICY)); |
| assertEquals(expectedPrivNames, permissionProvider.getPrivileges(policyTree)); |
| for (Tree child : policyTree.getChildren()) { |
| assertEquals(ImmutableSet.of(JCR_READ, JCR_READ_ACCESS_CONTROL), permissionProvider.getPrivileges(child)); |
| } |
| |
| setupPrincipalBasedAccessControl(testPrincipal, accessControlledPath, JCR_MODIFY_ACCESS_CONTROL); |
| root.commit(); |
| permissionProvider.refresh(); |
| |
| expectedPrivNames = ImmutableSet.of(JCR_READ, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL); |
| assertEquals(expectedPrivNames, permissionProvider.getPrivileges(root.getTree(accessControlledPath))); |
| policyTree = root.getTree(PathUtils.concat(accessControlledPath, REP_PRINCIPAL_POLICY)); |
| assertEquals(expectedPrivNames, permissionProvider.getPrivileges(policyTree)); |
| for (Tree child : policyTree.getChildren()) { |
| String effectivePath = child.getProperty(REP_EFFECTIVE_PATH).getValue(STRING); |
| if (contentPath.equals(effectivePath)) { |
| assertEquals(ImmutableSet.of(JCR_READ, JCR_READ_ACCESS_CONTROL), permissionProvider.getPrivileges(child)); |
| } else if (childPath.equals(effectivePath)) { |
| assertEquals(ImmutableSet.of(JCR_READ, JCR_READ_ACCESS_CONTROL), permissionProvider.getPrivileges(child)); |
| } else if (child2Path.equals(effectivePath)) { |
| assertEquals(ImmutableSet.of(JCR_READ, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL), permissionProvider.getPrivileges(child)); |
| } |
| } |
| } |
| } |