You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by tr...@apache.org on 2015/09/04 18:40:16 UTC
svn commit: r1701290 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/security/authorization/permission/
test/java/org/apache/jackrabbit/oak/security/authorization/restriction/
Author: tripod
Date: Fri Sep 4 16:40:16 2015
New Revision: 1701290
URL: http://svn.apache.org/r1701290
Log:
OAK-3324 Evaluation with restriction is not consistent with parent ACLs
- fixed it, so that the behavior is consisten between single node privs and dual node privs
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/EntryPredicate.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionEntry.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/restriction/CustomRestrictionProviderTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/restriction/PermissionTest.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImpl.java?rev=1701290&r1=1701289&r2=1701290&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImpl.java Fri Sep 4 16:40:16 2015
@@ -145,7 +145,8 @@ final class CompiledPermissionImpl imple
return new RepositoryPermission() {
@Override
public boolean isGranted(long repositoryPermissions) {
- return hasPermissions(getEntryIterator(new EntryPredicate()), repositoryPermissions, null);
+ EntryPredicate predicate = new EntryPredicate();
+ return hasPermissions(getEntryIterator(predicate), predicate, repositoryPermissions, null);
}
};
}
@@ -242,8 +243,8 @@ final class CompiledPermissionImpl imple
@Override
public boolean isGranted(@Nonnull String path, long permissions) {
- Iterator<PermissionEntry> it = getEntryIterator(new EntryPredicate(path, Permissions.respectParentPermissions(permissions)));
- return hasPermissions(it, permissions, path);
+ EntryPredicate predicate = new EntryPredicate(path, Permissions.respectParentPermissions(permissions));
+ return hasPermissions(getEntryIterator(predicate), predicate, permissions, path);
}
@Nonnull
@@ -260,11 +261,12 @@ final class CompiledPermissionImpl imple
//------------------------------------------------------------< private >---
private boolean internalIsGranted(@Nonnull Tree tree, @Nullable PropertyState property, long permissions) {
- Iterator<PermissionEntry> it = getEntryIterator(tree, property, permissions);
- return hasPermissions(it, permissions, tree.getPath());
+ EntryPredicate predicate = new EntryPredicate(tree, property, Permissions.respectParentPermissions(permissions));
+ return hasPermissions(getEntryIterator(predicate), predicate, permissions, tree.getPath());
}
private boolean hasPermissions(@Nonnull Iterator<PermissionEntry> entries,
+ @Nonnull EntryPredicate predicate,
long permissions, @Nullable String path) {
// calculate readable paths if the given permissions includes any read permission.
boolean isReadable = Permissions.diff(Permissions.READ, permissions) != Permissions.READ && readPolicy.isReadablePath(path, false);
@@ -310,14 +312,18 @@ final class CompiledPermissionImpl imple
}
if (entry.isAllow) {
- allowBits.addDifference(entry.privilegeBits, denyBits);
+ if (!respectParent || predicate.apply(entry, false)) {
+ allowBits.addDifference(entry.privilegeBits, denyBits);
+ }
long ap = PrivilegeBits.calculatePermissions(allowBits, parentAllowBits, true);
allows |= Permissions.diff(ap, denies);
if ((allows | ~permissions) == -1) {
return true;
}
} else {
- denyBits.addDifference(entry.privilegeBits, allowBits);
+ if (!respectParent || predicate.apply(entry, false)) {
+ denyBits.addDifference(entry.privilegeBits, allowBits);
+ }
long dp = PrivilegeBits.calculatePermissions(denyBits, parentDenyBits, false);
denies |= Permissions.diff(dp, allows);
if (Permissions.includes(denies, permissions)) {
@@ -377,11 +383,6 @@ final class CompiledPermissionImpl imple
}
@Nonnull
- private Iterator<PermissionEntry> getEntryIterator(@Nonnull Tree tree, @Nullable PropertyState property, long permissions) {
- return getEntryIterator(new EntryPredicate(tree, property, Permissions.respectParentPermissions(permissions)));
- }
-
- @Nonnull
private Iterator<PermissionEntry> getEntryIterator(@Nonnull EntryPredicate predicate) {
Iterator<PermissionEntry> userEntries = userStore.getEntryIterator(predicate);
Iterator<PermissionEntry> groupEntries = groupStore.getEntryIterator(predicate);
@@ -526,12 +527,16 @@ final class CompiledPermissionImpl imple
@Override
public boolean isGranted(long permissions) {
- return hasPermissions(getIterator(null, permissions), permissions, tree.getPath());
+ EntryPredicate predicate = new EntryPredicate(tree, null, Permissions.respectParentPermissions(permissions));
+ Iterator<PermissionEntry> it = concat(new LazyIterator(this, true, predicate), new LazyIterator(this, false, predicate));
+ return hasPermissions(it, predicate, permissions, tree.getPath());
}
@Override
public boolean isGranted(long permissions, @Nonnull PropertyState property) {
- return hasPermissions(getIterator(property, permissions), permissions, tree.getPath());
+ EntryPredicate predicate = new EntryPredicate(tree, property, Permissions.respectParentPermissions(permissions));
+ Iterator<PermissionEntry> it = concat(new LazyIterator(this, true, predicate), new LazyIterator(this, false, predicate));
+ return hasPermissions(it, predicate, permissions, tree.getPath());
}
//--------------------------------------------------------< private >---
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/EntryPredicate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/EntryPredicate.java?rev=1701290&r1=1701289&r2=1701290&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/EntryPredicate.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/EntryPredicate.java Fri Sep 4 16:40:16 2015
@@ -37,6 +37,7 @@ final class EntryPredicate implements Pr
private final String parentPath;
private final Tree parent;
+ private final boolean respectParent;
public EntryPredicate(@Nonnull Tree tree, @Nullable PropertyState property,
boolean respectParent) {
@@ -64,6 +65,7 @@ final class EntryPredicate implements Pr
parentPath = null;
parent = null;
}
+ this.respectParent = parent != null || parentPath != null;
}
@CheckForNull
@@ -73,25 +75,22 @@ final class EntryPredicate implements Pr
@Override
public boolean apply(@Nullable PermissionEntry entry) {
+ return apply(entry, true);
+ }
+
+ public boolean apply(@Nullable PermissionEntry entry, boolean respectParent) {
if (entry == null) {
return false;
}
+ respectParent &= this.respectParent;
+
if (tree != null) {
- return entry.matches(tree, property) || applyToParent(entry);
+ return entry.matches(tree, property) || (respectParent && parent != null && entry.matches(parent, null));
} else if (path != null) {
- return entry.matches(path) || applyToParent(entry);
+ return entry.matches(path) || (respectParent && parentPath != null && entry.matches(parentPath));
} else {
return entry.matches();
}
}
- private boolean applyToParent(@Nonnull PermissionEntry entry) {
- if (parent != null) {
- return entry.matches(parent, null);
- } else if (parentPath != null) {
- return entry.matches(parentPath);
- } else {
- return false;
- }
- }
}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionEntry.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionEntry.java?rev=1701290&r1=1701289&r2=1701290&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionEntry.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionEntry.java Fri Sep 4 16:40:16 2015
@@ -122,4 +122,16 @@ final class PermissionEntry implements C
public int hashCode() {
return Objects.hashCode(privilegeBits, index, path, isAllow, restriction);
}
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("PermissionEntry{");
+ sb.append("isAllow=").append(isAllow);
+ sb.append(", privilegeBits=").append(privilegeBits);
+ sb.append(", index=").append(index);
+ sb.append(", path='").append(path).append('\'');
+ sb.append(", restriction=").append(restriction);
+ sb.append('}');
+ return sb.toString();
+ }
}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/restriction/CustomRestrictionProviderTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/restriction/CustomRestrictionProviderTest.java?rev=1701290&r1=1701289&r2=1701290&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/restriction/CustomRestrictionProviderTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/restriction/CustomRestrictionProviderTest.java Fri Sep 4 16:40:16 2015
@@ -54,7 +54,6 @@ import org.apache.jackrabbit.oak.util.No
import org.apache.jackrabbit.value.StringValue;
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import com.google.common.collect.ImmutableMap;
@@ -63,6 +62,10 @@ import static org.apache.jackrabbit.JcrC
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
+/**
+ * Test suite for a custom restriction provider. The restriction is enabled based on the (non) existence of a property.
+ * The test creates nodes along '/testRoot/a/b/c/d/e' and sets the 'protect-me' property on '/testRoot/a/b/c'.
+ */
public class CustomRestrictionProviderTest extends AbstractSecurityTest {
private static final String TEST_ROOT_PATH = "/testRoot";
@@ -145,12 +148,9 @@ public class CustomRestrictionProviderTe
* @throws Exception
*/
@Test
- @Ignore("OAK-3324")
public void testProtectByRestriction() throws Exception {
- // create permissions
// allow rep:write /testroot
- // deny jcr:removeNode /testroot/a hasProperty = protect-me
-
+ // deny jcr:removeNode /testroot/a hasProperty=protect-me
addEntry(TEST_ROOT_PATH, true, "", PrivilegeConstants.JCR_READ, PrivilegeConstants.REP_WRITE);
addEntry(TEST_A_PATH, false, PROP_NAME_PROTECT_ME, PrivilegeConstants.JCR_REMOVE_NODE);
@@ -158,11 +158,11 @@ public class CustomRestrictionProviderTe
try {
Root testRoot = testSession.getLatestRoot();
PermissionProvider pp = getPermissionProvider(testSession);
- assertIsGranted(pp, testRoot, true, TEST_A_PATH, Permissions.REMOVE_NODE);
- assertIsGranted(pp, testRoot, true, TEST_B_PATH, Permissions.REMOVE_NODE);
+ assertIsGranted(pp, testRoot, true , TEST_A_PATH, Permissions.REMOVE_NODE);
+ assertIsGranted(pp, testRoot, true , TEST_B_PATH, Permissions.REMOVE_NODE);
assertIsGranted(pp, testRoot, false, TEST_C_PATH, Permissions.REMOVE_NODE);
assertIsGranted(pp, testRoot, true , TEST_D_PATH, Permissions.REMOVE_NODE);
- assertIsGranted(pp, testRoot, true, TEST_E_PATH, Permissions.REMOVE_NODE);
+ assertIsGranted(pp, testRoot, true , TEST_E_PATH, Permissions.REMOVE_NODE);
// should be able to remove /a/b/c/d
testRoot.getTree(TEST_D_PATH).remove();
@@ -186,10 +186,8 @@ public class CustomRestrictionProviderTe
*/
@Test
public void testProtectPropertiesByRestriction() throws Exception {
- // create permissions
- // allow rep:write /testroot
- // deny jcr:modifyProperties /testroot/a hasProperty = protect-me
-
+ // allow rep:write /testroot
+ // deny jcr:modifyProperties /testroot/a hasProperty=protect-me
addEntry(TEST_ROOT_PATH, true, "", PrivilegeConstants.JCR_READ, PrivilegeConstants.REP_WRITE);
addEntry(TEST_A_PATH, false, PROP_NAME_PROTECT_ME, PrivilegeConstants.JCR_MODIFY_PROPERTIES);
@@ -199,10 +197,10 @@ public class CustomRestrictionProviderTe
PermissionProvider pp = getPermissionProvider(testSession);
assertIsGranted(pp, testRoot, true , TEST_A_PATH, Permissions.MODIFY_PROPERTY);
- assertIsGranted(pp, testRoot, true, TEST_B_PATH, Permissions.MODIFY_PROPERTY);
+ assertIsGranted(pp, testRoot, true , TEST_B_PATH, Permissions.MODIFY_PROPERTY);
assertIsGranted(pp, testRoot, false, TEST_C_PATH, Permissions.MODIFY_PROPERTY);
- assertIsGranted(pp, testRoot, true, TEST_D_PATH, Permissions.MODIFY_PROPERTY);
- assertIsGranted(pp, testRoot, true, TEST_E_PATH, Permissions.MODIFY_PROPERTY);
+ assertIsGranted(pp, testRoot, true , TEST_D_PATH, Permissions.MODIFY_PROPERTY);
+ assertIsGranted(pp, testRoot, true , TEST_E_PATH, Permissions.MODIFY_PROPERTY);
} finally {
testSession.close();
@@ -210,17 +208,14 @@ public class CustomRestrictionProviderTe
}
/**
- * Tests the custom restriction provider that checks on the existence of a property.
+ * Tests the custom restriction provider that checks on the absence of a property.
* @throws Exception
*/
@Test
- @Ignore("OAK-3324")
public void testUnProtectByRestriction() throws Exception {
- // create permissions
// allow rep:write /testroot
// deny jcr:removeNode /testroot
- // allow jcr:removeNode /testroot/a hasProperty = !protect-me
-
+ // allow jcr:removeNode /testroot/a hasProperty=!protect-me
addEntry(TEST_ROOT_PATH, true, "", PrivilegeConstants.JCR_READ, PrivilegeConstants.REP_WRITE);
addEntry(TEST_ROOT_PATH, false, "", PrivilegeConstants.JCR_REMOVE_NODE);
addEntry(TEST_A_PATH, true, "!" + PROP_NAME_PROTECT_ME, PrivilegeConstants.JCR_REMOVE_NODE);
@@ -229,17 +224,20 @@ public class CustomRestrictionProviderTe
try {
Root testRoot = testSession.getLatestRoot();
PermissionProvider pp = getPermissionProvider(testSession);
- assertIsGranted(pp, testRoot, true, TEST_A_PATH, Permissions.REMOVE_NODE);
- assertIsGranted(pp, testRoot, true, TEST_B_PATH, Permissions.REMOVE_NODE);
+ assertIsGranted(pp, testRoot, true , TEST_A_PATH, Permissions.REMOVE_NODE);
+ assertIsGranted(pp, testRoot, true , TEST_B_PATH, Permissions.REMOVE_NODE);
assertIsGranted(pp, testRoot, false, TEST_C_PATH, Permissions.REMOVE_NODE);
- assertIsGranted(pp, testRoot, true, TEST_D_PATH, Permissions.REMOVE_NODE);
- assertIsGranted(pp, testRoot, true, TEST_E_PATH, Permissions.REMOVE_NODE);
+ assertIsGranted(pp, testRoot, true , TEST_D_PATH, Permissions.REMOVE_NODE);
+ assertIsGranted(pp, testRoot, true , TEST_E_PATH, Permissions.REMOVE_NODE);
} finally {
testSession.close();
}
}
+ /**
+ * Customs restriction provider that matches restrictions based on the existence of a property.
+ */
public static class PropertyRestrictionProvider extends AbstractRestrictionProvider {
public static final String RESTRICTION_NAME = "hasProperty";
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/restriction/PermissionTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/restriction/PermissionTest.java?rev=1701290&r1=1701289&r2=1701290&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/restriction/PermissionTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/restriction/PermissionTest.java Fri Sep 4 16:40:16 2015
@@ -51,6 +51,7 @@ public class PermissionTest extends Abst
private static final String TEST_B_PATH = "/testRoot/a/b";
private static final String TEST_C_PATH = "/testRoot/a/b/c";
private static final String TEST_D_PATH = "/testRoot/a/b/c/d";
+ private static final String TEST_E_PATH = "/testRoot/a/b/c/d/e";
private Principal testPrincipal;
@@ -64,7 +65,8 @@ public class PermissionTest extends Abst
NodeUtil a = testRootNode.addChild("a", NT_UNSTRUCTURED);
NodeUtil b = a.addChild("b", NT_UNSTRUCTURED);
NodeUtil c = b.addChild("c", NT_UNSTRUCTURED);
- c.addChild("d", NT_UNSTRUCTURED);
+ NodeUtil d = c.addChild("d", NT_UNSTRUCTURED);
+ d.addChild("e", NT_UNSTRUCTURED);
root.commit();
testPrincipal = getTestUser().getPrincipal();
@@ -152,7 +154,6 @@ public class PermissionTest extends Abst
* of /a/b/c yields a deny, which terminates the iteration.
*/
@Test
- @Ignore("OAK-3324")
public void testHasPermissionWithRestrictions() throws Exception {
// create permissions
// allow rep:write /testroot
@@ -172,6 +173,7 @@ public class PermissionTest extends Abst
assertIsGranted(pp, testRoot, true, TEST_B_PATH, Permissions.REMOVE_NODE);
assertIsGranted(pp, testRoot, false, TEST_C_PATH, Permissions.REMOVE_NODE);
assertIsGranted(pp, testRoot, true, TEST_D_PATH, Permissions.REMOVE_NODE);
+ assertIsGranted(pp, testRoot, true, TEST_E_PATH, Permissions.REMOVE_NODE);
// should be able to remove /a/b/c/d
testRoot.getTree(TEST_D_PATH).remove();
@@ -197,7 +199,6 @@ public class PermissionTest extends Abst
* since the 'deny' on /a/b is after the 'allow' on a/b/c, the deny wins.
*/
@Test
- @Ignore("OAK-3324")
public void testHasPermissionWithRestrictions2() throws Exception {
// create permissions
// allow rep:write /testroot
@@ -236,4 +237,35 @@ public class PermissionTest extends Abst
testSession.close();
}
}
+
+ /**
+ * Tests the custom restriction provider that checks on the existence of a property.
+ * @throws Exception
+ */
+ @Test
+ public void testProtectPropertiesByRestriction() throws Exception {
+ // create permissions
+ // allow rep:write /testroot
+ // deny jcr:modifyProperties /testroot/a glob = */c
+
+ addEntry(TEST_ROOT_PATH, true, "", PrivilegeConstants.JCR_READ, PrivilegeConstants.REP_WRITE);
+ addEntry(TEST_A_PATH, false, "*/c", PrivilegeConstants.JCR_MODIFY_PROPERTIES);
+
+ ContentSession testSession = createTestSession();
+ try {
+ Root testRoot = testSession.getLatestRoot();
+
+ PermissionProvider pp = getPermissionProvider(testSession);
+ assertIsGranted(pp, testRoot, true , TEST_A_PATH, Permissions.MODIFY_PROPERTY);
+ assertIsGranted(pp, testRoot, true, TEST_B_PATH, Permissions.MODIFY_PROPERTY);
+ assertIsGranted(pp, testRoot, false, TEST_C_PATH, Permissions.MODIFY_PROPERTY);
+ assertIsGranted(pp, testRoot, true, TEST_D_PATH, Permissions.MODIFY_PROPERTY);
+ assertIsGranted(pp, testRoot, true, TEST_E_PATH, Permissions.MODIFY_PROPERTY);
+
+ } finally {
+ testSession.close();
+ }
+ }
+
+
}
\ No newline at end of file