Author: angela
Date: Tue Mar 3 10:51:54 2015
New Revision: 1663623
URL: http://svn.apache.org/r1663623
Log:
OAK-1268
Add support for composite authorization setup,
OAK-2008 : authorization setup for closed user groups
Added:
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugValidatorProvider.java
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/SupportedPaths.java
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugValidatorTest.java
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/SupportedPathsTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfigurationTest.java
Removed:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/ControlFlag.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/AbstractCompositeTest.java
Modified:
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManager.java
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugConfiguration.java
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProvider.java
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/AbstractCugTest.java
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManagerTest.java
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugConfigurationTest.java
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugEvaluationTest.java
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProviderTest.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationConfigurationImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfiguration.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProvider.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/accesscontrol/PolicyOwner.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/AggregatedPermissionProvider.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProvider.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/TreeUtil.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/CompositeTokenConfigurationTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAccessControlManagerTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProviderTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/AbstractCompositeConfigurationTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/CompositeConfigurationTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProviderTest.java
Modified:
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManager.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManager.java?rev=1663623&r1=1663622&r2=1663623&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManager.java
(original)
+++
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManager.java
Tue Mar 3 10:51:54 2015
@@ -42,6 +42,7 @@ import org.apache.jackrabbit.oak.api.Roo
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import
org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.PolicyOwner;
import org.apache.jackrabbit.oak.spi.security.authorization.cug.CugPolicy;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
@@ -62,7 +63,7 @@ import static org.apache.jackrabbit.oak.
* Implementation of the {@link
org.apache.jackrabbit.api.security.JackrabbitAccessControlManager}
* interface that allows to create, modify and remove closed user group
policies.
*/
-class CugAccessControlManager extends AbstractAccessControlManager implements
CugConstants {
+class CugAccessControlManager extends AbstractAccessControlManager implements
CugConstants, PolicyOwner {
private static final Logger log =
LoggerFactory.getLogger(CugAccessControlManager.class);
@@ -124,7 +125,8 @@ class CugAccessControlManager extends Ab
} else {
CugPolicy cug = getCugPolicy(oakPath);
if (cug == null) {
- return new
AccessControlPolicyIteratorAdapter(ImmutableSet.of(new CugPolicyImpl(oakPath,
getNamePathMapper(), principalManager, CugUtil.getImportBehavior(config))));
+ cug = new CugPolicyImpl(oakPath, getNamePathMapper(),
principalManager, CugUtil.getImportBehavior(config));
+ return new
AccessControlPolicyIteratorAdapter(ImmutableSet.of(cug));
} else {
return AccessControlPolicyIteratorAdapter.EMPTY;
}
@@ -190,6 +192,12 @@ class CugAccessControlManager extends Ab
return new AccessControlPolicy[0];
}
+ //--------------------------------------------------------< PolicyOwner
>---
+ @Override
+ public boolean defines(@Nullable String absPath, @Nonnull
AccessControlPolicy accessControlPolicy) {
+ return isValidPolicy(absPath, accessControlPolicy);
+ }
+
//--------------------------------------------------------------------------
private boolean isSupportedPath(@Nullable String oakPath) throws
RepositoryException {
@@ -237,12 +245,16 @@ class CugAccessControlManager extends Ab
}
}
+ private static boolean isValidPolicy(@Nullable String absPath, @Nonnull
AccessControlPolicy policy) {
+ return policy instanceof CugPolicyImpl && ((CugPolicyImpl)
policy).getPath().equals(absPath);
+ }
+
private static void checkValidPolicy(@Nullable String absPath, @Nonnull
AccessControlPolicy policy) throws AccessControlException {
if (!(policy instanceof CugPolicyImpl)) {
throw new AccessControlException("Unsupported policy
implementation: " + policy);
}
- CugPolicy cug = (CugPolicy) policy;
+ CugPolicyImpl cug = (CugPolicyImpl) policy;
if (!cug.getPath().equals(absPath)) {
throw new AccessControlException("Path mismatch: Expected " +
cug.getPath() + ", Found: " + absPath);
}
Modified:
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugConfiguration.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugConfiguration.java?rev=1663623&r1=1663622&r2=1663623&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugConfiguration.java
(original)
+++
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugConfiguration.java
Tue Mar 3 10:51:54 2015
@@ -29,12 +29,12 @@ import javax.jcr.security.AccessControlM
import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;
+import com.google.common.collect.ImmutableList;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.ConfigurationPolicy;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
-import org.apache.felix.scr.annotations.PropertyOption;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.jackrabbit.oak.api.CommitFailedException;
@@ -48,6 +48,8 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.tree.RootFactory;
import org.apache.jackrabbit.oak.spi.commit.CompositeEditorProvider;
import org.apache.jackrabbit.oak.spi.commit.EditorHook;
+import org.apache.jackrabbit.oak.spi.commit.MoveTracker;
+import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
import org.apache.jackrabbit.oak.spi.lifecycle.RepositoryInitializer;
import org.apache.jackrabbit.oak.spi.security.CompositeConfiguration;
import org.apache.jackrabbit.oak.spi.security.ConfigurationBase;
@@ -58,8 +60,6 @@ import org.apache.jackrabbit.oak.spi.sec
import org.apache.jackrabbit.oak.spi.security.authentication.SystemSubject;
import
org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
import org.apache.jackrabbit.oak.spi.security.authorization.cug.CugExclude;
-import
org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider;
-import
org.apache.jackrabbit.oak.spi.security.authorization.permission.ControlFlag;
import
org.apache.jackrabbit.oak.spi.security.authorization.permission.EmptyPermissionProvider;
import
org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
import
org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
@@ -71,7 +71,7 @@ import org.apache.jackrabbit.oak.spi.xml
@Component(metatype = true,
label = "CUG Configuration",
- description = "Component to enable Allows to exclude principal(s) with
the configured name(s) from CUG evaluation.",
+ description = "Authorization configuration dedicated to setup and
evaluation 'closed user group' permissions.",
policy = ConfigurationPolicy.REQUIRE)
@Service({AuthorizationConfiguration.class, SecurityConfiguration.class})
@Properties({
@@ -86,15 +86,7 @@ import org.apache.jackrabbit.oak.spi.xml
@Property(name = CompositeConfiguration.PARAM_RANKING,
label = "Ranking",
description = "Ranking of this configuration in a setup with
multiple authorization configurations.",
- intValue = 200),
- @Property(name = AggregatedPermissionProvider.PARAM_CONTROL_FLAG,
- label = "Control Flag",
- description = "Control flag defining if the permission
provider is SUFFICIENT or REQUISITE.",
- options = {
- @PropertyOption(name = ControlFlag.SUFFICIENT_NAME,
value = ControlFlag.SUFFICIENT_NAME),
- @PropertyOption(name = ControlFlag.REQUISITE_NAME,
value = ControlFlag.REQUISITE_NAME)
- },
- value = ControlFlag.REQUISITE_NAME)
+ intValue = 200)
})
public class CugConfiguration extends ConfigurationBase implements
AuthorizationConfiguration, CugConstants {
@@ -107,6 +99,7 @@ public class CugConfiguration extends Co
@Reference
private CugExclude exclude = new CugExclude.Default();
+ @SuppressWarnings("UnusedDeclaration")
public CugConfiguration() {
super();
}
@@ -134,8 +127,7 @@ public class CugConfiguration extends Co
if (!enabled || supportedPaths.length == 0 ||
getExclude().isExcluded(principals)) {
return EmptyPermissionProvider.getInstance();
} else {
- ControlFlag flag =
ControlFlag.valueOf(params.getConfigValue(AggregatedPermissionProvider.PARAM_CONTROL_FLAG,
ControlFlag.REQUISITE_NAME));
- return new CugPermissionProvider(root, principals, supportedPaths,
flag, getContext());
+ return new CugPermissionProvider(root, principals, supportedPaths,
getContext());
}
}
@@ -164,6 +156,12 @@ public class CugConfiguration extends Co
};
}
+ @Nonnull
+ @Override
+ public List<? extends ValidatorProvider> getValidators(String
workspaceName, Set<Principal> principals, MoveTracker moveTracker) {
+ return ImmutableList.of(new CugValidatorProvider());
+ }
+
@Override
public List<ProtectedItemImporter> getProtectedItemImporters() {
return Collections.<ProtectedItemImporter>singletonList(new
CugImporter());
@@ -175,7 +173,7 @@ public class CugConfiguration extends Co
}
//----------------------------------------------------< SCR Integration
>---
-
+ @SuppressWarnings("UnusedDeclaration")
@Activate
protected void activate() throws IOException, CommitFailedException,
PrivilegedActionException, RepositoryException {
ContentSession systemSession = null;
@@ -198,6 +196,7 @@ public class CugConfiguration extends Co
}
//--------------------------------------------------------------------------
+ @Nonnull
private CugExclude getExclude() {
return (exclude == null) ? new CugExclude.Default() : exclude;
}
Modified:
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProvider.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProvider.java?rev=1663623&r1=1663622&r2=1663623&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProvider.java
(original)
+++
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProvider.java
Tue Mar 3 10:51:54 2015
@@ -22,6 +22,7 @@ import java.util.HashSet;
import java.util.Set;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import javax.jcr.Session;
import com.google.common.base.Predicates;
@@ -35,14 +36,15 @@ import org.apache.jackrabbit.oak.commons
import org.apache.jackrabbit.oak.plugins.tree.TreeLocation;
import org.apache.jackrabbit.oak.spi.security.Context;
import
org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider;
-import
org.apache.jackrabbit.oak.spi.security.authorization.permission.ControlFlag;
import
org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
import
org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;
import
org.apache.jackrabbit.oak.spi.security.authorization.permission.RepositoryPermission;
import
org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.plugins.tree.RootFactory;
+import org.apache.jackrabbit.oak.util.TreeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -62,21 +64,24 @@ class CugPermissionProvider implements P
PrivilegeConstants.REP_READ_PROPERTIES
);
+ private static final Set<PrivilegeBits> READ_PRIVILEGE_BITS =
ImmutableSet.of(
+ PrivilegeBits.BUILT_IN.get(PrivilegeConstants.JCR_READ),
+ PrivilegeBits.BUILT_IN.get(PrivilegeConstants.REP_READ_NODES),
+ PrivilegeBits.BUILT_IN.get(PrivilegeConstants.REP_READ_PROPERTIES)
+ );
+
private final Root root;
private final Set<String> principalNames;
- private final ControlFlag flag;
private final Context ctx;
- private final String[] supportedPaths;
- private final String[] supportedAltPaths;
+ private final SupportedPaths supportedPaths;
private Root immutableRoot;
CugPermissionProvider(@Nonnull Root root,
@Nonnull Set<Principal> principals,
@Nonnull String[] supportedPaths,
- @Nonnull ControlFlag flag,
@Nonnull Context ctx) {
this.root = root;
@@ -86,32 +91,22 @@ class CugPermissionProvider implements P
principalNames.add(p.getName());
}
- this.flag = flag;
-
- this.supportedPaths = supportedPaths;
- supportedAltPaths = new String[supportedPaths.length];
- int i = 0;
- for (String p : supportedPaths) {
- supportedAltPaths[i++] = p + '/';
- }
-
+ this.supportedPaths = new SupportedPaths(supportedPaths);
this.ctx = ctx;
}
//---------------------------------------< AggregatedPermissionProvider
>---
-
- public ControlFlag getFlag() {
- return flag;
- }
-
+ @Override
public boolean handles(String path, String jcrAction) {
return isReadAction(jcrAction) &&
includesCug(immutableRoot.getTree(path), path);
}
- public boolean handles(Tree tree) {
- return includesCug(tree, tree.getPath());
+ @Override
+ public boolean handles(@Nonnull Tree tree, PrivilegeBits privilegeBits) {
+ return READ_PRIVILEGE_BITS.contains(privilegeBits) &&
includesCug(tree, tree.getPath());
}
+ @Override
public boolean handles(Tree tree, long permission) {
return isRead(permission) && includesCug(tree, tree.getPath());
}
@@ -125,15 +120,18 @@ class CugPermissionProvider implements P
}
}
+ @Override
public boolean handlesRepositoryPermissions() {
return false;
}
//-------------------------------------------------< PermissionProvider
>---
+ @Override
public void refresh() {
immutableRoot = RootFactory.createReadOnlyRoot(root);
}
+ @Override
public Set<String> getPrivileges(Tree tree) {
if (canRead(tree)) {
return READ_PRIVILEGE_NAMES;
@@ -142,6 +140,7 @@ class CugPermissionProvider implements P
}
}
+ @Override
public boolean hasPrivileges(Tree tree, String... privilegeNames) {
for (String privilegeName : privilegeNames) {
if (!READ_PRIVILEGE_NAMES.contains(privilegeName)) {
@@ -151,35 +150,39 @@ class CugPermissionProvider implements P
return canRead(tree);
}
+ @Override
public RepositoryPermission getRepositoryPermission() {
throw new UnsupportedOperationException("Not supported");
}
+ @Override
public TreePermission getTreePermission(Tree tree, TreePermission
parentPermission) {
Tree immutableTree = getImmutableTree(tree);
- if (ctx.definesContextRoot(immutableTree)) {
+ if (parentPermission == TreePermission.EMPTY &&
!immutableTree.isRoot() || isAcContent(immutableTree, true)) {
return TreePermission.EMPTY;
}
+
+ TreePermission tp;
if (parentPermission instanceof CugTreePermission) {
+ tp = new CugTreePermission(immutableTree, ((CugTreePermission)
parentPermission).allow);
if (hasCug(immutableTree)) {
- return createCugPermission(immutableTree);
- } else {
- return new CugTreePermission(immutableTree,
((CugTreePermission) parentPermission).allow);
+ // a new (nested) cug starts off here
+ tp = createCugPermission(immutableTree, tp);
}
- } else if (parentPermission == TreePermission.EMPTY &&
!immutableTree.isRoot()) {
- return TreePermission.EMPTY;
} else {
String path = immutableTree.getPath();
- if (includes(path)) {
- return createCugPermission(immutableTree);
- } else if (mayContainCug(path)) {
- return new EmptyCugPermission(immutableTree);
+ if (supportedPaths.includes(path)) {
+ tp = createCugPermission(immutableTree, null);
+ } else if (supportedPaths.mayContainCug(path)) {
+ tp = new EmptyCugPermission(immutableTree);
} else {
- return TreePermission.EMPTY;
+ tp = TreePermission.EMPTY;
}
}
+ return tp;
}
+ @Override
public boolean isGranted(Tree tree, PropertyState property, long
permissions) {
if (isRead(permissions)) {
return canRead(tree);
@@ -188,9 +191,10 @@ class CugPermissionProvider implements P
}
}
+ @Override
public boolean isGranted(String oakPath, String jcrActions) {
TreeLocation location = TreeLocation.create(immutableRoot, oakPath);
- boolean isAcContent = ctx.definesLocation(location);
+ boolean isAcContent = isAcContent(location);
long permissions = Permissions.getPermissions(jcrActions, location,
isAcContent);
if (isRead(permissions)) {
@@ -221,34 +225,45 @@ class CugPermissionProvider implements P
return tree.exists() && tree.hasChild(REP_CUG_POLICY);
}
- private boolean includes(@Nonnull String path) {
- for (String p : supportedAltPaths) {
- if (p.startsWith(path)) {
- return true;
- }
- }
- for (String p : supportedPaths) {
- if (p.equals(path)) {
- return true;
- }
- }
- return false;
+ private boolean isAcContent(@Nonnull Tree tree, boolean testForCtxRoot) {
+ // FIXME: this should also take other ac-configurations into
considerations
+ return (testForCtxRoot) ? ctx.definesContextRoot(tree) :
ctx.definesTree(tree);
+ }
+
+ private boolean isAcContent(@Nonnull TreeLocation location) {
+ // FIXME: this should also take other ac-configurations into
considerations
+ return ctx.definesLocation(location);
}
private boolean includesCug(@Nonnull Tree tree, @Nonnull String path) {
return getCugRoot(tree, path) != null;
}
+ /**
+ * Returns the {@code tree} that holds a CUG policy in the ancestry of the
+ * given {@code tree} with the specified {@code path} or {@code null} if no
+ * such tree exists and thus no CUG is effective at the specified path.
+ *
+ * @param tree The target tree.
+ * @param path The path of the given target tree.
+ * @return the {@code tree} holding the CUG policy that effects the
specified
+ * path or {@code null} if no such policy exists.
+ */
@CheckForNull
private Tree getCugRoot(@Nonnull Tree tree, @Nonnull String path) {
- if (!includes(path)) {
+ if (!supportedPaths.includes(path)) {
return null;
}
Tree immutableTree = getImmutableTree(tree);
if (hasCug(immutableTree)) {
return immutableTree;
}
+ String parentPath;
while (!immutableTree.isRoot()) {
+ parentPath = PathUtils.getParentPath(path);
+ if (!supportedPaths.includes(parentPath)) {
+ break;
+ }
immutableTree = immutableTree.getParent();
if (hasCug(immutableTree)) {
return immutableTree;
@@ -257,37 +272,29 @@ class CugPermissionProvider implements P
return null;
}
- private boolean mayContainCug(@Nonnull String path) {
- String path2 = path + '/';
- for (String sp : supportedPaths) {
- if (path.equals(sp) || sp.startsWith(path2)) {
- return true;
- }
- }
- return false;
- }
-
private boolean canRead(@Nonnull Tree tree) {
Tree immutableTree = getImmutableTree(tree);
- if (ctx.definesTree(immutableTree)) {
+ if (isAcContent(immutableTree, false)) {
// cug defining access control content is not accessible
return false;
}
Tree cugRoot = getCugRoot(immutableTree, immutableTree.getPath());
- return cugRoot != null && createCugPermission(cugRoot).canRead();
+ return cugRoot != null && createCugPermission(cugRoot, null).canRead();
}
+ @Nonnull
private Tree getImmutableTree(@Nonnull Tree tree) {
- return immutableRoot.getTree(tree.getPath());
+ return TreeUtil.isReadOnlyTree(tree) ? tree :
immutableRoot.getTree(tree.getPath());
}
- private TreePermission createCugPermission(@Nonnull Tree tree) {
+ @Nonnull
+ private TreePermission createCugPermission(@Nonnull Tree tree, @Nullable
TreePermission fallback) {
Tree cugTree = tree.getChild(REP_CUG_POLICY);
if (CugUtil.definesCug(cugTree)) {
- PropertyState pNameState =
cugTree.getProperty(REP_PRINCIPAL_NAMES);
- if (pNameState != null) {
+ PropertyState princNamesState =
cugTree.getProperty(REP_PRINCIPAL_NAMES);
+ if (princNamesState != null) {
boolean allow = false;
- for (String pName : pNameState.getValue(Type.STRINGS)) {
+ for (String pName : princNamesState.getValue(Type.STRINGS)) {
if (principalNames.contains(pName)) {
allow = true;
break;
@@ -298,10 +305,15 @@ class CugPermissionProvider implements P
log.warn("Tree at {0} doesn't represent a valid CUG.",
cugTree.getPath());
}
}
- return new EmptyCugPermission(tree);
+ return (fallback == null) ? new EmptyCugPermission(tree) : fallback;
}
//--------------------------------------------------------------------------
+
+ /**
+ * Same as {@link
org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission#EMPTY}
+ * from a permission point of view but indicating that
+ */
private final class EmptyCugPermission implements TreePermission {
private Tree tree;
@@ -346,6 +358,9 @@ class CugPermissionProvider implements P
}
}
+ /**
+ * {@code TreePermission} implementation for all items located with a CUG.
+ */
private final class CugTreePermission implements TreePermission {
private final Tree tree;
Added:
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugValidatorProvider.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugValidatorProvider.java?rev=1663623&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugValidatorProvider.java
(added)
+++
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugValidatorProvider.java
Tue Mar 3 10:51:54 2015
@@ -0,0 +1,93 @@
+/*
+ * 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 javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypePredicate;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.DefaultValidator;
+import org.apache.jackrabbit.oak.spi.commit.Validator;
+import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
+import org.apache.jackrabbit.oak.spi.commit.VisibleValidator;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
+
+import static
org.apache.jackrabbit.oak.api.CommitFailedException.ACCESS_CONTROL;
+
+class CugValidatorProvider extends ValidatorProvider implements CugConstants {
+
+ private TypePredicate isMixCug;
+
+ @Override
+ protected Validator getRootValidator(NodeState before, NodeState after,
CommitInfo info) {
+ this.isMixCug = new TypePredicate(after, MIX_REP_CUG_MIXIN);
+ return new CugValidator(after);
+ }
+
+ private static CommitFailedException accessViolation(int code, String
message) {
+ return new CommitFailedException(ACCESS_CONTROL, code, message);
+ }
+
+ private void validateCugNode(@Nonnull NodeState parent, @Nonnull NodeState
nodeState) throws CommitFailedException {
+ if
(!NT_REP_CUG_POLICY.equals(NodeStateUtils.getPrimaryTypeName(nodeState))) {
+ throw accessViolation(21, "Reserved name 'rep:cugPolicy' must only
be used for nodes of type 'rep:CugPolicy'.");
+ }
+ if (!isMixCug.apply(parent)) {
+ throw accessViolation(22, "Parent node not of mixin type
'rep:CugMixin'.");
+ }
+ }
+
+ private final class CugValidator extends DefaultValidator {
+ private final NodeState parentAfter;
+
+ private CugValidator(@Nonnull NodeState parentAfter) {
+ this.parentAfter = parentAfter;
+ }
+
+ //------------------------------------------------------< Validator
>---
+ @Override
+ public void propertyChanged(PropertyState before, PropertyState after)
throws CommitFailedException {
+ String name = after.getName();
+ if (JcrConstants.JCR_PRIMARYTYPE.equals(name)) {
+ if (NT_REP_CUG_POLICY.equals(before.getValue(Type.STRING)) ||
NT_REP_CUG_POLICY.equals(after.getValue(Type.STRING))) {
+ throw accessViolation(20, "Attempt to change primary type
of/to CUG policy.");
+ }
+ }
+ }
+
+ @Override
+ public Validator childNodeAdded(String name, NodeState after) throws
CommitFailedException {
+ if (REP_CUG_POLICY.equals(name)) {
+ validateCugNode(parentAfter, after);
+ }
+ return new VisibleValidator(new CugValidator(after), true, true);
+ }
+
+ @Override
+ public Validator childNodeChanged(String name, NodeState before,
NodeState after) throws CommitFailedException {
+ if (after.hasChildNode(REP_CUG_POLICY)) {
+ validateCugNode(after, after.getChildNode(REP_CUG_POLICY));
+ }
+ return new VisibleValidator(new CugValidator(after), true, true);
+ }
+ }
+}
\ No newline at end of file
Added:
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/SupportedPaths.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/SupportedPaths.java?rev=1663623&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/SupportedPaths.java
(added)
+++
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/SupportedPaths.java
Tue Mar 3 10:51:54 2015
@@ -0,0 +1,99 @@
+/*
+ * 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 javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.commons.PathUtils;
+
+class SupportedPaths {
+
+ private final String[] supportedPaths;
+ private final String[] supportedAltPaths;
+
+ private final boolean includesRootPath;
+
+ SupportedPaths(@Nonnull String[] supportedPaths) {
+ this.supportedPaths = supportedPaths;
+ supportedAltPaths = new String[supportedPaths.length];
+
+ boolean foundRootPath = false;
+ int i = 0;
+ for (String p : supportedPaths) {
+ if (PathUtils.denotesRoot(p)) {
+ foundRootPath = true;
+ } else {
+ supportedAltPaths[i++] = p + '/';
+ }
+ }
+ includesRootPath = foundRootPath;
+ }
+
+ /**
+ * Test if the specified {@code path} is contained in any of the configured
+ * supported paths for CUGs.
+ *
+ * @param path An absolute path.
+ * @return {@code true} if the specified {@code path} is equal to or a
+ * descendant of one of the configured supported paths.
+ */
+ boolean includes(@Nonnull String path) {
+ if (supportedPaths.length == 0) {
+ return false;
+ }
+ if (includesRootPath) {
+ return true;
+ }
+ for (String p : supportedAltPaths) {
+ if (path.startsWith(p)) {
+ return true;
+ }
+ }
+ for (String p : supportedPaths) {
+ if (path.equals(p)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Tests if further evaluation below {@code path} is required as one of the
+ * configured supported paths is a descendant (e.g. there might be CUGs
+ * in the subtree although the specified {@code path} does not directly
+ * support CUGs.
+ *
+ * @param path An absolute path
+ * @return {@code true} if there exists a configured supported path that is
+ * a descendant of the given {@code path}.
+ */
+ boolean mayContainCug(@Nonnull String path) {
+ if (supportedPaths.length == 0) {
+ return false;
+ }
+ if (includesRootPath || PathUtils.denotesRoot(path)) {
+ return true;
+ }
+ String path2 = path + '/';
+ for (String sp : supportedPaths) {
+ if (sp.startsWith(path2)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
\ No newline at end of file
Modified:
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/AbstractCugTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/AbstractCugTest.java?rev=1663623&r1=1663622&r2=1663623&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/AbstractCugTest.java
(original)
+++
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/AbstractCugTest.java
Tue Mar 3 10:51:54 2015
@@ -16,24 +16,65 @@
*/
package org.apache.jackrabbit.oak.spi.security.authorization.cug.impl;
+import java.security.Principal;
import java.util.Iterator;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import javax.jcr.RepositoryException;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.AccessControlPolicy;
+import javax.jcr.security.AccessControlPolicyIterator;
+import com.google.common.collect.ImmutableMap;
import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
+import
org.apache.jackrabbit.oak.security.authorization.composite.CompositeAuthorizationConfiguration;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.SecurityConfiguration;
import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
import
org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
-import
org.apache.jackrabbit.oak.security.authorization.composite.CompositeAuthorizationConfiguration;
+import org.apache.jackrabbit.oak.spi.security.authorization.cug.CugPolicy;
+import org.apache.jackrabbit.oak.util.NodeUtil;
/**
* Base class for CUG related test that setup the authorization configuration
* to expose the CUG specific implementations of {@code AccessControlManager}
* and {@code PermissionProvider}.
*/
-public class AbstractCugTest extends AbstractSecurityTest {
+public class AbstractCugTest extends AbstractSecurityTest implements
CugConstants {
+
+ static final String SUPPORTED_PATH = "/content";
+ static final String SUPPORTED_PATH2 = "/content2";
+ static final String UNSUPPORTED_PATH = "/testNode";
+ static final String INVALID_PATH = "/path/to/non/existing/tree";
+
+ static final ConfigurationParameters CUG_CONFIG =
ConfigurationParameters.of(
+ CugConstants.PARAM_CUG_SUPPORTED_PATHS, new String[]
{SUPPORTED_PATH, SUPPORTED_PATH2},
+ CugConstants.PARAM_CUG_ENABLED, true);
+
+ @Override
+ public void before() throws Exception {
+ super.before();
+
+ NodeUtil rootNode = new NodeUtil(root.getTree("/"));
+ NodeUtil content = rootNode.addChild("content",
NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+ content.addChild("subtree", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+ rootNode.addChild("content2", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+ rootNode.addChild("testNode", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+ root.commit();
+ }
+
+ @Override
+ public void after() throws Exception {
+ try {
+ root.getTree(SUPPORTED_PATH).remove();
+ root.getTree(UNSUPPORTED_PATH).remove();
+ root.commit();
+ } finally {
+ super.after();
+ }
+ }
@Override
protected SecurityProvider getSecurityProvider() {
@@ -43,6 +84,27 @@ public class AbstractCugTest extends Abs
return securityProvider;
}
+ @Override
+ protected ConfigurationParameters getSecurityConfigParameters() {
+ return ConfigurationParameters.of(ImmutableMap.of(
+ AuthorizationConfiguration.NAME, CUG_CONFIG)
+ );
+ }
+
+ void createCug(@Nonnull String absPath, @Nonnull Principal principal)
throws RepositoryException {
+ AccessControlManager acMgr = getAccessControlManager(root);
+ AccessControlPolicyIterator it = acMgr.getApplicablePolicies(absPath);
+ while (it.hasNext()) {
+ AccessControlPolicy policy = it.nextAccessControlPolicy();
+ if (policy instanceof CugPolicy) {
+ ((CugPolicy) policy).addPrincipals(principal);
+ acMgr.setPolicy(absPath, policy);
+ return;
+ }
+ }
+ throw new IllegalStateException("Unable to create CUG at " + absPath);
+ }
+
final class CugSecurityProvider implements SecurityProvider {
private final SecurityProvider base;
@@ -86,8 +148,8 @@ public class AbstractCugTest extends Abs
T c = base.getConfiguration(configClass);
if (AuthorizationConfiguration.class == configClass) {
CompositeAuthorizationConfiguration composite = new
CompositeAuthorizationConfiguration(this);
- composite.addConfiguration((AuthorizationConfiguration) c);
composite.addConfiguration(cugConfiguration);
+ composite.addConfiguration((AuthorizationConfiguration) c);
return (T) composite;
} else {
return c;
Modified:
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManagerTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManagerTest.java?rev=1663623&r1=1663622&r2=1663623&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManagerTest.java
(original)
+++
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManagerTest.java
Tue Mar 3 10:51:54 2015
@@ -37,13 +37,10 @@ import org.apache.jackrabbit.oak.api.Tre
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
-import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
-import
org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
import org.apache.jackrabbit.oak.spi.security.authorization.cug.CugPolicy;
import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
import org.apache.jackrabbit.oak.spi.xml.ImportBehavior;
-import org.apache.jackrabbit.oak.util.NodeUtil;
import org.apache.jackrabbit.oak.util.TreeUtil;
import org.junit.Test;
@@ -56,42 +53,15 @@ import static org.junit.Assert.fail;
public class CugAccessControlManagerTest extends AbstractCugTest {
- private static final String SUPPORTED_PATH = "/content";
- private static final String UNSUPPORTED_PATH = "/testNode";
- private static final String INVALID_PATH = "/path/to/non/existing/tree";
- private static final ConfigurationParameters CUG_CONFIG =
ConfigurationParameters.of(CugConstants.PARAM_CUG_SUPPORTED_PATHS,
SUPPORTED_PATH);
-
private CugAccessControlManager cugAccessControlManager;
@Override
public void before() throws Exception {
super.before();
- NodeUtil rootNode = new NodeUtil(root.getTree("/"));
- NodeUtil content = rootNode.addChild("content",
NodeTypeConstants.NT_OAK_UNSTRUCTURED);
- content.addChild("subtree", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
- rootNode.addChild("testNode", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
- root.commit();
-
cugAccessControlManager = new CugAccessControlManager(root,
NamePathMapper.DEFAULT, getSecurityProvider());
}
- @Override
- public void after() throws Exception {
- try {
- root.getTree(SUPPORTED_PATH).remove();
- root.getTree(UNSUPPORTED_PATH).remove();
- root.commit();
- } finally {
- super.after();
- }
- }
-
- @Override
- protected ConfigurationParameters getSecurityConfigParameters() {
- return
ConfigurationParameters.of(ImmutableMap.of(AuthorizationConfiguration.NAME,
CUG_CONFIG));
- }
-
private CugPolicy createCug(@Nonnull String path) {
return new CugPolicyImpl(path, NamePathMapper.DEFAULT,
getPrincipalManager(root), ImportBehavior.ABORT);
}
@@ -307,6 +277,9 @@ public class CugAccessControlManagerTest
cugAccessControlManager.removePolicy(SUPPORTED_PATH,
createCug(SUPPORTED_PATH + "/subtree"));
}
+ /**
+ * An invalid (unsupported) implementation of {@link CugPolicy}.
+ */
private static final class InvalidCug implements CugPolicy {
private static final InvalidCug INSTANCE = new InvalidCug();
Modified:
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugConfigurationTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugConfigurationTest.java?rev=1663623&r1=1663622&r2=1663623&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugConfigurationTest.java
(original)
+++
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugConfigurationTest.java
Tue Mar 3 10:51:54 2015
@@ -18,7 +18,6 @@ package org.apache.jackrabbit.oak.spi.se
import java.security.Principal;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import javax.jcr.security.AccessControlManager;
@@ -59,11 +58,10 @@ public class CugConfigurationTest extend
@Test
public void testGetPermissionProviderDisabled2() {
- Map<String, Object> params = ImmutableMap.<String, Object>of(
+ ConfigurationParameters params = ConfigurationParameters.of(
CugConstants.PARAM_CUG_ENABLED, false,
CugConstants.PARAM_CUG_SUPPORTED_PATHS, "/content");
- CugConfiguration cc =
createConfiguration(ConfigurationParameters.of(params));
-
+ CugConfiguration cc = createConfiguration(params);
PermissionProvider pp = cc.getPermissionProvider(root, "default",
ImmutableSet.<Principal>of(EveryonePrincipal.getInstance()));
assertSame(EmptyPermissionProvider.getInstance(), pp);
}
@@ -87,10 +85,10 @@ public class CugConfigurationTest extend
@Test
public void testGetPermissionProviderSupportedPaths() {
- Map<String, Object> params = ImmutableMap.<String, Object>of(
+ ConfigurationParameters params = ConfigurationParameters.of(
CugConstants.PARAM_CUG_ENABLED, true,
CugConstants.PARAM_CUG_SUPPORTED_PATHS, "/content");
- CugConfiguration cc =
createConfiguration(ConfigurationParameters.of(params));
+ CugConfiguration cc = createConfiguration(params);
PermissionProvider pp = cc.getPermissionProvider(root, "default",
ImmutableSet.<Principal>of(EveryonePrincipal.getInstance()));
assertTrue(pp instanceof CugPermissionProvider);
@@ -114,10 +112,10 @@ public class CugConfigurationTest extend
@Test
public void testGetAccessControlManagerSupportedPaths() {
- Map<String, Object> params = ImmutableMap.<String, Object>of(
+ ConfigurationParameters params = ConfigurationParameters.of(
CugConstants.PARAM_CUG_ENABLED, true,
CugConstants.PARAM_CUG_SUPPORTED_PATHS, "/content");
- CugConfiguration cc =
createConfiguration(ConfigurationParameters.of(params));
+ CugConfiguration cc = createConfiguration(params);
AccessControlManager acMgr = cc.getAccessControlManager(root,
NamePathMapper.DEFAULT);
assertTrue(acMgr instanceof CugAccessControlManager);
@@ -125,11 +123,10 @@ public class CugConfigurationTest extend
@Test
public void testExcludedPrincipals() {
- Map<String, Object> params = ImmutableMap.<String, Object>of(
+ ConfigurationParameters params = ConfigurationParameters.of(
CugConstants.PARAM_CUG_ENABLED, true,
CugConstants.PARAM_CUG_SUPPORTED_PATHS, "/content");
-
- CugConfiguration cc =
createConfiguration(ConfigurationParameters.of(params));
+ CugConfiguration cc = createConfiguration(params);
List<Principal> excluded = ImmutableList.of(
SystemPrincipal.INSTANCE,
Modified:
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugEvaluationTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugEvaluationTest.java?rev=1663623&r1=1663622&r2=1663623&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugEvaluationTest.java
(original)
+++
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugEvaluationTest.java
Tue Mar 3 10:51:54 2015
@@ -16,7 +16,435 @@
*/
package org.apache.jackrabbit.oak.spi.security.authorization.cug.impl;
-public class CugEvaluationTest extends AbstractCugTest {
+import java.security.Principal;
+import java.util.List;
+import java.util.Set;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.security.AccessControlList;
+import javax.jcr.security.AccessControlManager;
- // TODO
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.User;
+import
org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.ContentSession;
+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.plugins.nodetype.NodeTypeConstants;
+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.PermissionProvider;
+import
org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;
+import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.apache.jackrabbit.oak.util.NodeUtil;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class CugEvaluationTest extends AbstractCugTest implements
NodeTypeConstants {
+
+ private static final String TEST_GROUP_ID = "testGroup";
+ private static final String TEST_USER2_ID = "testUser2";
+
+ private ContentSession testSession;
+ private Root testRoot;
+ private Principal testGroupPrincipal;
+
+ @Before
+ @Override
+ public void before() throws Exception {
+ super.before();
+
+ Group testGroup = getUserManager(root).createGroup(TEST_GROUP_ID);
+ testGroupPrincipal = testGroup.getPrincipal();
+ User testUser2 = getUserManager(root).createUser(TEST_USER2_ID,
TEST_USER2_ID);
+ testGroup.addMember(testUser2);
+ root.commit();
+
+ // add more child nodes
+ NodeUtil n = new NodeUtil(root.getTree(SUPPORTED_PATH));
+ n.addChild("a", NT_OAK_UNSTRUCTURED).addChild("b",
NT_OAK_UNSTRUCTURED).addChild("c", NT_OAK_UNSTRUCTURED);
+ n.addChild("aa", NT_OAK_UNSTRUCTURED).addChild("bb",
NT_OAK_UNSTRUCTURED).addChild("cc", NT_OAK_UNSTRUCTURED);
+
+ // create cugs
+ createCug("/content/a", testGroupPrincipal);
+ createCug("/content/aa/bb", testGroupPrincipal);
+ createCug("/content/a/b/c", EveryonePrincipal.getInstance());
+ createCug("/content2", EveryonePrincipal.getInstance());
+
+ // setup regular acl at /content
+ AccessControlManager acMgr = getAccessControlManager(root);
+ AccessControlList acl = AccessControlUtils.getAccessControlList(acMgr,
"/content");
+ acl.addAccessControlEntry(getTestUser().getPrincipal(),
privilegesFromNames(
+ PrivilegeConstants.JCR_READ));
+ acl.addAccessControlEntry(testGroupPrincipal, privilegesFromNames(
+ PrivilegeConstants.JCR_READ, PrivilegeConstants.REP_WRITE,
PrivilegeConstants.JCR_READ_ACCESS_CONTROL)
+ );
+ acMgr.setPolicy("/content", acl);
+
+ root.commit();
+
+ testSession = createTestSession();
+ testRoot = testSession.getLatestRoot();
+ }
+
+ @Override
+ public void after() throws Exception {
+ try {
+ // revert transient pending changes (that might be invalid)
+ root.refresh();
+
+ // remove the test group and second test user
+ Authorizable testGroup =
getUserManager(root).getAuthorizable(TEST_GROUP_ID);
+ if (testGroup != null) {
+ testGroup.remove();
+ }
+ Authorizable testUser2 =
getUserManager(root).getAuthorizable(TEST_USER2_ID);
+ if (testUser2 != null) {
+ testUser2.remove();
+ }
+ root.commit();
+ } finally {
+ if (testSession != null) {
+ testSession.close();
+ }
+ super.after();
+ }
+ }
+
+ private PermissionProvider createPermissionProvider(Set<Principal>
principals) {
+ return
getSecurityProvider().getConfiguration(AuthorizationConfiguration.class).getPermissionProvider(root,
adminSession.getWorkspaceName(), principals);
+ }
+
+ @Test
+ public void testRead() throws Exception {
+ List<String> noAccess = ImmutableList.of(
+ "/", UNSUPPORTED_PATH, /* no access */
+ "/content/a", "/content/a/b", "/content/aa/bb", /* granted by
ace, denied by cug */
+ "/content2" /* granted by cug only */
+ );
+ for (String p : noAccess) {
+ assertFalse(p, testRoot.getTree(p).exists());
+ }
+
+ List<String> readAccess = ImmutableList.of("/content",
"/content/subtree", "/content/a/b/c", "/content/aa");
+ for (String p : readAccess) {
+ assertTrue(p, testRoot.getTree(p).exists());
+ }
+ }
+
+ @Test
+ public void testReadAcl() throws Exception {
+ assertFalse(testRoot.getTree("/content/rep:policy").exists());
+ }
+
+ @Test
+ public void testReadAcl2() throws Exception {
+ ContentSession cs = login(new SimpleCredentials(TEST_USER2_ID,
TEST_USER2_ID.toCharArray()));
+ try {
+ Root r = cs.getLatestRoot();
+
+ assertTrue(r.getTree("/content/rep:policy").exists());
+ assertFalse(r.getTree("/content2/rep:cugPolicy").exists());
+ } finally {
+ cs.close();
+ }
+ }
+
+ @Ignore("FIXME: cugpolicy not detected as ac-content") // FIXME
+ @Test
+ public void testReadCug() throws Exception {
+ List<String> noAccess = ImmutableList.of(
+ "/content/a/rep:cugPolicy", "/content/aa/bb/rep:cugPolicy",
"/content2/rep:cugPolicy"
+ );
+ for (String p : noAccess) {
+ assertFalse(p, testRoot.getTree(p).exists());
+ }
+ }
+
+ @Test
+ public void testReadCug2() throws Exception {
+ ContentSession cs = login(new SimpleCredentials(TEST_USER2_ID,
TEST_USER2_ID.toCharArray()));
+ try {
+ Root r = cs.getLatestRoot();
+
+ assertTrue(r.getTree("/content/a/rep:cugPolicy").exists());
+ assertFalse(r.getTree("/content2/rep:cugPolicy").exists());
+ } finally {
+ cs.close();
+ }
+ }
+
+ @Test
+ public void testWrite() throws Exception {
+ List<String> readOnly = ImmutableList.of("/content", "/content/a/b/c");
+ for (String p : readOnly) {
+ try {
+ NodeUtil content = new NodeUtil(testRoot.getTree(p));
+ content.addChild("writeTest", NT_OAK_UNSTRUCTURED);
+ testRoot.commit();
+ fail();
+ } catch (CommitFailedException e) {
+ assertTrue(e.isAccessViolation());
+ } finally {
+ testRoot.refresh();
+ }
+ }
+ }
+
+ @Test
+ public void testWrite2() throws Exception {
+ ContentSession cs = login(new SimpleCredentials(TEST_USER2_ID,
TEST_USER2_ID.toCharArray()));
+ Root r = cs.getLatestRoot();
+ try {
+ List<String> readOnly = ImmutableList.of("/content",
"/content/a/b/c");
+ for (String p : readOnly) {
+ NodeUtil content = new NodeUtil(r.getTree(p));
+ content.addChild("writeTest", NT_OAK_UNSTRUCTURED);
+ r.commit();
+ }
+ } finally {
+ r.refresh();
+ cs.close();
+ }
+ }
+
+ @Test
+ public void testWriteAcl() throws Exception {
+ ContentSession cs = login(new SimpleCredentials(TEST_USER2_ID,
TEST_USER2_ID.toCharArray()));
+ Root r = cs.getLatestRoot();
+ try {
+ Tree tree = r.getTree("/content/a/b/c");
+ tree.setProperty(JCR_MIXINTYPES,
ImmutableList.of(MIX_REP_CUG_MIXIN,
AccessControlConstants.MIX_REP_ACCESS_CONTROLLABLE), Type.NAMES);
+
tree.addChild(AccessControlConstants.REP_POLICY).setProperty(JCR_PRIMARYTYPE,
AccessControlConstants.NT_REP_ACL, Type.NAME);
+ r.commit();
+ fail();
+ } catch (CommitFailedException e) {
+ assertTrue(e.isAccessViolation());
+ } finally {
+ r.refresh();
+ }
+ }
+
+ @Ignore("FIXME: cugpolicy not detected as ac-content") // FIXME
+ @Test
+ public void testWriteCug() throws Exception {
+ ContentSession cs = login(new SimpleCredentials(TEST_USER2_ID,
TEST_USER2_ID.toCharArray()));
+ Root r = cs.getLatestRoot();
+ try {
+ // modify the existing cug
+ Tree tree = r.getTree("/content/a/rep:cugPolicy");
+ tree.setProperty(REP_PRINCIPAL_NAMES,
ImmutableList.of(EveryonePrincipal.NAME, testGroupPrincipal.getName()),
Type.STRINGS);
+ r.commit();
+ fail();
+ } catch (CommitFailedException e) {
+ assertTrue(e.isAccessViolation());
+ } finally {
+ r.refresh();
+ }
+ }
+
+ @Test
+ public void testIsGranted() throws Exception {
+ Tree content = root.getTree("/content");
+ Tree a = root.getTree("/content/a");
+ Tree c = root.getTree("/content/a/b/c");
+
+ // testGroup
+ Set<Principal> principals = ImmutableSet.of(testGroupPrincipal);
+ PermissionProvider pp = createPermissionProvider(principals);
+
+ assertTrue(pp.isGranted(content, null, Permissions.READ));
+ assertTrue(pp.isGranted(a, null, Permissions.READ));
+ assertFalse(pp.isGranted(c, null, Permissions.READ));
+
+ assertTrue(pp.isGranted(content, null,
Permissions.READ_ACCESS_CONTROL));
+ assertTrue(pp.isGranted(a, null, Permissions.READ_ACCESS_CONTROL));
+ assertTrue(pp.isGranted(c, null, Permissions.READ_ACCESS_CONTROL));
+
+ // everyone
+ principals =
ImmutableSet.<Principal>of(EveryonePrincipal.getInstance());
+ pp = createPermissionProvider(principals);
+
+ assertFalse(pp.isGranted(content, null, Permissions.READ));
+ assertFalse(pp.isGranted(a, null, Permissions.READ));
+ assertFalse(pp.isGranted(c, null, Permissions.READ));
+
+ assertFalse(pp.isGranted(content, null,
Permissions.READ_ACCESS_CONTROL));
+ assertFalse(pp.isGranted(a, null, Permissions.READ_ACCESS_CONTROL));
+ assertFalse(pp.isGranted(c, null, Permissions.READ_ACCESS_CONTROL));
+
+ // testGroup + everyone
+ principals = ImmutableSet.of(testGroupPrincipal,
EveryonePrincipal.getInstance());
+ pp = createPermissionProvider(principals);
+
+ assertTrue(pp.isGranted(content, null, Permissions.READ));
+ assertTrue(pp.isGranted(a, null, Permissions.READ));
+ assertTrue(pp.isGranted(c, null, Permissions.READ));
+
+ assertTrue(pp.isGranted(content, null,
Permissions.READ_ACCESS_CONTROL));
+ assertTrue(pp.isGranted(a, null, Permissions.READ_ACCESS_CONTROL));
+ assertTrue(pp.isGranted(c, null, Permissions.READ_ACCESS_CONTROL));
+
+ // testUser + everyone
+ principals = ImmutableSet.of(getTestUser().getPrincipal(),
EveryonePrincipal.getInstance());
+ pp = createPermissionProvider(principals);
+
+ assertTrue(pp.isGranted(content, null, Permissions.READ));
+ assertFalse(pp.isGranted(a, null, Permissions.READ));
+ assertTrue(pp.isGranted(c, null, Permissions.READ));
+
+ assertFalse(pp.isGranted(content, null,
Permissions.READ_ACCESS_CONTROL));
+ assertFalse(pp.isGranted(a, null, Permissions.READ_ACCESS_CONTROL));
+ assertFalse(pp.isGranted(c, null, Permissions.READ_ACCESS_CONTROL));
+ }
+
+ @Test
+ public void testHasPrivileges() throws Exception {
+ Tree content = root.getTree("/content");
+ Tree a = root.getTree("/content/a");
+ Tree c = root.getTree("/content/a/b/c");
+
+ // testGroup
+ Set<Principal> principals = ImmutableSet.of(testGroupPrincipal);
+ PermissionProvider pp = createPermissionProvider(principals);
+
+ assertTrue(pp.hasPrivileges(content, PrivilegeConstants.JCR_READ));
+ assertTrue(pp.hasPrivileges(a, PrivilegeConstants.JCR_READ));
+ assertFalse(pp.hasPrivileges(c, PrivilegeConstants.JCR_READ));
+
+ assertTrue(pp.hasPrivileges(content, PrivilegeConstants.REP_WRITE,
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+ assertTrue(pp.hasPrivileges(a, PrivilegeConstants.REP_WRITE,
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+ assertTrue(pp.hasPrivileges(c, PrivilegeConstants.REP_WRITE,
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+
+ // everyone
+ principals =
ImmutableSet.<Principal>of(EveryonePrincipal.getInstance());
+ pp = createPermissionProvider(principals);
+
+ assertFalse(pp.hasPrivileges(content, PrivilegeConstants.JCR_READ));
+ assertFalse(pp.hasPrivileges(a, PrivilegeConstants.JCR_READ));
+ assertFalse(pp.hasPrivileges(c, PrivilegeConstants.JCR_READ));
+
+ assertFalse(pp.hasPrivileges(content, PrivilegeConstants.REP_WRITE,
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+ assertFalse(pp.hasPrivileges(a, PrivilegeConstants.REP_WRITE,
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+ assertFalse(pp.hasPrivileges(c, PrivilegeConstants.REP_WRITE,
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+
+ // testGroup + everyone
+ principals = ImmutableSet.of(testGroupPrincipal,
EveryonePrincipal.getInstance());
+ pp = createPermissionProvider(principals);
+
+ assertTrue(pp.hasPrivileges(content, PrivilegeConstants.JCR_READ));
+ assertTrue(pp.hasPrivileges(a, PrivilegeConstants.JCR_READ));
+ assertTrue(pp.hasPrivileges(c, PrivilegeConstants.JCR_READ));
+
+ assertTrue(pp.hasPrivileges(content, PrivilegeConstants.REP_WRITE,
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+ assertTrue(pp.hasPrivileges(a, PrivilegeConstants.REP_WRITE,
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+ assertTrue(pp.hasPrivileges(c, PrivilegeConstants.REP_WRITE,
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+
+ // testUser + everyone
+ principals = ImmutableSet.of(getTestUser().getPrincipal(),
EveryonePrincipal.getInstance());
+ pp = createPermissionProvider(principals);
+
+ assertTrue(pp.hasPrivileges(content, PrivilegeConstants.JCR_READ));
+ assertFalse(pp.hasPrivileges(a, PrivilegeConstants.JCR_READ));
+ assertTrue(pp.hasPrivileges(c, PrivilegeConstants.JCR_READ));
+
+ assertFalse(pp.hasPrivileges(content, PrivilegeConstants.REP_WRITE,
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+ assertFalse(pp.hasPrivileges(a, PrivilegeConstants.REP_WRITE,
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+ assertFalse(pp.hasPrivileges(c, PrivilegeConstants.REP_WRITE,
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+ }
+
+ @Test
+ public void testHasAllPrivileges() throws Exception {
+ // testGroup
+ Set<Principal> principals = ImmutableSet.of(testGroupPrincipal);
+ PermissionProvider pp = createPermissionProvider(principals);
+
+ assertFalse(pp.hasPrivileges(root.getTree("/content"),
PrivilegeConstants.JCR_ALL));
+ assertFalse(pp.hasPrivileges(root.getTree("/content/a"),
PrivilegeConstants.JCR_ALL));
+ assertFalse(pp.hasPrivileges(root.getTree("/content/b/c"),
PrivilegeConstants.JCR_ALL));
+ }
+
+ @Test
+ public void testHasAllPrivileges2() throws Exception {
+ AccessControlManager acMgr = getAccessControlManager(root);
+ AccessControlList acl = AccessControlUtils.getAccessControlList(acMgr,
"/content/a");
+ acl.addAccessControlEntry(testGroupPrincipal,
privilegesFromNames(PrivilegeConstants.JCR_ALL));
+ acMgr.setPolicy("/content/a", acl);
+ root.commit();
+
+ // testGroup
+ Set<Principal> principals = ImmutableSet.of(testGroupPrincipal);
+ PermissionProvider pp = createPermissionProvider(principals);
+
+ assertFalse(pp.hasPrivileges(root.getTree("/content"),
PrivilegeConstants.JCR_ALL));
+ assertTrue(pp.hasPrivileges(root.getTree("/content/a"),
PrivilegeConstants.JCR_ALL));
+ assertTrue(pp.hasPrivileges(root.getTree("/content/a/b"),
PrivilegeConstants.JCR_ALL));
+ assertFalse(pp.hasPrivileges(root.getTree("/content/a/b/c"),
PrivilegeConstants.JCR_ALL));
+ }
+
+ @Test
+ public void testHasAllPrivileges3() throws Exception {
+ // admin principal
+ Set<Principal> principals = adminSession.getAuthInfo().getPrincipals();
+ PermissionProvider pp = createPermissionProvider(principals);
+
+ assertTrue(pp.hasPrivileges(root.getTree("/content"),
PrivilegeConstants.JCR_ALL));
+ assertTrue(pp.hasPrivileges(root.getTree("/content/a"),
PrivilegeConstants.JCR_ALL));
+ assertTrue(pp.hasPrivileges(root.getTree("/content/a/b/c"),
PrivilegeConstants.JCR_ALL));
+ }
+
+ @Ignore() // FIXME
+ @Test
+ public void testGetPrivileges() throws Exception {
+ Tree content = root.getTree("/content");
+ Tree a = root.getTree("/content/a");
+ Tree c = root.getTree("/content/a/b/c");
+
+ Set<String> r = ImmutableSet.of(PrivilegeConstants.JCR_READ);
+ Set<String> w_rac = ImmutableSet.of(PrivilegeConstants.REP_WRITE,
PrivilegeConstants.JCR_READ_ACCESS_CONTROL);
+ Set<String> r_w_rac = ImmutableSet.of(PrivilegeConstants.JCR_READ,
PrivilegeConstants.REP_WRITE, PrivilegeConstants.JCR_READ_ACCESS_CONTROL);
+
+ // testGroup
+ Set<Principal> principals = ImmutableSet.of(testGroupPrincipal);
+ PermissionProvider pp = createPermissionProvider(principals);
+
+ assertEquals(r_w_rac, pp.getPrivileges(content));
+ assertEquals(r_w_rac, pp.getPrivileges(a));
+ assertEquals(w_rac, pp.getPrivileges(c));
+
+ // everyone
+ principals =
ImmutableSet.<Principal>of(EveryonePrincipal.getInstance());
+ pp = createPermissionProvider(principals);
+
+ assertTrue(pp.getPrivileges(content).isEmpty());
+ assertTrue(pp.getPrivileges(a).isEmpty());
+ assertTrue(pp.getPrivileges(c).isEmpty());
+
+ // testGroup + everyone
+ principals = ImmutableSet.of(testGroupPrincipal,
EveryonePrincipal.getInstance());
+ pp = createPermissionProvider(principals);
+
+ assertEquals(r_w_rac, pp.getPrivileges(content));
+ assertEquals(r_w_rac, pp.getPrivileges(a));
+ assertEquals(r_w_rac, pp.getPrivileges(c));
+
+ // testUser + everyone
+ principals = ImmutableSet.of(getTestUser().getPrincipal(),
EveryonePrincipal.getInstance());
+ pp = createPermissionProvider(principals);
+
+ assertEquals(r, pp.getPrivileges(content));
+ assertTrue(pp.getPrivileges(a).isEmpty());
+ assertEquals(r, pp.getPrivileges(c));
+ }
}
\ No newline at end of file
Modified:
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProviderTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProviderTest.java?rev=1663623&r1=1663622&r2=1663623&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProviderTest.java
(original)
+++
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProviderTest.java
Tue Mar 3 10:51:54 2015
@@ -17,62 +17,337 @@
package org.apache.jackrabbit.oak.spi.security.authorization.cug.impl;
import java.security.Principal;
-import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import java.util.Set;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.Session;
-import
org.apache.jackrabbit.oak.spi.security.authorization.permission.ControlFlag;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
+import
org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
+import
org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;
+import
org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission;
+import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.apache.jackrabbit.oak.util.NodeUtil;
import org.junit.Before;
import org.junit.Test;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
-public class CugPermissionProviderTest extends AbstractCugTest {
+public class CugPermissionProviderTest extends AbstractCugTest implements
NodeTypeConstants {
- private CugPermissionProvider ppSufficient;
- private CugPermissionProvider ppRequisite;
+ private static final String TEST_GROUP_ID = "testGroupForCugTest";
+
+ private Principal testGroupPrincipal;
+ private CugPermissionProvider cugPermProvider;
@Before
@Override
public void before() throws Exception {
super.before();
- Set<Principal> principals = Collections.emptySet(); // TODO
- String[] supportedPaths = new String[0]; // TODO
+ Group testGroup = getUserManager(root).createGroup(TEST_GROUP_ID);
+ root.commit();
+
+ // add more child nodes
+ NodeUtil n = new NodeUtil(root.getTree(SUPPORTED_PATH));
+ n.addChild("a", NT_OAK_UNSTRUCTURED).addChild("b",
NT_OAK_UNSTRUCTURED).addChild("c", NT_OAK_UNSTRUCTURED);
+ n.addChild("aa", NT_OAK_UNSTRUCTURED).addChild("bb",
NT_OAK_UNSTRUCTURED).addChild("cc", NT_OAK_UNSTRUCTURED);
+
+ testGroupPrincipal = testGroup.getPrincipal();
+ createCug("/content/a", testGroupPrincipal);
+ createCug("/content/a/b/c", EveryonePrincipal.getInstance());
+ createCug("/content/aa/bb", testGroupPrincipal);
+
+ root.commit();
- ppSufficient = new CugPermissionProvider(root, principals,
supportedPaths, ControlFlag.SUFFICIENT, CugContext.INSTANCE);
- ppRequisite = new CugPermissionProvider(root, principals,
supportedPaths, ControlFlag.REQUISITE, CugContext.INSTANCE);
+ Set<Principal> principals =
ImmutableSet.of(getTestUser().getPrincipal(), EveryonePrincipal.getInstance());
+ String[] supportedPaths = new String[] {SUPPORTED_PATH};
+
+ cugPermProvider = new CugPermissionProvider(root, principals,
supportedPaths, CugContext.INSTANCE);
}
- @Test
- public void testGetFlag() {
- assertSame(ControlFlag.SUFFICIENT, ppSufficient.getFlag());
- assertSame(ControlFlag.REQUISITE, ppRequisite.getFlag());
+ @Override
+ public void after() throws Exception {
+ try {
+ // revert transient pending changes (that might be invalid)
+ root.refresh();
+
+ // remove the test group
+ Authorizable testGroup =
getUserManager(root).getAuthorizable(TEST_GROUP_ID);
+ if (testGroup != null) {
+ testGroup.remove();
+ }
+ root.commit();
+ } finally {
+ super.after();
+ }
}
@Test
public void testHandlesPath() {
- // TODO
+ Map<String, Boolean> pathMap = new HashMap<String, Boolean>();
+ pathMap.put(SUPPORTED_PATH, false);
+ pathMap.put("/content/a", true);
+ pathMap.put("/content/a/rep:cugPolicy", true);
+ pathMap.put("/content/a/b", true);
+ pathMap.put("/content/a/b/c/jcr:primaryType", true);
+ pathMap.put("/content/aa", false);
+ pathMap.put("/content/aa/bb/cc", true);
+ // paths that may not contain cugs anyway
+ pathMap.put(NODE_TYPES_PATH, false);
+ pathMap.put("/", false);
+ pathMap.put(UNSUPPORTED_PATH, false);
+ pathMap.put(INVALID_PATH, false);
+
+ for (String path : pathMap.keySet()) {
+ boolean expected = pathMap.get(path);
+
+ assertEquals(path, expected, cugPermProvider.handles(path,
Session.ACTION_READ));
+ assertFalse(cugPermProvider.handles(path,
Session.ACTION_ADD_NODE));
+ }
}
@Test
public void testHandlesTree() {
- // TODO
+ Map<Tree, Boolean> pathMap = new HashMap<Tree, Boolean>();
+ pathMap.put(root.getTree(SUPPORTED_PATH), false);
+ pathMap.put(root.getTree("/content/a"), true);
+ pathMap.put(root.getTree("/content/a/rep:cugPolicy"), true);
+ pathMap.put(root.getTree("/content/a/b"), true);
+ pathMap.put(root.getTree("/content/a/b/c/jcr:primaryType"), true);
+ pathMap.put(root.getTree("/content/aa"), false);
+ pathMap.put(root.getTree("/content/aa/bb/cc"), true);
+ // paths that may not contain cugs anyway
+ pathMap.put(root.getTree(NODE_TYPES_PATH), false);
+ pathMap.put(root.getTree("/"), false);
+ pathMap.put(root.getTree(UNSUPPORTED_PATH), false);
+ pathMap.put(root.getTree(INVALID_PATH), false);
+
+ for (Tree tree : pathMap.keySet()) {
+ boolean expected = pathMap.get(tree);
+
+ assertEquals(tree.getPath(), expected,
cugPermProvider.handles(tree,
PrivilegeBits.BUILT_IN.get(PrivilegeConstants.JCR_READ)));
+ assertEquals(tree.getPath(), expected,
cugPermProvider.handles(tree, Permissions.READ));
+ assertEquals(tree.getPath(), expected,
cugPermProvider.handles(tree, Permissions.READ_PROPERTY));
+ assertEquals(tree.getPath(), expected,
cugPermProvider.handles(tree, Permissions.READ_NODE));
+
+ assertFalse(cugPermProvider.handles(tree,
Permissions.ADD_NODE|Permissions.REMOVE));
+ }
+ }
+
+ @Test
+ public void testHandlesTreePermission() {
+ TreePermission rootTp =
cugPermProvider.getTreePermission(root.getTree("/"), TreePermission.EMPTY);
+
+ Map<TreePermission, Boolean> tpMap = new HashMap<TreePermission,
Boolean>();
+
+ TreePermission contentTp =
cugPermProvider.getTreePermission(root.getTree(SUPPORTED_PATH), rootTp);
+ tpMap.put(contentTp, false);
+
+ TreePermission aTp =
cugPermProvider.getTreePermission(root.getTree("/content/a"), contentTp);
+ tpMap.put(aTp, true);
+
tpMap.put(cugPermProvider.getTreePermission(root.getTree("/content/a/rep:cugPolicy"),
aTp), true);
+
+ TreePermission bTp =
cugPermProvider.getTreePermission(root.getTree("/content/a/b"), aTp);
+ tpMap.put(bTp, true);
+
tpMap.put(cugPermProvider.getTreePermission(root.getTree("/content/a/b/c"),
bTp), true);
+
+ TreePermission aaTp =
cugPermProvider.getTreePermission(root.getTree("/content/aa"), contentTp);
+ tpMap.put(aaTp, false);
+
+ TreePermission bbTp =
cugPermProvider.getTreePermission(root.getTree("/content/aa/bb"), aaTp);
+
tpMap.put(cugPermProvider.getTreePermission(root.getTree("/content/aa/bb/cc"),
bbTp), true);
+
+ // paths that may not contain cugs anyway
+
tpMap.put(cugPermProvider.getTreePermission(root.getTree("/jcr:system"),
rootTp), false);
+ tpMap.put(rootTp, false);
+
tpMap.put(cugPermProvider.getTreePermission(root.getTree(UNSUPPORTED_PATH),
rootTp), false);
+
+ for (TreePermission tp : tpMap.keySet()) {
+ boolean expected = tpMap.get(tp);
+
+ assertEquals(expected, cugPermProvider.handles(tp,
Permissions.READ));
+ assertEquals(expected, cugPermProvider.handles(tp,
Permissions.READ_NODE));
+ assertEquals(expected, cugPermProvider.handles(tp,
Permissions.READ_PROPERTY));
+
+ assertFalse(cugPermProvider.handles(tp,
Permissions.ADD_NODE|Permissions.REMOVE));
+ }
}
@Test
public void testHandlesRepositoryPermissions() {
- assertFalse(ppSufficient.handlesRepositoryPermissions());
- assertFalse(ppRequisite.handlesRepositoryPermissions());
+ assertFalse(cugPermProvider.handlesRepositoryPermissions());
}
@Test
public void getPrivileges() {
- // TODO
+ List<String> paths = ImmutableList.of("/", UNSUPPORTED_PATH,
+ "/content", "/content/a", "/content/a/b",
+ "/content/aa", "/content/bb", "/content/aa/bb/rep:cugPolicy");
+ for (String p : paths) {
+
assertTrue(cugPermProvider.getPrivileges(root.getTree(p)).isEmpty());
+ }
}
@Test
- public void hasPrivileges() {
- // TODO
+ public void testGetPrivilegesAtCug() {
+ Set<String> expected = ImmutableSet.of(
+ PrivilegeConstants.JCR_READ,
+ PrivilegeConstants.REP_READ_NODES,
+ PrivilegeConstants.REP_READ_PROPERTIES);
+ assertEquals(expected,
cugPermProvider.getPrivileges(root.getTree("/content/a/b/c")));
+ }
+
+ @Test
+ public void testGetPrivilegesAtCug2() {
+ PermissionProvider pp = new CugPermissionProvider(root,
ImmutableSet.of(testGroupPrincipal), new String[] {SUPPORTED_PATH},
CugContext.INSTANCE);
+
+ Set<String> expected = ImmutableSet.of(
+ PrivilegeConstants.JCR_READ,
+ PrivilegeConstants.REP_READ_NODES,
+ PrivilegeConstants.REP_READ_PROPERTIES);
+ assertEquals(expected, pp.getPrivileges(root.getTree("/content/a")));
+ assertEquals(expected,
pp.getPrivileges(root.getTree("/content/aa/bb")));
+
+ assertTrue(pp.getPrivileges(root.getTree("/content/a/b/c")).isEmpty());
+ }
+
+ @Test
+ public void hasReadPrivileges() {
+ List<String> paths = ImmutableList.of("/", UNSUPPORTED_PATH,
+ "/content", "/content/a", "/content/a/b",
+ "/content/aa", "/content/bb", "/content/aa/bb/rep:cugPolicy");
+ for (String p : paths) {
+ Tree tree = root.getTree(p);
+ assertFalse(cugPermProvider.hasPrivileges(tree,
PrivilegeConstants.JCR_READ));
+ assertFalse(cugPermProvider.hasPrivileges(tree,
PrivilegeConstants.REP_READ_NODES));
+ assertFalse(cugPermProvider.hasPrivileges(tree,
PrivilegeConstants.REP_READ_PROPERTIES));
+ assertFalse(cugPermProvider.hasPrivileges(tree,
PrivilegeConstants.REP_READ_NODES, PrivilegeConstants.REP_READ_PROPERTIES));
+ }
+
+ Tree cugTree = root.getTree("/content/a/b/c");
+ assertTrue(cugPermProvider.hasPrivileges(cugTree,
PrivilegeConstants.JCR_READ));
+ assertTrue(cugPermProvider.hasPrivileges(cugTree,
PrivilegeConstants.REP_READ_NODES));
+ assertTrue(cugPermProvider.hasPrivileges(cugTree,
PrivilegeConstants.REP_READ_PROPERTIES));
+ assertTrue(cugPermProvider.hasPrivileges(cugTree,
PrivilegeConstants.REP_READ_NODES, PrivilegeConstants.REP_READ_PROPERTIES));
+ }
+
+ @Test
+ public void hasNonReadPrivileges() {
+ List<String> paths = ImmutableList.of("/", UNSUPPORTED_PATH,
+ "/content", "/content/a", "/content/a/b", "/content/a/b/c",
+ "/content/aa", "/content/bb", "/content/aa/bb/rep:cugPolicy");
+ for (String p : paths) {
+ Tree tree = root.getTree(p);
+ assertFalse(cugPermProvider.hasPrivileges(tree,
PrivilegeConstants.JCR_WRITE));
+ assertFalse(cugPermProvider.hasPrivileges(tree,
PrivilegeConstants.JCR_LIFECYCLE_MANAGEMENT));
+ assertFalse(cugPermProvider.hasPrivileges(tree,
PrivilegeConstants.JCR_READ, PrivilegeConstants.JCR_LIFECYCLE_MANAGEMENT));
+ assertFalse(cugPermProvider.hasPrivileges(tree,
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+ assertFalse(cugPermProvider.hasPrivileges(tree,
PrivilegeConstants.JCR_ALL));
+ }
+ }
+
+ @Test
+ public void testIsGrantedRead() {
+ List<String> paths = ImmutableList.of("/", UNSUPPORTED_PATH,
+ "/content", "/content/a", "/content/a/b",
+ "/content/aa", "/content/bb", "/content/aa/bb/rep:cugPolicy");
+ for (String p : paths) {
+ Tree tree = root.getTree(p);
+ assertFalse(cugPermProvider.isGranted(tree, null,
Permissions.READ));
+ assertFalse(cugPermProvider.isGranted(tree,
tree.getProperty(JCR_PRIMARYTYPE), Permissions.READ_PROPERTY));
+ }
+
+ Tree cugTree = root.getTree("/content/a/b/c");
+ assertTrue(cugPermProvider.isGranted(cugTree, null, Permissions.READ));
+ assertTrue(cugPermProvider.isGranted(cugTree, null,
Permissions.READ_NODE));
+ assertTrue(cugPermProvider.isGranted(cugTree,
cugTree.getProperty(JCR_PRIMARYTYPE), Permissions.READ_PROPERTY));
+ }
+
+ @Test
+ public void testIsGrantedNonRead() {
+ List<String> paths = ImmutableList.of("/", UNSUPPORTED_PATH,
+ "/content", "/content/a", "/content/a/b",
"/content/a/b/c",
+ "/content/aa", "/content/bb",
"/content/aa/bb/rep:cugPolicy");
+ for (String p : paths) {
+ Tree tree = root.getTree(p);
+ assertFalse(cugPermProvider.isGranted(tree, null,
Permissions.ALL));
+ assertFalse(cugPermProvider.isGranted(tree, null,
Permissions.READ|Permissions.READ_ACCESS_CONTROL));
+ assertFalse(cugPermProvider.isGranted(tree, null,
Permissions.REMOVE_NODE));
+ }
+ }
+
+ @Test
+ public void testIsGrantedJcrActions() {
+ List<String> paths = ImmutableList.of("/", UNSUPPORTED_PATH,
+ "/content", "/content/a", "/content/a/b",
+ "/content/aa", "/content/bb", "/content/aa/bb/rep:cugPolicy");
+ for (String p : paths) {
+ assertFalse(cugPermProvider.isGranted(p, Session.ACTION_READ));
+ assertFalse(cugPermProvider.isGranted(p, Session.ACTION_ADD_NODE));
+ assertFalse(cugPermProvider.isGranted(p, Session.ACTION_READ + ','
+ Session.ACTION_ADD_NODE));
+ }
+
+ assertTrue(cugPermProvider.isGranted("/content/a/b/c",
Session.ACTION_READ));
+ assertFalse(cugPermProvider.isGranted("/content/a/b/c",
Session.ACTION_ADD_NODE));
+ assertFalse(cugPermProvider.isGranted("/content/a/b/c",
Session.ACTION_READ + ',' + Session.ACTION_ADD_NODE));
+ }
+
+ @Test
+ public void testGetTreePermissions() throws AccessDeniedException {
+ TreePermission rootTp =
cugPermProvider.getTreePermission(root.getTree("/"), TreePermission.EMPTY);
+ assertTrue(rootTp.getClass().getName().endsWith("EmptyCugPermission"));
+
+ TreePermission contentTp =
cugPermProvider.getTreePermission(root.getTree(SUPPORTED_PATH), rootTp);
+
assertTrue(contentTp.getClass().getName().endsWith("EmptyCugPermission"));
+
+ TreePermission aTp =
cugPermProvider.getTreePermission(root.getTree("/content/a"), contentTp);
+ assertTrue(aTp.getClass().getName().endsWith("CugTreePermission"));
+
+ TreePermission bTp =
cugPermProvider.getTreePermission(root.getTree("/content/a/b"), aTp);
+ assertTrue(bTp.getClass().getName().endsWith("CugTreePermission"));
+
+ TreePermission cTp =
cugPermProvider.getTreePermission(root.getTree("/content/a/b/c"), bTp);
+ assertTrue(cTp.getClass().getName().endsWith("CugTreePermission"));
+
+ TreePermission aaTp =
cugPermProvider.getTreePermission(root.getTree("/content/aa"), contentTp);
+ assertTrue(aaTp.getClass().getName().endsWith("EmptyCugPermission"));
+
+ TreePermission bbTp =
cugPermProvider.getTreePermission(root.getTree("/content/aa/bb"), aaTp);
+ assertTrue(bbTp.getClass().getName().endsWith("CugTreePermission"));
+
+ TreePermission ccTp =
cugPermProvider.getTreePermission(root.getTree("/content/aa/bb/cc"), bbTp);
+ assertTrue(ccTp.getClass().getName().endsWith("CugTreePermission"));
+
+ // false cug-policy node (wrong nt)
+ Tree aaTree = root.getTree("/content/aa");
+ new NodeUtil(aaTree).addChild(CugConstants.REP_CUG_POLICY,
NT_OAK_UNSTRUCTURED);
+ TreePermission aaTp2 =
cugPermProvider.getTreePermission(root.getTree("/content/aa"), contentTp);
+ assertTrue(aaTp2.getClass().getName().endsWith("EmptyCugPermission"));
+
+ TreePermission falseCugTp =
cugPermProvider.getTreePermission(root.getTree("/content/aa/rep:cugPolicy"),
aaTp2);
+ assertNotSame(TreePermission.EMPTY, falseCugTp);
+
+ // ac content
+ TreePermission cugTp =
cugPermProvider.getTreePermission(root.getTree("/content/a/rep:cugPolicy"),
aTp);
+ assertSame(TreePermission.EMPTY, cugTp);
+ // TODO: for regular acl-node
+
+ // paths that may not contain cugs anyway
+ assertSame(TreePermission.EMPTY,
cugPermProvider.getTreePermission(root.getTree("/jcr:system"), rootTp));
+ assertSame(TreePermission.EMPTY,
cugPermProvider.getTreePermission(root.getTree(UNSUPPORTED_PATH), rootTp));
}
}
\ No newline at end of file