You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by an...@apache.org on 2013/04/24 15:02:26 UTC
svn commit: r1471392 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/
oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/
oak-core/src/main/java/org/apache/jackrabbit/o...
Author: angela
Date: Wed Apr 24 13:02:26 2013
New Revision: 1471392
URL: http://svn.apache.org/r1471392
Log:
OAK-785 : PermissionValidator: add compatibility flag to ignore USER_MGT permission
Added:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/Jr2CompatibilityTest.java
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/UserManagementTest.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlConfigurationImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlConstants.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlInitializer.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidator.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidatorProvider.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/ConfigurationParameters.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/AccessControlConfiguration.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/ConfigurationParametersTest.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlConfigurationImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlConfigurationImpl.java?rev=1471392&r1=1471391&r2=1471392&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlConfigurationImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlConfigurationImpl.java Wed Apr 24 13:02:26 2013
@@ -35,6 +35,7 @@ import org.apache.jackrabbit.oak.securit
import org.apache.jackrabbit.oak.spi.commit.CommitHook;
import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
import org.apache.jackrabbit.oak.spi.lifecycle.WorkspaceInitializer;
+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.SecurityProvider;
@@ -49,9 +50,11 @@ import org.apache.jackrabbit.oak.spi.xml
public class AccessControlConfigurationImpl extends SecurityConfiguration.Default implements AccessControlConfiguration {
private final SecurityProvider securityProvider;
+ private final ConfigurationParameters config;
public AccessControlConfigurationImpl(SecurityProvider securityProvider) {
this.securityProvider = securityProvider;
+ config = securityProvider.getConfiguration(PARAM_ACCESS_CONTROL_OPTIONS);
}
//----------------------------------------------< SecurityConfiguration >---
@@ -63,6 +66,12 @@ public class AccessControlConfigurationI
@Nonnull
@Override
+ public ConfigurationParameters getConfigurationParameters() {
+ return config;
+ }
+
+ @Nonnull
+ @Override
public WorkspaceInitializer getWorkspaceInitializer() {
return new AccessControlInitializer();
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlConstants.java?rev=1471392&r1=1471391&r2=1471392&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlConstants.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlConstants.java Wed Apr 24 13:02:26 2013
@@ -36,7 +36,6 @@ public interface AccessControlConstants
*/
String REP_RESTRICTIONS = "rep:restrictions";
-
String MIX_REP_ACCESS_CONTROLLABLE = "rep:AccessControllable";
String MIX_REP_REPO_ACCESS_CONTROLLABLE = "rep:RepoAccessControllable";
String NT_REP_POLICY = "rep:Policy";
@@ -55,4 +54,16 @@ public interface AccessControlConstants
Collection<String> ACE_PROPERTY_NAMES = ImmutableSet.of(REP_PRINCIPAL_NAME, REP_PRIVILEGES);
Collection<String> AC_NODETYPE_NAMES = ImmutableSet.of(NT_REP_POLICY, NT_REP_ACL, NT_REP_ACE, NT_REP_DENY_ACE, NT_REP_GRANT_ACE, NT_REP_RESTRICTIONS);
+
+ /**
+ * Configuration parameter to enforce backwards compatible permission
+ * validation with respect to user/group creation, modification and removal.
+ * As of OAK 1.0 those actions require
+ * {@link org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions#USER_MANAGEMENT USER_MANAGEMENT}
+ * permissions while in Jackrabbit 2.0 they were covered by regular item
+ * write permissions.
+ *
+ * @since OAK 1.0
+ */
+ String PARAM_PERMISSIONS_JR2 = "permissionsJr2";
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlInitializer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlInitializer.java?rev=1471392&r1=1471391&r2=1471392&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlInitializer.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlInitializer.java Wed Apr 24 13:02:26 2013
@@ -31,7 +31,7 @@ import org.apache.jackrabbit.oak.spi.sta
* a property index definitions for {@link #REP_PRINCIPAL_NAME rep:principalName}
* properties defined with ACE nodes.
*/
-public class AccessControlInitializer implements WorkspaceInitializer, AccessControlConstants {
+class AccessControlInitializer implements WorkspaceInitializer, AccessControlConstants {
@Nonnull
@Override
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidator.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidator.java?rev=1471392&r1=1471391&r2=1471392&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidator.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidator.java Wed Apr 24 13:02:26 2013
@@ -161,7 +161,7 @@ class PermissionValidator extends Defaul
if (!permissionProvider.isGranted(tree, null, toTest)) {
throw new CommitFailedException(ACCESS, 0, "Access denied");
}
- if (noTraverse(toTest)) {
+ if (noTraverse(toTest, defaultPermission)) {
return null;
} else {
return (isBefore) ?
@@ -207,7 +207,8 @@ class PermissionValidator extends Defaul
long perm;
if (provider.getAccessControlContext().definesTree(tree)) {
perm = Permissions.MODIFY_ACCESS_CONTROL;
- } else if (provider.getUserContext().definesTree(tree)) {
+ } else if (provider.getUserContext().definesTree(tree)
+ && !provider.jr2Permissions()) {
perm = Permissions.USER_MANAGEMENT;
} else {
// FIXME: OAK-710 (identify renaming/move of nodes that only required MODIFY_CHILD_NODE_COLLECTION permission)
@@ -232,7 +233,8 @@ class PermissionValidator extends Defaul
perm = Permissions.VERSION_MANAGEMENT;
} else if (provider.getAccessControlContext().definesProperty(parent, propertyState)) {
perm = Permissions.MODIFY_ACCESS_CONTROL;
- } else if (provider.getUserContext().definesProperty(parent, propertyState)) {
+ } else if (provider.getUserContext().definesProperty(parent, propertyState)
+ && !provider.jr2Permissions()) {
perm = Permissions.USER_MANAGEMENT;
} else {
perm = defaultPermission;
@@ -245,10 +247,11 @@ class PermissionValidator extends Defaul
}
// TODO
- public static boolean noTraverse(long permission) {
+ public static boolean noTraverse(long permission, long defaultPermission) {
return permission == Permissions.MODIFY_ACCESS_CONTROL ||
permission == Permissions.VERSION_MANAGEMENT ||
- permission == Permissions.REMOVE_NODE;
+ permission == Permissions.REMOVE_NODE ||
+ defaultPermission == Permissions.REMOVE_NODE;
}
// TODO
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidatorProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidatorProvider.java?rev=1471392&r1=1471391&r2=1471392&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidatorProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidatorProvider.java Wed Apr 24 13:02:26 2013
@@ -22,8 +22,10 @@ import javax.security.auth.Subject;
import org.apache.jackrabbit.oak.core.ImmutableTree;
import org.apache.jackrabbit.oak.core.TreeTypeProviderImpl;
+import org.apache.jackrabbit.oak.security.authorization.AccessControlConstants;
import org.apache.jackrabbit.oak.spi.commit.Validator;
import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.Context;
import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
@@ -35,12 +37,16 @@ import org.apache.jackrabbit.oak.spi.sta
public class PermissionValidatorProvider extends ValidatorProvider {
private final SecurityProvider securityProvider;
+ private final boolean jr2Permissions;
private Context acCtx;
private Context userCtx;
public PermissionValidatorProvider(SecurityProvider securityProvider) {
this.securityProvider = securityProvider;
+
+ ConfigurationParameters params = securityProvider.getAccessControlConfiguration().getConfigurationParameters();
+ jr2Permissions = params.getConfigValue(AccessControlConstants.PARAM_PERMISSIONS_JR2, false);
}
//--------------------------------------------------< ValidatorProvider >---
@@ -67,6 +73,10 @@ public class PermissionValidatorProvider
return userCtx;
}
+ boolean jr2Permissions() {
+ return jr2Permissions;
+ }
+
private ImmutableTree createTree(NodeState root) {
return new ImmutableTree(root, new TreeTypeProviderImpl(getAccessControlContext()));
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/ConfigurationParameters.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/ConfigurationParameters.java?rev=1471392&r1=1471391&r2=1471392&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/ConfigurationParameters.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/ConfigurationParameters.java Wed Apr 24 13:02:26 2013
@@ -18,6 +18,9 @@ package org.apache.jackrabbit.oak.spi.se
import java.util.Collections;
import java.util.Map;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,11 +43,45 @@ public class ConfigurationParameters {
this(null);
}
- public ConfigurationParameters(Map<String, ?> options) {
+ public ConfigurationParameters(@Nullable Map<String, ?> options) {
this.options = (options == null) ? Collections.<String, Object>emptyMap() : Collections.unmodifiableMap(options);
}
- public <T> T getConfigValue(String key, T defaultValue) {
+ /**
+ * Returns {@code true} if this instance contains a configuration entry with
+ * the specified key irrespective of the defined value; {@code false} otherwise.
+ *
+ * @param key The key to be tested.
+ * @return {@code true} if this instance contains a configuration entry with
+ * the specified key irrespective of the defined value; {@code false} otherwise.
+ */
+ public boolean contains(@Nonnull String key) {
+ return options.containsKey(key);
+ }
+
+ /**
+ * Returns the value of the configuration entry with the given {@code key}
+ * applying the following rules:
+ *
+ * <ul>
+ * <li>If this instance doesn't contain a configuration entry with that
+ * key the specified {@code defaultValue} will be returned.</li>
+ * <li>If {@code defaultValue} is {@code null} the original value will
+ * be returned.</li>
+ * <li>If the configured value is {@code null} this method will always
+ * return {@code null}.</li>
+ * <li>If neither {@code defaultValue} nor the configured value is
+ * {@code null} an attempt is made to convert the configured value to
+ * match the type of the default value.</li>
+ * </ul>
+ *
+ * @param key The name of the configuration option.
+ * @param defaultValue The default value to return if no such entry exists
+ * or to use for conversion.
+ * @return The original or converted configuration value or {@code null}.
+ */
+ @CheckForNull
+ public <T> T getConfigValue(@Nonnull String key, @Nullable T defaultValue) {
if (options != null && options.containsKey(key)) {
return convert(options.get(key), defaultValue);
} else {
@@ -54,7 +91,8 @@ public class ConfigurationParameters {
//--------------------------------------------------------< private >---
@SuppressWarnings("unchecked")
- private static <T> T convert(Object configProperty, T defaultValue) {
+ @CheckForNull
+ private static <T> T convert(@Nullable Object configProperty, @Nullable T defaultValue) {
if (configProperty == null) {
return null;
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/AccessControlConfiguration.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/AccessControlConfiguration.java?rev=1471392&r1=1471391&r2=1471392&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/AccessControlConfiguration.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/AccessControlConfiguration.java Wed Apr 24 13:02:26 2013
@@ -32,6 +32,8 @@ import org.apache.jackrabbit.oak.spi.sec
*/
public interface AccessControlConfiguration extends SecurityConfiguration {
+ String PARAM_ACCESS_CONTROL_OPTIONS = "org.apache.jackrabbit.oak.accesscontrol.options";
+
@Nonnull
AccessControlManager getAccessControlManager(@Nonnull Root root,
@Nonnull NamePathMapper namePathMapper);
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java?rev=1471392&r1=1471391&r2=1471392&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java Wed Apr 24 13:02:26 2013
@@ -97,13 +97,17 @@ public abstract class AbstractSecurityTe
protected SecurityProvider getSecurityProvider() {
if (securityProvider == null) {
- securityProvider = new SecurityProviderImpl();
+ securityProvider = new SecurityProviderImpl(getSecurityConfigParameters());
}
return securityProvider;
}
+ protected ConfigurationParameters getSecurityConfigParameters() {
+ return ConfigurationParameters.EMPTY;
+ }
+
protected Configuration getConfiguration() {
- return ConfigurationUtil.getDefaultConfiguration(ConfigurationParameters.EMPTY);
+ return ConfigurationUtil.getDefaultConfiguration(getSecurityConfigParameters());
}
protected ContentSession login(@Nullable Credentials credentials)
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/ConfigurationParametersTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/ConfigurationParametersTest.java?rev=1471392&r1=1471391&r2=1471392&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/ConfigurationParametersTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/ConfigurationParametersTest.java Wed Apr 24 13:02:26 2013
@@ -26,8 +26,10 @@ import org.junit.Before;
import org.junit.Test;
import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
/**
* ConfigurationParametersTest...
@@ -41,6 +43,22 @@ public class ConfigurationParametersTest
public void tearDown() {}
@Test
+ public void testContains() {
+ ConfigurationParameters params = ConfigurationParameters.EMPTY;
+ assertFalse(params.contains("some"));
+ assertFalse(params.contains(""));
+
+ Map<String, String> map = new HashMap<String, String>();
+ map.put("key1", "v");
+ map.put("key2", "v");
+ params = new ConfigurationParameters(map);
+ assertTrue(params.contains("key1"));
+ assertTrue(params.contains("key2"));
+ assertFalse(params.contains("another"));
+ assertFalse(params.contains(""));
+ }
+
+ @Test
public void testGetConfigValue() {
Map<String, String> map = new HashMap<String, String>();
map.put("o1", "v");
@@ -120,6 +138,7 @@ public class ConfigurationParametersTest
assertNull(options.getConfigValue("test", null));
assertNull(options.getConfigValue("test", "value"));
assertNull(options.getConfigValue("test", new TestObject("t")));
+ assertNull(options.getConfigValue("test", false));
}
private class TestObject {
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/Jr2CompatibilityTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/Jr2CompatibilityTest.java?rev=1471392&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/Jr2CompatibilityTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/Jr2CompatibilityTest.java Wed Apr 24 13:02:26 2013
@@ -0,0 +1,108 @@
+/*
+ * 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.security.authorization.evaluation;
+
+import java.util.Collections;
+import java.util.Map;
+
+import javax.jcr.security.AccessControlEntry;
+import javax.jcr.security.AccessControlManager;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.security.authorization.AccessControlConstants;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+import org.apache.jackrabbit.oak.spi.security.authorization.AccessControlConfiguration;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Jr2CompatibilityTest... TODO
+ */
+public class Jr2CompatibilityTest extends AbstractOakCoreTest {
+
+ @Override
+ @Before
+ public void before() throws Exception {
+ super.before();
+ setupPermission("/", getTestUser().getPrincipal(), true, PrivilegeConstants.JCR_READ, PrivilegeConstants.REP_WRITE);
+ }
+
+ @Override
+ @After
+ public void after() throws Exception {
+ try {
+ AccessControlManager acMgr = getAccessControlManager(root);
+ JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(acMgr, "/");
+ if (acl != null) {
+ boolean modified = false;
+ for (AccessControlEntry entry : acl.getAccessControlEntries()) {
+ if (entry.getPrincipal().equals(getTestUser().getPrincipal())) {
+ acl.removeAccessControlEntry(entry);
+ modified = true;
+ }
+ }
+ if (modified) {
+ acMgr.setPolicy("/", acl);
+ root.commit();
+ }
+ }
+ } finally {
+ super.after();
+ }
+ }
+ @Override
+ protected ConfigurationParameters getSecurityConfigParameters() {
+ Map<String, Boolean> map = Collections.singletonMap(AccessControlConstants.PARAM_PERMISSIONS_JR2, Boolean.TRUE);
+ ConfigurationParameters acConfig = new ConfigurationParameters(map);
+
+ return new ConfigurationParameters(ImmutableMap.of(AccessControlConfiguration.PARAM_ACCESS_CONTROL_OPTIONS, acConfig));
+ }
+
+ @Test
+ public void testUserManagementPermissionWithJr2Flag() throws Exception {
+ Root testRoot = getTestRoot();
+ testRoot.refresh();
+
+ UserManager testUserMgr = getUserConfiguration().getUserManager(testRoot, NamePathMapper.DEFAULT);
+ try {
+ User u = testUserMgr.createUser("a", "b");
+ testRoot.commit();
+
+ u.changePassword("c");
+ testRoot.commit();
+
+ u.remove();
+ testRoot.commit();
+ } finally {
+ root.refresh();
+ Authorizable user = getUserManager().getAuthorizable("a");
+ if (user != null) {
+ user.remove();
+ root.commit();
+ }
+ }
+ }
+}
\ No newline at end of file
Added: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/UserManagementTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/UserManagementTest.java?rev=1471392&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/UserManagementTest.java (added)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/UserManagementTest.java Wed Apr 24 13:02:26 2013
@@ -0,0 +1,337 @@
+/*
+ * 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.jcr.security.authorization;
+
+import java.util.List;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.security.AccessControlEntry;
+import javax.jcr.security.Privilege;
+
+import com.google.common.collect.Lists;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
+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.api.security.user.UserManager;
+import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Testing permission evaluation for user management operations.
+ *
+ * @since OAK 1.0 As of OAK user mgt related operations require a specific
+ * user management permission (unless the system in configured to behave like
+ * jackrabbit 2x).
+ */
+public class UserManagementTest extends AbstractEvaluationTest {
+
+ private final String userId = "testUser2";
+ private final String groupId = "testGroup2";
+
+ private List<String> authorizablesToRemove = Lists.newArrayList(userId, groupId);
+
+ @Override
+ @Before
+ public void tearDown() throws Exception {
+ try {
+ testSession.refresh(false);
+ superuser.refresh(false);
+
+ UserManager userMgr = getUserManager(superuser);
+ for (String id : authorizablesToRemove) {
+ Authorizable a = userMgr.getAuthorizable(id);
+ if (a != null) {
+ a.remove();
+ }
+ }
+
+ JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(acMgr, "/");
+ if (acl != null) {
+ boolean modified = false;
+ for (AccessControlEntry entry : acl.getAccessControlEntries()) {
+ if (testUser.getPrincipal().equals(entry.getPrincipal())) {
+ acl.removeAccessControlEntry(entry);
+ modified = true;
+ }
+ }
+ if (modified) {
+ acMgr.setPolicy("/", acl);
+ }
+ }
+
+ superuser.save();
+ } finally {
+ super.tearDown();
+ }
+ }
+
+ private void createUser(String userId) throws Exception {
+ getUserManager(superuser).createUser(userId, "pw");
+ superuser.save();
+ testSession.refresh(false);
+ }
+
+ @Test
+ public void testCreateUserWithoutPermission() throws Exception {
+ UserManager testUserMgr = getUserManager(testSession);
+
+ // testSession has read-only access
+ try {
+ testUserMgr.createUser(userId, "pw");
+ testSession.save();
+ fail("Test session doesn't have sufficient permission -> creating user should fail.");
+ } catch (AccessDeniedException e) {
+ // success
+ }
+
+ // testSession has write permission but no user-mgt permission
+ // -> should still fail
+ modify("/", PrivilegeConstants.REP_WRITE, true);
+ try {
+ testUserMgr.createUser(userId, "pw");
+ testSession.save();
+ fail("Test session doesn't have sufficient permission -> creating user should fail.");
+ } catch (AccessDeniedException e) {
+ // success
+ }
+ }
+
+ @Test
+ public void testCreateUser() throws Exception {
+ UserManager testUserMgr = getUserManager(testSession);
+ Privilege[] privs = privilegesFromNames(new String[] {PrivilegeConstants.REP_USER_MANAGEMENT, PrivilegeConstants.REP_WRITE});
+ allow("/", privs);
+
+ // creating user should succeed
+ testUserMgr.createUser(userId, "pw");
+ testSession.save();
+ }
+
+ @Test
+ public void testCreateGroup() throws Exception {
+ UserManager testUserMgr = getUserManager(testSession);
+ Privilege[] privs = privilegesFromNames(new String[] {PrivilegeConstants.REP_USER_MANAGEMENT, PrivilegeConstants.REP_WRITE});
+ allow("/", privs);
+
+ // creating group should succeed
+ Group gr = testUserMgr.createGroup(groupId);
+ testSession.save();
+ }
+
+ @Test
+ public void testChangePasswordWithoutPermission() throws Exception {
+ createUser(userId);
+
+ UserManager testUserMgr = getUserManager(testSession);
+ User user = (User) testUserMgr.getAuthorizable(userId);
+ try {
+ user.changePassword("pw2");
+ testSession.save();
+ fail();
+ } catch (AccessDeniedException e) {
+ // success
+ }
+ }
+
+ @Test
+ public void testChangePasswordWithoutPermission2() throws Exception {
+ createUser(userId);
+
+ modify("/", PrivilegeConstants.REP_WRITE, true);
+
+ UserManager testUserMgr = getUserManager(testSession);
+ User user = (User) testUserMgr.getAuthorizable(userId);
+ try {
+ user.changePassword("pw2");
+ testSession.save();
+ fail();
+ } catch (AccessDeniedException e) {
+ // success
+ }
+ }
+
+ @Test
+ public void testChangePassword() throws Exception {
+ createUser(userId);
+
+ // after granting user-mgt privilege changing the pw must succeed.
+ modify("/", PrivilegeConstants.REP_USER_MANAGEMENT, true);
+
+ UserManager testUserMgr = getUserManager(testSession);
+ User user = (User) testUserMgr.getAuthorizable(userId);
+ user.changePassword("pw2");
+ testSession.save();
+ }
+
+ @Test
+ public void testDisableUserWithoutPermission() throws Exception {
+ createUser(userId);
+
+ UserManager testUserMgr = getUserManager(testSession);
+ User user = (User) testUserMgr.getAuthorizable(userId);
+ try {
+ user.disable("disabled!");
+ testSession.save();
+ fail();
+ } catch (AccessDeniedException e) {
+ // success
+ }
+ }
+
+ @Test
+ public void testDisableUserWithoutPermission2() throws Exception {
+ createUser(userId);
+
+ modify("/", PrivilegeConstants.REP_WRITE, true);
+
+ UserManager testUserMgr = getUserManager(testSession);
+ User user = (User) testUserMgr.getAuthorizable(userId);
+ try {
+ user.disable("disabled!");
+ testSession.save();
+ fail();
+ } catch (AccessDeniedException e) {
+ // success
+ }
+ }
+
+ @Test
+ public void testDisableUser() throws Exception {
+ createUser(userId);
+
+ // after granting user-mgt privilege changing the pw must succeed.
+ modify("/", PrivilegeConstants.REP_USER_MANAGEMENT, true);
+
+ UserManager testUserMgr = getUserManager(testSession);
+ User user = (User) testUserMgr.getAuthorizable(userId);
+ user.disable("disabled!");
+ testSession.save();
+ }
+
+ @Test
+ public void testRemoveUserWithoutPermission() throws Exception {
+ createUser(userId);
+
+ UserManager testUserMgr = getUserManager(testSession);
+ // testSession has read-only access
+ try {
+ Authorizable a = testUserMgr.getAuthorizable(userId);
+ a.remove();
+ testSession.save();
+ fail("Test session doesn't have sufficient permission to remove a user.");
+ } catch (AccessDeniedException e) {
+ // success
+ }
+
+ // testSession has write permission but no user-mgt permission
+ // -> should still fail
+ modify("/", PrivilegeConstants.REP_WRITE, true);
+ try {
+ Authorizable a = testUserMgr.getAuthorizable(userId);
+ a.remove();
+ testSession.save();
+ fail("Test session doesn't have sufficient permission to remove a user.");
+ } catch (AccessDeniedException e) {
+ // success
+ }
+ }
+
+ @Test
+ public void testRemoveUser() throws Exception {
+ createUser(userId);
+
+ // testSession has user-mgt permission -> removal should succeed.
+ modify("/", PrivilegeConstants.REP_USER_MANAGEMENT, true);
+
+ UserManager testUserMgr = getUserManager(testSession);
+ Authorizable a = testUserMgr.getAuthorizable(userId);
+ a.remove();
+ testSession.save();
+ }
+
+ @Test
+ public void testRemoveUser2() throws Exception {
+ createUser(userId);
+
+ // testSession has user-mgt permission -> removal should succeed.
+ Privilege[] privs = privilegesFromNames(new String[] {
+ PrivilegeConstants.REP_USER_MANAGEMENT,
+ PrivilegeConstants.REP_WRITE});
+ allow("/", privs);
+
+ UserManager testUserMgr = getUserManager(testSession);
+ Authorizable a = testUserMgr.getAuthorizable(userId);
+ a.remove();
+ testSession.save();
+ }
+
+ @Test
+ public void testChangeUserPropertiesWithoutPermission() throws Exception {
+ createUser(userId);
+
+ // testSession has read-only access
+ UserManager testUserMgr = getUserManager(testSession);
+ try {
+ Authorizable a = testUserMgr.getAuthorizable(userId);
+ a.setProperty("someProp", testSession.getValueFactory().createValue("value"));
+ testSession.save();
+ fail("Test session doesn't have sufficient permission to alter user properties.");
+ } catch (AccessDeniedException e) {
+ // success
+ }
+ }
+
+ @Test
+ public void testChangeUserPropertiesWithoutPermission2() throws Exception {
+ createUser(userId);
+
+ // testSession has read and user-mgt permission but lacks permission to
+ // alter regular properties
+ modify("/", PrivilegeConstants.REP_USER_MANAGEMENT, true);
+
+ UserManager testUserMgr = getUserManager(testSession);
+ try {
+ Authorizable a = testUserMgr.getAuthorizable(userId);
+ a.setProperty("someProp", testSession.getValueFactory().createValue("value"));
+ testSession.save();
+ fail("Test session doesn't have sufficient permission to alter user properties.");
+ } catch (AccessDeniedException e) {
+ // success
+ }
+ }
+
+ @Test
+ public void testChangeUserProperties() throws Exception {
+ createUser(userId);
+
+ // make sure user can create/modify/remove regular properties
+ modify("/", PrivilegeConstants.JCR_MODIFY_PROPERTIES, true);
+
+ UserManager testUserMgr = getUserManager(testSession);
+ Authorizable a = testUserMgr.getAuthorizable(userId);
+ a.setProperty("someProp", testSession.getValueFactory().createValue("value"));
+ testSession.save();
+
+ a.setProperty("someProperty", testSession.getValueFactory().createValue("modified"));
+ testSession.save();
+
+ a.removeProperty("someProperty");
+ testSession.save();
+ }
+}
\ No newline at end of file