blob: ba0188d198d16bec3e3b832f46ecdca93aad0971 [file] [log] [blame]
/*
* 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.cug.impl;
import java.util.Set;
import javax.jcr.security.AccessControlManager;
import javax.jcr.security.AccessControlPolicy;
import com.google.common.collect.ImmutableSet;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.plugins.tree.RootProvider;
import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
import org.apache.jackrabbit.oak.spi.security.authorization.cug.CugPolicy;
import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
import org.jetbrains.annotations.NotNull;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.apache.jackrabbit.oak.commons.PathUtils.ROOT_PATH;
public class NestedCugHookTest extends AbstractCugTest {
protected static void assertNestedCugs(@NotNull Root root, @NotNull RootProvider rootProvider,
@NotNull String cugHoldingPath, boolean hasCugPolicy, @NotNull String... expectedNestedPaths) {
Root immutableRoot = rootProvider.createReadOnlyRoot(root);
Tree tree = immutableRoot.getTree(cugHoldingPath);
if (hasCugPolicy) {
assertFalse(tree.hasProperty(HIDDEN_NESTED_CUGS));
tree = tree.getChild(REP_CUG_POLICY);
}
assertTrue(tree.exists());
if (tree.isRoot()) {
if (expectedNestedPaths.length == 0) {
assertFalse(tree.hasProperty(HIDDEN_TOP_CUG_CNT));
} else {
assertTrue(tree.hasProperty(HIDDEN_TOP_CUG_CNT));
assertEquals(Long.valueOf(expectedNestedPaths.length), tree.getProperty(HIDDEN_TOP_CUG_CNT).getValue(Type.LONG));
}
} else {
assertFalse(tree.hasProperty(HIDDEN_TOP_CUG_CNT));
}
if (expectedNestedPaths.length == 0) {
assertFalse(tree.hasProperty(HIDDEN_NESTED_CUGS));
} else {
assertTrue(tree.hasProperty(HIDDEN_NESTED_CUGS));
PropertyState nestedCugs = tree.getProperty(HIDDEN_NESTED_CUGS);
assertNotNull(nestedCugs);
Set<String> nestedPaths = ImmutableSet.copyOf(nestedCugs.getValue(Type.PATHS));
assertEquals(ImmutableSet.copyOf(expectedNestedPaths), nestedPaths);
}
}
protected boolean removeCug(@NotNull String path, boolean doCommit) throws Exception {
AccessControlManager acMgr = getAccessControlManager(root);
for (AccessControlPolicy policy : acMgr.getPolicies(path)) {
if (policy instanceof CugPolicy) {
acMgr.removePolicy(path, policy);
if (doCommit) {
root.commit();
}
return true;
}
}
return false;
}
@Test
public void testToString() {
assertEquals("NestedCugHook", new NestedCugHook().toString());
}
@Test
public void testAddCug() throws Exception {
createCug("/content", getTestGroupPrincipal());
root.commit();
assertNestedCugs(root, getRootProvider(), "/", false, "/content");
assertNestedCugs(root, getRootProvider(), "/content", true);
}
@Test
public void testAddNestedCug() throws Exception {
// create cugs
// - /content/a : allow testGroup, deny everyone
// - /content/aa/bb : allow testGroup, deny everyone
// - /content/a/b/c : allow everyone, deny testGroup (isolated)
// - /content2 : allow everyone, deny testGroup (isolated)
setupCugsAndAcls();
assertNestedCugs(root, getRootProvider(), ROOT_PATH, false, "/content/a", "/content/aa/bb", "/content2");
assertNestedCugs(root, getRootProvider(), "/content/a", true, "/content/a/b/c");
// add CUG at /content after having created CUGs in the subtree
createCug("/content", EveryonePrincipal.getInstance());
root.commit();
assertNestedCugs(root, getRootProvider(), ROOT_PATH, false, "/content", "/content2");
assertNestedCugs(root, getRootProvider(), "/content", true, "/content/a", "/content/aa/bb");
assertNestedCugs(root, getRootProvider(), "/content/a", true, "/content/a/b/c");
}
@Test
public void testAddNodeWithCug() throws Exception {
createCug(SUPPORTED_PATH2, EveryonePrincipal.getInstance());
Tree newTree = TreeUtil.addChild(root.getTree(SUPPORTED_PATH2), "child", NT_OAK_UNSTRUCTURED);
String path = newTree.getPath();
createCug(path, getTestGroupPrincipal());
root.commit();
assertNestedCugs(root, getRootProvider(), ROOT_PATH, false, SUPPORTED_PATH2);
assertNestedCugs(root, getRootProvider(), SUPPORTED_PATH2, true, path);
}
@Test
public void testAddNodeWithCugManually() throws Exception {
createCug(root, SUPPORTED_PATH3, EveryonePrincipal.NAME);
Tree newTree = TreeUtil.addChild(root.getTree(SUPPORTED_PATH3), "child", NT_OAK_UNSTRUCTURED);
String path = newTree.getPath();
createCug(root, path, getTestGroupPrincipal().getName());
root.commit();
assertNestedCugs(root, getRootProvider(), ROOT_PATH, false, SUPPORTED_PATH3);
assertNestedCugs(root, getRootProvider(), SUPPORTED_PATH3, true, path);
}
@Test
public void testAddAtUnsupportedPath() throws Exception {
String unsupportedPath = UNSUPPORTED_PATH + "/child";
createCug(root, unsupportedPath, EveryonePrincipal.NAME);
root.commit();
assertNestedCugs(root, getRootProvider(), ROOT_PATH, false, unsupportedPath);
}
@Test
public void testAddAtRoot() throws Exception {
createCug(root, ROOT_PATH, EveryonePrincipal.NAME);
root.commit();
assertTrue(root.getTree(ROOT_PATH).hasChild(REP_CUG_POLICY));
createCug("/content", getTestGroupPrincipal());
createCug("/content2", EveryonePrincipal.getInstance());
root.commit();
assertNestedCugs(root, getRootProvider(), ROOT_PATH, true, "/content", "/content2");
}
@Test
public void testRemoveCug() throws Exception {
// create cugs at /content
createCug("/content", getTestGroupPrincipal());
root.commit();
// remove CUG at /content
assertTrue(removeCug("/content", true));
assertNestedCugs(root, getRootProvider(), ROOT_PATH, false);
}
@Test
public void testRemoveNestedCug() throws Exception {
// create cugs
// - /content/a : allow testGroup, deny everyone
// - /content/aa/bb : allow testGroup, deny everyone
// - /content/a/b/c : allow everyone, deny testGroup (isolated)
// - /content2 : allow everyone, deny testGroup (isolated)
setupCugsAndAcls();
// remove CUG at /content/a/b/c
assertTrue(removeCug("/content/a/b/c", true));
assertNestedCugs(root, getRootProvider(), ROOT_PATH, false, "/content/a", "/content/aa/bb", "/content2");
assertNestedCugs(root, getRootProvider(), "/content/a", true);
}
@Test
public void testRemoveIntermediateCug() throws Exception {
// create cugs
// - /content/a : allow testGroup, deny everyone
// - /content/aa/bb : allow testGroup, deny everyone
// - /content/a/b/c : allow everyone, deny testGroup (isolated)
// - /content2 : allow everyone, deny testGroup (isolated)
setupCugsAndAcls();
// remove CUG at /content/a
assertTrue(removeCug("/content/a", true));
assertNestedCugs(root, getRootProvider(), ROOT_PATH, false, "/content/aa/bb", "/content2", "/content/a/b/c");
assertFalse(root.getTree("/content/a").hasChild(REP_CUG_POLICY));
}
@Test
public void testRemoveMultipleCug() throws Exception {
// create cugs
// - /content/a : allow testGroup, deny everyone
// - /content/aa/bb : allow testGroup, deny everyone
// - /content/a/b/c : allow everyone, deny testGroup (isolated)
// - /content2 : allow everyone, deny testGroup (isolated)
setupCugsAndAcls();
assertTrue(removeCug("/content/a", false));
assertTrue(removeCug("/content/aa/bb", false));
root.commit();
assertNestedCugs(root, getRootProvider(), ROOT_PATH, false, "/content2", "/content/a/b/c");
}
@Test
public void testRemoveMultipleCug2() throws Exception {
// create cugs
// - /content/a : allow testGroup, deny everyone
// - /content/aa/bb : allow testGroup, deny everyone
// - /content/a/b/c : allow everyone, deny testGroup (isolated)
// - /content2 : allow everyone, deny testGroup (isolated)
setupCugsAndAcls();
assertTrue(removeCug("/content/a", false));
assertTrue(removeCug("/content/a/b/c", false));
root.commit();
assertNestedCugs(root, getRootProvider(), ROOT_PATH, false, "/content/aa/bb", "/content2");
}
@Test
public void testRemoveContentNode() throws Exception {
// create cugs
// - /content/a : allow testGroup, deny everyone
// - /content/aa/bb : allow testGroup, deny everyone
// - /content/a/b/c : allow everyone, deny testGroup (isolated)
// - /content2 : allow everyone, deny testGroup (isolated)
setupCugsAndAcls();
root.getTree("/content").remove();
root.commit();
assertNestedCugs(root, getRootProvider(), ROOT_PATH, false, "/content2");
}
@Test
public void testRemoveContentANode() throws Exception {
// create cugs
// - /content/a : allow testGroup, deny everyone
// - /content/aa/bb : allow testGroup, deny everyone
// - /content/a/b/c : allow everyone, deny testGroup (isolated)
// - /content2 : allow everyone, deny testGroup (isolated)
setupCugsAndAcls();
root.getTree("/content/a").remove();
root.commit();
assertNestedCugs(root, getRootProvider(), ROOT_PATH, false, "/content2", "/content/aa/bb");
}
@Test
public void testRemoveRootCug() throws Exception {
// add cug at /
createCug(root, ROOT_PATH, EveryonePrincipal.NAME);
createCug("/content", getTestGroupPrincipal());
createCug("/content2", EveryonePrincipal.getInstance());
root.commit();
assertTrue(root.getTree(PathUtils.concat(ROOT_PATH, REP_CUG_POLICY)).remove());
root.commit();
assertNestedCugs(root, getRootProvider(), ROOT_PATH, false, "/content", "/content2");
assertTrue(removeCug("/content", true));
assertNestedCugs(root, getRootProvider(), ROOT_PATH, false, "/content2");
assertTrue(removeCug("/content2", true));
assertNestedCugs(root, getRootProvider(), ROOT_PATH, false);
}
@Test
public void testRemoveAndReadd() throws Exception {
createCug(root, SUPPORTED_PATH3, EveryonePrincipal.NAME);
Tree newTree = TreeUtil.addChild(root.getTree(SUPPORTED_PATH3), "child", NT_OAK_UNSTRUCTURED);
String path = newTree.getPath();
createCug(path, getTestGroupPrincipal());
root.commit();
assertNestedCugs(root, getRootProvider(), ROOT_PATH, false, SUPPORTED_PATH3);
assertNestedCugs(root, getRootProvider(), SUPPORTED_PATH3, true, path);
removeCug(path, false);
createCug(path, EveryonePrincipal.getInstance());
root.commit();
assertNestedCugs(root, getRootProvider(), SUPPORTED_PATH3, true, path);
}
@Test
public void testMoveToUnsupportedPath() throws Exception {
createCug(root, SUPPORTED_PATH3, EveryonePrincipal.NAME);
Tree newTree = TreeUtil.addChild(root.getTree(SUPPORTED_PATH3), "child", NT_OAK_UNSTRUCTURED);
String path = newTree.getPath();
createCug(path, getTestGroupPrincipal());
root.commit();
String destPath = PathUtils.concat(UNSUPPORTED_PATH, "moved");
root.move(path, destPath);
root.commit();
assertNestedCugs(root, getRootProvider(), SUPPORTED_PATH3, true);
assertNestedCugs(root, getRootProvider(), ROOT_PATH, false, SUPPORTED_PATH3, destPath);
}
@Test
public void testMoveToSupportedPath() throws Exception {
createCug(root, SUPPORTED_PATH3, EveryonePrincipal.NAME);
Tree newTree = TreeUtil.addChild(root.getTree(SUPPORTED_PATH3), "child", NT_OAK_UNSTRUCTURED);
String path = newTree.getPath();
createCug(path, getTestGroupPrincipal());
root.commit();
String destPath = PathUtils.concat(SUPPORTED_PATH, "moved");
root.move(path, destPath);
root.commit();
assertNestedCugs(root, getRootProvider(), SUPPORTED_PATH3, true);
assertNestedCugs(root, getRootProvider(), ROOT_PATH, false, SUPPORTED_PATH3, destPath);
}
@Test
public void testMoveToNested() throws Exception {
createCug(root, SUPPORTED_PATH2, EveryonePrincipal.NAME);
createCug(root, SUPPORTED_PATH3, EveryonePrincipal.NAME);
Tree newTree = TreeUtil.addChild(root.getTree(SUPPORTED_PATH3), "child", NT_OAK_UNSTRUCTURED);
String path = newTree.getPath();
createCug(path, getTestGroupPrincipal());
root.commit();
String destPath = PathUtils.concat(SUPPORTED_PATH2, "moved");
root.move(path, destPath);
root.commit();
assertNestedCugs(root, getRootProvider(), ROOT_PATH, false, SUPPORTED_PATH3, SUPPORTED_PATH2);
assertNestedCugs(root, getRootProvider(), SUPPORTED_PATH3, true);
assertNestedCugs(root, getRootProvider(), SUPPORTED_PATH2, true, destPath);
}
}