Author: angela
Date: Wed Mar  6 13:11:48 2019
New Revision: 1854921

URL: http://svn.apache.org/viewvc?rev=1854921&view=rev
Log:
OAK-8101 : AccessControlValidator prevents alternative authorization models to 
use restrictions

Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlValidator.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlValidatorTest.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlValidator.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlValidator.java?rev=1854921&r1=1854920&r2=1854921&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlValidator.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlValidator.java
 Wed Mar  6 13:11:48 2019
@@ -40,6 +40,8 @@ import org.apache.jackrabbit.oak.securit
 import org.apache.jackrabbit.oak.spi.commit.DefaultValidator;
 import org.apache.jackrabbit.oak.spi.commit.Validator;
 import org.apache.jackrabbit.oak.spi.commit.VisibleValidator;
+import org.apache.jackrabbit.oak.spi.security.Context;
+import 
org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
 import 
org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
 import 
org.apache.jackrabbit.oak.spi.security.authorization.restriction.Restriction;
 import 
org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
@@ -69,6 +71,8 @@ class AccessControlValidator extends Def
     private final TypePredicate isRepoAccessControllable;
     private final TypePredicate isAccessControllable;
 
+    private final Context ctx;
+
     AccessControlValidator(@NotNull NodeState parentAfter,
                            @NotNull PrivilegeManager privilegeManager,
                            @NotNull PrivilegeBitsProvider 
privilegeBitsProvider,
@@ -81,6 +85,7 @@ class AccessControlValidator extends Def
         this.restrictionProvider = restrictionProvider;
         this.isRepoAccessControllable = new TypePredicate(parentAfter, 
MIX_REP_REPO_ACCESS_CONTROLLABLE);
         this.isAccessControllable = new TypePredicate(parentAfter, 
MIX_REP_ACCESS_CONTROLLABLE);
+        ctx = 
providerCtx.getSecurityProvider().getConfiguration(AuthorizationConfiguration.class).getContext();
     }
 
     private AccessControlValidator(AccessControlValidator parent, Tree 
parentAfter) {
@@ -91,6 +96,7 @@ class AccessControlValidator extends Def
         this.restrictionProvider = parent.restrictionProvider;
         this.isRepoAccessControllable = parent.isRepoAccessControllable;
         this.isAccessControllable = parent.isAccessControllable;
+        this.ctx = parent.ctx;
     }
 
     //----------------------------------------------------------< Validator 
>---
@@ -157,8 +163,15 @@ class AccessControlValidator extends Def
         } else if (isAccessControlEntry(treeAfter)) {
             checkValidAccessControlEntry(treeAfter);
         } else if 
(NT_REP_RESTRICTIONS.equals(TreeUtil.getPrimaryTypeName(treeAfter))) {
-            checkIsAccessControlEntry(parentAfter);
-            checkValidRestrictions(parentAfter);
+            // only validate restrictions if defined with an ACE controlled by 
this validator. otherwise verify that
+            // the parent is indeed access control content as defined by the 
authorization Context.
+            // this allows alternative authorization models to re-use the 
configured restriction provide and store
+            // them in a 'rep:Restriction' node even if the surrounding 
policy/access control entries look different
+            if (isAccessControlEntry(parentAfter)) {
+                checkValidRestrictions(parentAfter);
+            } else if (!ctx.definesTree(parentAfter)) {
+                throw accessViolation(2, "Access control entry node expected 
at " + parentAfter.getPath());
+            }
         }
     }
 
@@ -171,12 +184,6 @@ class AccessControlValidator extends Def
         return NT_REP_DENY_ACE.equals(ntName) || 
NT_REP_GRANT_ACE.equals(ntName);
     }
 
-    private static void checkIsAccessControlEntry(Tree tree) throws 
CommitFailedException {
-        if (!isAccessControlEntry(tree)) {
-            throw accessViolation(2, "Access control entry node expected at " 
+ tree.getPath());
-        }
-    }
-
     private void checkValidPolicy(Tree parent, Tree policyTree, NodeState 
policyNode) throws CommitFailedException {
         if (REP_REPO_POLICY.equals(policyTree.getName())) {
             checkValidAccessControlledNode(parent, isRepoAccessControllable, 
treeProvider);

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlValidatorTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlValidatorTest.java?rev=1854921&r1=1854920&r2=1854921&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlValidatorTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlValidatorTest.java
 Wed Mar  6 13:11:48 2019
@@ -17,32 +17,59 @@
 package org.apache.jackrabbit.oak.security.authorization.accesscontrol;
 
 import java.security.Principal;
+import java.util.List;
+import java.util.Set;
 import javax.jcr.AccessDeniedException;
 import javax.jcr.PropertyType;
 import javax.jcr.Value;
 import javax.jcr.ValueFactory;
+import javax.jcr.ValueFormatException;
 import javax.jcr.security.AccessControlManager;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
 import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
 import 
org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
 import org.apache.jackrabbit.oak.AbstractSecurityTest;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.Root;
 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.MemoryNodeStore;
+import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
 import 
org.apache.jackrabbit.oak.security.authorization.AuthorizationConfigurationImpl;
 import 
org.apache.jackrabbit.oak.security.authorization.composite.CompositeAuthorizationConfiguration;
+import 
org.apache.jackrabbit.oak.security.authorization.restriction.RestrictionProviderImpl;
+import org.apache.jackrabbit.oak.security.internal.SecurityProviderBuilder;
+import org.apache.jackrabbit.oak.security.internal.SecurityProviderHelper;
+import org.apache.jackrabbit.oak.spi.commit.CommitHook;
 import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.MoveTracker;
+import org.apache.jackrabbit.oak.spi.commit.ThreeWayConflictHandler;
 import org.apache.jackrabbit.oak.spi.commit.Validator;
+import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
+import org.apache.jackrabbit.oak.spi.lifecycle.RepositoryInitializer;
+import org.apache.jackrabbit.oak.spi.lifecycle.WorkspaceInitializer;
 import org.apache.jackrabbit.oak.spi.nodetype.NodeTypeConstants;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+import org.apache.jackrabbit.oak.spi.security.Context;
+import org.apache.jackrabbit.oak.spi.security.SecurityConfiguration;
 import 
org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
 import 
org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
+import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.OpenPermissionProvider;
+import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
+import 
org.apache.jackrabbit.oak.spi.security.authorization.restriction.Restriction;
+import 
org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
 import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.xml.ProtectedItemImporter;
 import org.apache.jackrabbit.oak.util.NodeUtil;
+import org.jetbrains.annotations.NotNull;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -54,6 +81,8 @@ import static org.junit.Assert.assertNul
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 public class AccessControlValidatorTest extends AbstractSecurityTest 
implements AccessControlConstants {
 
@@ -300,6 +329,7 @@ public class AccessControlValidatorTest
         } catch (CommitFailedException e) {
             // success
             assertTrue(e.isAccessControlViolation());
+            assertEquals(2, e.getCode());
             assertThat(e.getMessage(), containsString("/testRoot"));
         } finally {
             // revert pending changes that cannot be saved.
@@ -474,4 +504,55 @@ public class AccessControlValidatorTest
                 ":hidden", root.getChildNode("test").getChildNode(":hidden"));
         assertNull(hiddenValidator);
     }
+
+    /**
+     * Test case illustrating OAK-8081
+     */
+    @Test
+    public void testRestrictionsUsedByOtherModule() throws Exception {
+        AuthorizationConfiguration sc = mock(AuthorizationConfiguration.class);
+        // new acNode is covered by Context.definesTree
+        when(sc.getContext()).thenReturn(new Context.Default() {
+            @Override
+            public boolean definesTree(@NotNull Tree tree) {
+                return "differentAccessControl".equals(tree.getName());
+            }
+        });
+        when(sc.getParameters()).thenReturn(ConfigurationParameters.EMPTY);
+        SecurityProviderHelper.updateConfig(getSecurityProvider(), sc, 
AuthorizationConfiguration.class);
+
+        Tree acNode = TreeUtil.addChild(root.getTree(PathUtils.ROOT_PATH), 
"differentAccessControl", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+        RestrictionProvider rp = new RestrictionProviderImpl();
+        Restriction r = rp.createRestriction(PathUtils.ROOT_PATH, 
REP_ITEM_NAMES, new Value[] {getValueFactory(root).createValue("someName", 
PropertyType.NAME)});
+        rp.writeRestrictions(PathUtils.ROOT_PATH, acNode, ImmutableSet.of(r));
+
+        root.commit();
+    }
+
+    /**
+     * Test case illustrating OAK-8081, where a given 'aceTree' is not covered 
by the authorization-context and thus
+     * the AccessControlValidator will still fail.
+     */
+    @Test
+    public void testRestrictionsUsedByOtherModule2() throws Exception {
+        AuthorizationConfiguration sc = mock(AuthorizationConfiguration.class);
+        // new acNode is not covered by Context.definesTree
+        when(sc.getContext()).thenReturn(new Context.Default());
+        when(sc.getParameters()).thenReturn(ConfigurationParameters.EMPTY);
+        SecurityProviderHelper.updateConfig(getSecurityProvider(), sc, 
AuthorizationConfiguration.class);
+
+        Tree acNode = TreeUtil.addChild(root.getTree(PathUtils.ROOT_PATH), 
"notCoveredByContext", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+        RestrictionProvider rp = new RestrictionProviderImpl();
+        Restriction r = rp.createRestriction(PathUtils.ROOT_PATH, 
REP_ITEM_NAMES, new Value[]{getValueFactory(root).createValue("someName", 
PropertyType.NAME)});
+        rp.writeRestrictions(PathUtils.ROOT_PATH, acNode, ImmutableSet.of(r));
+
+        try {
+            root.commit();
+        } catch (CommitFailedException e) {
+            assertTrue(e.isAccessControlViolation());
+            assertEquals(2, e.getCode());
+        } finally {
+            root.refresh();
+        }
+    }
 }
\ No newline at end of file


Reply via email to