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