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 an...@apache.org on 2020/08/19 13:56:53 UTC

svn commit: r1880990 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/ oak-doc/src/site/markdown/security/authorization/ oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authori...

Author: angela
Date: Wed Aug 19 13:56:53 2020
New Revision: 1880990

URL: http://svn.apache.org/viewvc?rev=1880990&view=rev
Log:
OAK-9179 : Documentation (and comments) about rep:glob patterns in ACE restriction is confusing

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/GlobPattern.java
    jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/authorization/restriction.md
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/ReadWithGlobRestrictionTest.java
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/WriteRestrictionTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/GlobPattern.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/GlobPattern.java?rev=1880990&r1=1880989&r2=1880990&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/GlobPattern.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/GlobPattern.java Wed Aug 19 13:56:53 2020
@@ -42,8 +42,8 @@ import static com.google.common.base.Pre
  * <pre>
  * NodePath     |   Restriction   |   Matches
  * -----------------------------------------------------------------------------
- * /foo         |   null          |   matches /foo and all children of /foo
- * /foo         |   ""            |   matches /foo only
+ * /foo         |   null          |   matches /foo and all descendants of /foo
+ * /foo         |   ""            |   matches /foo only (no descendants, not even properties)
  * </pre>
  * </p>
  *
@@ -53,10 +53,10 @@ import static com.google.common.base.Pre
  * NodePath = "/foo"
  * Restriction   |   Matches
  * -----------------------------------------------------------------------------
- * /cat          |   the node /foo/cat and all it's children
- * /cat/         |   the descendants of the node /foo/cat
- * cat           |   the node /foocat and all it's children
- * cat/          |   all descendants of the node /foocat
+ * /cat          |   '/foo/cat' and all it's descendants
+ * /cat/         |   all descendants of '/foo/cat'
+ * cat           |   '/foocat' and all it's descendants
+ * cat/          |   all descendants of '/foocat'
  * </pre>
  * </p>
  *
@@ -67,7 +67,7 @@ import static com.google.common.base.Pre
  * Restriction   |   Matches
  * -----------------------------------------------------------------------------
  * &#42;         |   foo, all siblings of foo and their descendants
- * /&#42;cat     |   all children of /foo whose path ends with "cat"
+ * /&#42;cat     |   all descendants of /foo whose path ends with "cat"
  * /&#42;/cat    |   all non-direct descendants of /foo named "cat"
  * /cat&#42;     |   all descendant path of /foo that have the direct foo-descendant segment starting with "cat"
  * &#42;cat      |   all siblings and descendants of foo that have a name ending with cat

Modified: jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/authorization/restriction.md
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/authorization/restriction.md?rev=1880990&r1=1880989&r2=1880990&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/authorization/restriction.md (original)
+++ jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/authorization/restriction.md Wed Aug 19 13:56:53 2020
@@ -130,15 +130,15 @@ Consequently the examples below need to
 
 | rep:glob      | Result                                                   |
 |---------------|----------------------------------------------------------|
-| null          | i.e. no restriction: matches /foo and all children       |
-| ""            | matches node /foo only                                   |
+| null          | i.e. no restriction: matches /foo and all descendants    |
+| ""            | matches node /foo only (no descendants, not even properties) |
 
 Examples including wildcard char:
 
 | rep:glob      | Result                                                   |
 |---------------|----------------------------------------------------------|
 | \*            | foo, siblings of foo and their descendants               |
-| /\*cat        | all child items of /foo whose paths end with 'cat'       |
+| /\*cat        | all descendants of /foo whose paths end with 'cat'       |
 | \*cat         | all siblings and descendants of foo that have a name ending with 'cat' |
 | /\*/cat       | all non-direct descendants of /foo named 'cat'           |
 | /cat\*        | all descendant of /foo that have the direct foo-descendant segment starting with 'cat' |
@@ -151,12 +151,12 @@ Examples without wildcard char:
 
 | rep:glob      | Result                                                   |
 |---------------|----------------------------------------------------------|
-| /cat          |   the node /foo/cat and all it's child items             |
-| /cat/         |   the descendants of the node /foo/cat                   |
-| cat           |   the node /foocat and all it's child items              |
-| cat/          |   all descendants of the node /foocat                    |
+| /cat          | '/foo/cat' and all it's descendants                      |
+| /cat/         | all descendants of '/foo/cat'                            |
+| cat           | '/foocat' and all it's descendants                       |
+| cat/          | all descendants of '/foocat'                             |
 
-See also [GlobPattern] for implementation details.
+See also [GlobPattern] for implementation details and the [GlobRestrictionTest] in the _oak-exercise_ module for training material.
 
 <a name="representation"></a>
 ### Representation in the Repository
@@ -194,6 +194,7 @@ implementation:
 
 - implement `RestrictionProvider` interface exposing your custom restriction(s).
 - make the provider implementation an OSGi service and make it available to the Oak repository.
+- make sure the `RestrictionProvider` is listed as required service with the `SecurityProvider` (see also [Introduction](../introduction.html#configuration]))
 
 Please make sure to consider the following recommendations when implementing a custom `RestrictionProvider`:
 - restrictions are part of the overall permission evaluation and thus may heavily impact overall read/write performance
@@ -302,6 +303,7 @@ The time-based `RestrictionPattern` used
 
 <!-- hidden references -->
 [GlobPattern]: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/GlobPattern.java?view=markup
+[GlobRestrictionTest]: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/accesscontrol/L8_GlobRestrictionTest.java?view=markup
 [Restriction]: /oak/docs/apidocs/org/apache/jackrabbit/oak/spi/security/authorization/restriction/Restriction.html
 [RestrictionDefinition]: /oak/docs/apidocs/org/apache/jackrabbit/oak/spi/security/authorization/restriction/RestrictionDefinition.html
 [RestrictionPattern]: /oak/docs/apidocs/org/apache/jackrabbit/oak/spi/security/authorization/restriction/RestrictionPattern.html

Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/ReadWithGlobRestrictionTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/ReadWithGlobRestrictionTest.java?rev=1880990&r1=1880989&r2=1880990&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/ReadWithGlobRestrictionTest.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/ReadWithGlobRestrictionTest.java Wed Aug 19 13:56:53 2020
@@ -20,16 +20,29 @@ import java.security.Principal;
 import java.util.HashSet;
 import java.util.Set;
 import javax.jcr.Node;
+import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.security.Privilege;
 
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
 import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.junit.Test;
 
 public class ReadWithGlobRestrictionTest extends AbstractEvaluationTest {
 
+    private String ccPath;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        Node grandchild = superuser.getNode(childNPath).addNode("child");
+        ccPath = grandchild.getPath();
+        superuser.save();
+    }
+
     @Test
     public void testGlobRestriction() throws Exception {
         deny(path, readPrivileges, createGlobRestriction("*/" + jcrPrimaryType));
@@ -64,7 +77,7 @@ public class ReadWithGlobRestrictionTest
             allow(path, group2.getPrincipal(), readPrivs);
             deny(path, group3.getPrincipal(), readPrivs);
 
-            Set<Principal> principals = new HashSet<Principal>();
+            Set<Principal> principals = new HashSet<>();
             principals.add(getTestGroup().getPrincipal());
             principals.add(group2.getPrincipal());
             principals.add(group3.getPrincipal());
@@ -155,11 +168,7 @@ public class ReadWithGlobRestrictionTest
      * @see <a href="https://issues.apache.org/jira/browse/OAK-2412">OAK-2412</a>
      */
     @Test
-    public void testEmptyGlobRestriction() throws Exception{
-        Node grandchild = superuser.getNode(childNPath).addNode("child");
-        String ccPath = grandchild.getPath();
-        superuser.save();
-
+    public void testEmptyGlobRestriction() throws Exception {
         // first deny access to 'path' (read-access is granted in the test setup)
         deny(path, readPrivileges);
         assertFalse(canReadNode(testSession, path));
@@ -184,10 +193,6 @@ public class ReadWithGlobRestrictionTest
      */
     @Test
     public void testEmptyGlobRestriction2() throws Exception{
-        Node grandchild = superuser.getNode(childNPath).addNode("child");
-        String ccPath = grandchild.getPath();
-        superuser.save();
-
         // first deny access to 'path' (read-access is granted in the test setup)
         deny(path, readPrivileges);
         assertFalse(canReadNode(testSession, path));
@@ -268,4 +273,34 @@ public class ReadWithGlobRestrictionTest
         assertTrue(canReadNode(testSession, n121.getPath()));
         assertTrue(canReadNode(testSession, n122.getPath()));
     }
+
+    /**
+     * OAK-9179
+     */
+    @Test
+    public void testGlobTrailingSlash() throws Exception {
+        // first deny access to 'path' (read-access is granted in the test setup)
+        deny(path, readPrivileges);
+        allow(path, readPrivileges, createGlobRestriction("/"+PathUtils.getName(childNPath) + "/"));
+        assertGlobTrailingSlashEffect();
+    }
+
+    /**
+     * OAK-9179
+     */
+    @Test
+    public void testGlobTrailingSlashWildcard() throws Exception {
+        // first deny access to 'path' (read-access is granted in the test setup)
+        deny(path, readPrivileges);
+        allow(path, readPrivileges, createGlobRestriction("/"+PathUtils.getName(childNPath) + "/*"));
+        assertGlobTrailingSlashEffect();
+    }
+
+    private void assertGlobTrailingSlashEffect() throws RepositoryException {
+        assertFalse(canReadNode(testSession, path));
+        assertFalse(canReadNode(testSession, path+"/"));
+        assertFalse(canReadNode(testSession, childNPath));
+        assertTrue(canReadNode(testSession, ccPath));
+        assertTrue(testSession.propertyExists(childchildPPath));
+    }
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/WriteRestrictionTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/WriteRestrictionTest.java?rev=1880990&r1=1880989&r2=1880990&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/WriteRestrictionTest.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/WriteRestrictionTest.java Wed Aug 19 13:56:53 2020
@@ -18,14 +18,19 @@ package org.apache.jackrabbit.oak.jcr.se
 
 import javax.jcr.AccessDeniedException;
 import javax.jcr.Node;
+import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.security.Privilege;
 
-import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.test.api.util.Text;
 import org.junit.Before;
 import org.junit.Test;
 
+import static javax.jcr.security.Privilege.JCR_ADD_CHILD_NODES;
+import static javax.jcr.security.Privilege.JCR_REMOVE_CHILD_NODES;
+import static javax.jcr.security.Privilege.JCR_REMOVE_NODE;
+
 /**
  * WriteRestrictionTest: tests add and remove node in combination with glob restrictions.
  */
@@ -68,8 +73,8 @@ public class WriteRestrictionTest extend
     @Test
     public void testGlobRestriction2() throws Exception {
 
-        Privilege[] addNode = privilegesFromName(Privilege.JCR_ADD_CHILD_NODES);
-        Privilege[] rmNode = privilegesFromName(Privilege.JCR_REMOVE_NODE);
+        Privilege[] addNode = privilegesFromName(JCR_ADD_CHILD_NODES);
+        Privilege[] rmNode = privilegesFromName(JCR_REMOVE_NODE);
 
         // permissions defined @ path
         // restriction: grants write-priv to nodeName3 grand-children but not direct nodeName3 children.
@@ -84,7 +89,7 @@ public class WriteRestrictionTest extend
 
     @Test
     public void testGlobRestriction3() throws Exception {
-        Privilege[] addNode = privilegesFromName(Privilege.JCR_ADD_CHILD_NODES);
+        Privilege[] addNode = privilegesFromName(JCR_ADD_CHILD_NODES);
 
         // permissions defined @ path
         // restriction: allows write to nodeName3 children
@@ -104,7 +109,7 @@ public class WriteRestrictionTest extend
 
     @Test
     public void testGlobRestriction4() throws Exception {
-        Privilege[] addNode = privilegesFromName(Privilege.JCR_ADD_CHILD_NODES);
+        Privilege[] addNode = privilegesFromName(JCR_ADD_CHILD_NODES);
 
         allow(path, repWritePrivileges, createGlobRestriction("/*"+nodeName3));
         deny(childNPath2, addNode);
@@ -122,7 +127,7 @@ public class WriteRestrictionTest extend
         /* allow READ/WRITE privilege for testUser at 'path' */
         allow(path, testUser.getPrincipal(), readWritePrivileges);
         /* deny REMOVE_NODE privileges at subtree. */
-        deny(path, privilegesFromName(PrivilegeConstants.JCR_REMOVE_NODE), createGlobRestriction("*/" + nodeName3));
+        deny(path, privilegesFromName(JCR_REMOVE_NODE), createGlobRestriction("*/" + nodeName3));
 
         testSession.getNode(childNPath).getNode(nodeName3).remove();
         try {
@@ -138,7 +143,7 @@ public class WriteRestrictionTest extend
         /* allow READ/WRITE privilege for testUser at 'path' */
         allow(path, testUser.getPrincipal(), readWritePrivileges);
         /* deny REMOVE_NODE privileges at subtree. */
-        deny(path, privilegesFromName(PrivilegeConstants.JCR_REMOVE_CHILD_NODES), createGlobRestriction("*/" + Text.getName(childNPath)));
+        deny(path, privilegesFromName(JCR_REMOVE_CHILD_NODES), createGlobRestriction("*/" + Text.getName(childNPath)));
 
         testSession.getNode(childNPath).getNode(nodeName3).remove();
         try {
@@ -154,7 +159,7 @@ public class WriteRestrictionTest extend
         /* allow READ/WRITE privilege for testUser at 'path' */
         allow(path, testUser.getPrincipal(), readWritePrivileges);
         /* deny ADD_CHILD_NODES privileges at subtree. */
-        deny(path, privilegesFromName(PrivilegeConstants.JCR_ADD_CHILD_NODES), createGlobRestriction("*/"+nodeName3));
+        deny(path, privilegesFromName(JCR_ADD_CHILD_NODES), createGlobRestriction("*/"+nodeName3));
 
         Node node4 = testSession.getNode(nodePath3).addNode(nodeName4);
         try {
@@ -164,4 +169,43 @@ public class WriteRestrictionTest extend
             // success
         }
     }
+
+    /**
+     * OAK-9179
+     */
+    @Test
+    public void testGlobTrailingSlash() throws Exception {
+        Node grandchild = superuser.getNode(childNPath).addNode("child");
+        String ccPath = grandchild.getPath();
+
+        // allow ADD_CHILD_NODES privileges at '/cat/' -> matches descendants of childNPath
+        allow(path, privilegesFromName(JCR_ADD_CHILD_NODES), createGlobRestriction("/"+PathUtils.getName(childNPath) + "/"));
+        assertGlobTrailingSlashEffect(ccPath);
+    }
+
+    /**
+     * OAK-9179
+     */
+    @Test
+    public void testGlobTrailingSlashWildcard() throws Exception {
+        Node grandchild = superuser.getNode(childNPath).addNode("grandchild");
+        String ccPath = grandchild.getPath();
+
+        // allow ADD_CHILD_NODES privileges at '/cat/*' -> matches descendants of childNPath
+        allow(path, privilegesFromName(JCR_ADD_CHILD_NODES), createGlobRestriction("/"+PathUtils.getName(childNPath) + "/*"));
+        assertGlobTrailingSlashEffect(ccPath);
+    }
+
+    private void assertGlobTrailingSlashEffect(String ccPath) throws RepositoryException {
+        assertFalse(testSession.hasPermission(path, Session.ACTION_ADD_NODE));
+        assertFalse(testSession.hasPermission(childNPath, Session.ACTION_ADD_NODE));
+        assertFalse(testSession.hasPermission(childNPath+"/", Session.ACTION_ADD_NODE));
+        assertFalse(testSession.hasPermission(ccPath, Session.ACTION_ADD_NODE));
+        assertFalse(testSession.hasPermission(ccPath+"/", Session.ACTION_ADD_NODE));
+        assertTrue(testSession.hasPermission(ccPath+"/greatgrandchild", Session.ACTION_ADD_NODE));
+        assertTrue(testSession.hasPermission(ccPath+"/greatgrandchild/", Session.ACTION_ADD_NODE));
+        assertTrue(testSession.hasPermission(ccPath+"/greatgrandchild/descendant", Session.ACTION_ADD_NODE));
+        testSession.getNode(ccPath).addNode("greatgrandchild").addNode("descendant");
+        testSession.save();
+    }
 }
\ No newline at end of file