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 2015/06/18 16:30:17 UTC
svn commit: r1686235 [4/6] - in /jackrabbit/oak/trunk: ./
oak-doc/src/site/markdown/ oak-exercise/ oak-exercise/src/
oak-exercise/src/main/ oak-exercise/src/main/java/
oak-exercise/src/main/java/org/ oak-exercise/src/main/java/org/apache/
oak-exercise/...
Propchange: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L3_PrecedenceRulesTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L4_PrivilegesAndPermissionsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L4_PrivilegesAndPermissionsTest.java?rev=1686235&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L4_PrivilegesAndPermissionsTest.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L4_PrivilegesAndPermissionsTest.java Thu Jun 18 14:30:16 2015
@@ -0,0 +1,505 @@
+/*
+ * 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.permission;
+
+import java.security.Principal;
+import java.util.Map;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.Privilege;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.api.JackrabbitSession;
+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.plugins.nodetype.NodeTypeConstants;
+import org.apache.jackrabbit.oak.security.ExerciseUtility;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.test.api.util.Text;
+
+/**
+ * <pre>
+ * Module: Authorization (Permission Evaluation)
+ * =============================================================================
+ *
+ * Title: Privileges and Permissions
+ * -----------------------------------------------------------------------------
+ *
+ * Goal:
+ * The aim of this is test is to make you familiar with the subtle differences
+ * between privileges (that are always granted on an existing node) and effective
+ * permissions on the individual items (nodes, properties or even non-existing
+ * items).
+ * Having completed this exercise you should also be familiar with the oddities
+ * of those privileges that allow modify the parent collection, while the effective
+ * permission is evaluated the target item.
+ *
+ * Exercises:
+ *
+ * - {@link #testAddNodes()}
+ * This test aims to practise the subtle difference between granting 'jcr:addChildNode'
+ * privilege at a given parent node and {@link Session#hasPermission(String, String)}
+ * using {@link Session#ACTION_ADD_NODE}, which effectively tests if a given
+ * new node could be created.
+ * Fill in the expected values for the permission discovery with the given
+ * permission setup. Subsequently, list the expected values for
+ * {@link javax.jcr.security.AccessControlManager#getPrivileges(String)}.
+ * Explain the difference given the mini-explanation in the test introduction.
+ *
+ * - {@link #testAddProperties()}
+ * This test grants the test user privilege to add properties at 'childPath'.
+ * Fill in the expected result of {@link javax.jcr.Session#hasPermission(String, String)}
+ * both for the regular JCR action {@link Session#ACTION_SET_PROPERTY} and
+ * for the string value of {@link Permissions#ADD_PROPERTY}. Compare and explain
+ * the differences.
+ *
+ * - {@link #testRemoveNodes()} ()}
+ * This test illustrates what kind of privileges are required in order to
+ * remove a given node. Fix the test-case by setting the correct permission
+ * setup.
+ *
+ * - {@link #testRemoveProperties()} ()}
+ * In this test the test-user is only granted rep:removeProperties privilege
+ * and lists which properties must be removable. Nevertheless the test-case is
+ * broken... can you identify the root cause without modifying the result map
+ * nor the permission setup?
+ *
+ * - {@link #testRemoveNonExistingItems()}
+ * Look at the contract of {@link Session#hasPermission(String, String)} and
+ * the implementation present in Oak to understand what happens if you test
+ * permissions for removal of non-existing items.
+ *
+ * - {@link #testModifyProperties()}
+ * Now the test-user is just allowed to modify properties. Complete the test
+ * by modifying the result-map: add for each path whether accessing and setting
+ * the properties is expected to succeed. Explain for each path why it passes
+ * or fails. In case of doubt debug the test to understand what is going on.
+ *
+ * - {@link #testSetProperty()}
+ * Properties cannot only be modified by calling {@link Property#setValue}
+ * but also by calling {@link Node#setProperty} each for different types and
+ * single vs multivalued properties. While they are mostly equivalent there
+ * are subtle differences that have an impact on the permission evaluation.
+ * Can you find suitable value(s) for each of these paths such that the
+ * test passes?
+ * Hint: passing a 'null' value is defined to be equivalent to removal.
+ * Discuss your findings.
+ *
+ * Question: Can you explain the required values if the test user was allowed
+ * to remove properties instead? -> Modify the test to verify your expectations.
+ *
+ * - {@link #testChangingPrimaryAndMixinTypes()}
+ * In order to change the primary (or mixin) type(s) of a given existing node
+ * the editing session must have {@link Privilege#JCR_NODE_TYPE_MANAGEMENT}
+ * privilege granted.
+ * For consistency with this requirement, also {@link Node#addNode(String, String)},
+ * which explicitly specifies the primary type requires this privilege as
+ * the effective operation is equivalent to the combination of:
+ * 1. {@link Node#addNode(String)} +
+ * 2. {@link Node#setPrimaryType(String)}
+ * Use this test case to become familiar with setting or changing the primary
+ * type and modifying the set of mixin types.
+ *
+ *
+ * Additional Exercises:
+ * -----------------------------------------------------------------------------
+ *
+ * - Modifying Nodes
+ * Discuss why there is no dedicated privilege (and test case) for "modify nodes".
+ * Explain how {@link Privilege#JCR_NODE_TYPE_MANAGEMENT, {@link Privilege#JCR_ADD_CHILD_NODES},
+ * {@link Privilege#JCR_REMOVE_CHILD_NODES} (and maybe others) are linked to
+ * node modification.
+ *
+ *
+ * Advanced Exercises:
+ * -----------------------------------------------------------------------------
+ *
+ * If you wished to become more familiar with the interals of the Oak permission
+ * evaluation, it is indispensible to understand the internal representation of
+ * registered privileges (as {@link org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits}
+ * and their mapping to {@link org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions}.
+ *
+ * Precondition for these advanced exercises is the following test:
+ *
+ * - {@link org.apache.jackrabbit.oak.security.privilege.L5_PrivilegeContentTest }
+ *
+ * The following exercises aim to provide you with some insight and allow you
+ * to understand the internal structure of the permission store.
+ *
+ * - PrivilegeBits and the corresponding provider class
+ * Take a look at the methods exposed by
+ * {@link org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBitsProvider}
+ * and the {@link org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits}
+ * class itself. Using these classes Oak generates the repository internal
+ * representation of the privileges that are used for
+ * - calculation of effective privileges
+ * - calculation of final permission from effective privileges granted (or denied)
+ *
+ * - Mapping Privileges to Permissions
+ * As you could see in the above exercises there is no 1:1 mapping between
+ * privileges and permissions as a few privileges (like jcr:addChildNodes and
+ * jcr:removeChildNodes) are granted for the parent node. This needs to be
+ * handled specially when evaluating if a given node can be created or removed.
+ * Look at {@link org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits#calculatePermissions()}
+ * and compare the code with the results obtained from the test-cases above.
+ *
+ * - Mapping of JCR Actions to Permissions
+ * The exercises also illustrated the subtle differences between 'actions'
+ * as defined on {@link javax.jcr.Session} and the effective permissions
+ * being evaluated.
+ * Take a closer look at {@link org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions#getPermissions(String, org.apache.jackrabbit.oak.plugins.tree.TreeLocation, boolean)}
+ * to improve your understanding on how the mapping is being implemented
+ * and discuss the consequences for {@link Session#hasPermission(String, String)}.
+ * Compare the code with the test-results.
+ *
+ *
+ * Related Exercises
+ * -----------------------------------------------------------------------------
+ *
+ * - {@link org.apache.jackrabbit.oak.security.authorization.permission.L5_SpecialPermissionsTest}
+ * - {@link L7_PermissionContentTest }
+ *
+ * </pre>
+ */
+public class L4_PrivilegesAndPermissionsTest extends AbstractJCRTest {
+
+ private User testUser;
+ private Principal testPrincipal;
+ private Principal testGroupPrincipal;
+ private Session testSession;
+
+ private String childPath;
+ private String grandChildPath;
+ private String propertyPath;
+ private String childPropertyPath;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ Property p = testRootNode.setProperty(propertyName1, "val");
+ propertyPath = p.getPath();
+
+ Node child = testRootNode.addNode(nodeName1);
+ childPath = child.getPath();
+
+ p = child.setProperty(propertyName2, "val");
+ childPropertyPath = p.getPath();
+
+ Node grandChild = child.addNode(nodeName2);
+ grandChildPath = grandChild.getPath();
+
+ testUser = ExerciseUtility.createTestUser(((JackrabbitSession) superuser).getUserManager());
+ Group testGroup = ExerciseUtility.createTestGroup(((JackrabbitSession) superuser).getUserManager());
+ testGroup.addMember(testUser);
+ superuser.save();
+
+ testPrincipal = testUser.getPrincipal();
+ testGroupPrincipal = testGroup.getPrincipal();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ try {
+ if (testSession != null && testSession.isLive()) {
+ testSession.logout();
+ }
+ UserManager uMgr = ((JackrabbitSession) superuser).getUserManager();
+ if (testUser != null) {
+ testUser.remove();
+ }
+ Authorizable testGroup = uMgr.getAuthorizable(testGroupPrincipal);
+ if (testGroup != null) {
+ testGroup.remove();
+ }
+ superuser.save();
+ } finally {
+ super.tearDown();
+ }
+ }
+
+ private Session createTestSession() throws RepositoryException {
+ if (testSession == null) {
+ testSession = superuser.getRepository().login(ExerciseUtility.getTestCredentials(testUser.getID()));
+ }
+ return testSession;
+ }
+
+ public void testAddNodes() throws Exception {
+ // grant the test principal jcr:addChildNode privilege at 'childPath'
+ AccessControlUtils.addAccessControlEntry(superuser, childPath, testPrincipal, new String[] {Privilege.JCR_ADD_CHILD_NODES}, true);
+ superuser.save();
+
+ Session userSession = createTestSession();
+
+ // EXERCISE: fill in the expected return values for Session.hasPermission as performed below
+ // EXERCISE: verify that the test passes and explain the individual results
+ Map<String, Boolean> pathHasPermissionMap = ImmutableMap.of(
+ testRootNode.getPath(), null,
+ childPath, null,
+ childPath + "/toCreate", null,
+ grandChildPath + "/nextGeneration", null,
+ propertyPath, null
+ );
+
+ for (String path : pathHasPermissionMap.keySet()) {
+ boolean expectedHasPermission = pathHasPermissionMap.get(path);
+ assertEquals(expectedHasPermission, userSession.hasPermission(path, Session.ACTION_ADD_NODE));
+ }
+
+ // EXERCISE: fill in the expected return values for AccessControlManager#getPrivileges as performed below
+ // EXERCISE: verify that the test passes and compare the results with your findings from the permission-discovery
+ Map<String, Privilege[]> pathPrivilegesMap = ImmutableMap.of(
+ testRootNode.getPath(), null,
+ childPath, null,
+ childPath + "/toCreate", null,
+ grandChildPath + "/nextGeneration", null
+ );
+
+ for (String path : pathPrivilegesMap.keySet()) {
+ Privilege[] expectedPrivileges = pathPrivilegesMap.get(path);
+ assertEquals(ImmutableSet.of(expectedPrivileges), ImmutableSet.of(userSession.getAccessControlManager().getPrivileges(path)));
+ }
+
+ // EXERCISE: optionally add nodes at the expected allowed path(s)
+ // EXERCISE: using 'userSession' to verify that it actually works and
+ // EXERCISE: save the changes to trigger the evaluation
+ }
+
+ public void testAddProperties() throws Exception {
+ // grant the test principal rep:addProperties privilege at 'childPath'
+ // EXERCISE: explain the difference between rep:addProperites and jcr:modifyProperties privilege!
+ AccessControlUtils.addAccessControlEntry(superuser, childPath, testPrincipal, new String[] {PrivilegeConstants.REP_ADD_PROPERTIES}, true);
+ superuser.save();
+
+ // EXERCISE: fill in the expected return values for Session.hasPermission as performed below
+ // EXERCISE: verify that the test passes and explain the individual results
+ Map<String, Boolean[]> pathHasPermissionMap = ImmutableMap.of(
+ propertyPath, new Boolean[]{null, null},
+ childPath + "/newProp", new Boolean[]{null, null},
+ childPropertyPath, new Boolean[]{null, null},
+ grandChildPath + "/" + JcrConstants.JCR_PRIMARYTYPE, new Boolean[]{null, null}
+ );
+
+ Session userSession = createTestSession();
+ for (String path : pathHasPermissionMap.keySet()) {
+ Boolean[] result = pathHasPermissionMap.get(path);
+ boolean setPropertyAction = result[0];
+ boolean addPropertiesPermission = result[1];
+ assertEquals(setPropertyAction, userSession.hasPermission(path, Session.ACTION_SET_PROPERTY));
+ assertEquals(addPropertiesPermission, userSession.hasPermission(path, Permissions.getString(Permissions.ADD_PROPERTY)));
+ }
+ }
+
+ public void testRemoveNodes() throws Exception {
+ // EXERCISE: setup the correct set of privileges such that the test passes
+ superuser.save();
+
+ Map<String, Boolean> pathHasPermissionMap = ImmutableMap.of(
+ testRootNode.getPath(), false,
+ childPath, false,
+ grandChildPath, true
+ );
+
+ Session userSession = createTestSession();
+ for (String path : pathHasPermissionMap.keySet()) {
+ boolean expectedHasPermission = pathHasPermissionMap.get(path);
+ assertEquals(expectedHasPermission, userSession.hasPermission(path, Session.ACTION_REMOVE));
+ }
+
+ AccessControlManager acMgr = userSession.getAccessControlManager();
+ assertFalse(acMgr.hasPrivileges(childPath, new Privilege[]{acMgr.privilegeFromName(Privilege.JCR_REMOVE_NODE)}));
+
+ userSession.getNode(grandChildPath).remove();
+ userSession.save();
+ }
+
+ public void testRemoveProperties() throws Exception {
+ // EXERCISE: fix the test case without changing the result-map :-)
+
+ // grant the test principal rep:removeProperties privilege at 'childPath'
+ AccessControlUtils.addAccessControlEntry(superuser, childPath, testPrincipal, new String[] {PrivilegeConstants.REP_REMOVE_PROPERTIES}, true);
+ superuser.save();
+
+ Map<String, Boolean> pathCanRemoveMap = ImmutableMap.of(
+ propertyPath, false,
+ childPropertyPath, true,
+ grandChildPath + "/" + JcrConstants.JCR_PRIMARYTYPE, false,
+ grandChildPath + "/" + propertyName2, false
+ );
+
+ Session userSession = createTestSession();
+ for (String path : pathCanRemoveMap.keySet()) {
+ boolean canRemove = pathCanRemoveMap.get(path);
+
+ try {
+ userSession.getProperty(path).remove();
+ if (!canRemove) {
+ fail("property at " + path + " should not be removable.");
+ }
+ } catch (RepositoryException e) {
+ if (canRemove) {
+ fail("property at " + path + " should be removable.");
+ }
+ } finally {
+ userSession.refresh(false);
+ }
+ }
+ }
+
+ public void testRemoveNonExistingItems() throws Exception {
+ AccessControlUtils.addAccessControlEntry(superuser, childPath, testPrincipal, new String[] {
+ Privilege.JCR_REMOVE_NODE,
+ Privilege.JCR_REMOVE_CHILD_NODES,
+ PrivilegeConstants.REP_REMOVE_PROPERTIES}, true);
+ superuser.save();
+
+ // EXERCISE: fill in the expected values for Session.hasPermission(path, Session.ACTION_REMOVE) and explain
+ Map<String, Boolean> pathHasPermission = ImmutableMap.of(
+ childPath + "_non_existing_sibling", null,
+ childPath + "/_non_existing_childitem", null,
+ grandChildPath + "/_non_existing_child_item", null
+ );
+
+ Session userSession = createTestSession();
+ for (String nonExistingItemPath : pathHasPermission.keySet()) {
+ boolean hasPermission = pathHasPermission.get(nonExistingItemPath).booleanValue();
+ assertEquals(hasPermission, userSession.hasPermission(nonExistingItemPath, Session.ACTION_REMOVE));
+ }
+
+ // Additional exercise:
+ // EXERCISE: change the set of privileges granted initially and observe the result of Session.hasPermission. Explain the diff
+ }
+
+ public void testModifyProperties() throws Exception {
+ // grant the test principal rep:alterProperties privilege at 'childPath'
+ AccessControlUtils.addAccessControlEntry(superuser, childPath, testPrincipal, new String[] {PrivilegeConstants.REP_ALTER_PROPERTIES}, true);
+ superuser.save();
+
+ // EXERCISE: Fill if setting the property at the path(s) is expected to pass or not
+ Map<String, Boolean> pathCanModify = ImmutableMap.of(
+ propertyPath, null,
+ childPropertyPath, null,
+ grandChildPath + "/" + JcrConstants.JCR_PRIMARYTYPE, null,
+ grandChildPath + "/" + propertyName2, null
+ );
+
+ Session userSession = createTestSession();
+ for (String path : pathCanModify.keySet()) {
+ boolean canModify = pathCanModify.get(path);
+ try {
+ userSession.getProperty(path).setValue("newVal");
+ userSession.save();
+ if (!canModify) {
+ fail("setting property at " + path + " should fail.");
+ }
+ } catch (RepositoryException e) {
+ if (canModify) {
+ fail("setting property at " + path + " should not fail.");
+ }
+ } finally {
+ userSession.refresh(false);
+ }
+ }
+ }
+
+ public void testSetProperty() throws RepositoryException {
+ // grant the test principal rep:removeProperties privilege at 'childPath'
+ AccessControlUtils.addAccessControlEntry(superuser, childPath, testPrincipal, new String[] {PrivilegeConstants.REP_ALTER_PROPERTIES}, true);
+ superuser.save();
+
+ // EXERCISE: Fill if new properties values such that the test-cases succeeds
+ // EXERCISE: Discuss your findings and explain each value.
+
+ Map<String, Value> pathResultMap = Maps.newHashMap();
+ pathResultMap.put(childPropertyPath, (Value) null);
+ pathResultMap.put(grandChildPath + "/nonexisting", (Value) null);
+
+ Session userSession = createTestSession();
+ for (String path : pathResultMap.keySet()) {
+ try {
+ Value val = pathResultMap.get(path);
+
+ Node parent = userSession.getNode(Text.getRelativeParent(path, 1));
+ parent.setProperty(Text.getName(path), val);
+
+ userSession.save();
+ } finally {
+ userSession.refresh(false);
+ }
+ }
+ }
+
+ public void testChangingPrimaryAndMixinTypes() throws RepositoryException {
+ // 1 - grant privilege to change node type information
+ // EXERCISE: fill in the required privilege name such that the test passes
+ String privilegeName = null;
+ AccessControlUtils.addAccessControlEntry(superuser, childPath, testPrincipal, new String[] {privilegeName}, true);
+ superuser.save();
+
+ Session userSession = createTestSession();
+ Node n = userSession.getNode(childPath);
+ n.setPrimaryType(NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+ n.addMixin(JcrConstants.MIX_REFERENCEABLE);
+ userSession.save();
+
+ // 2 - additionally grant privilege to add a child node
+ // EXERCISE: extend the set of privileges such that the adding a child node succeeds as well
+ privilegeName = null;
+ AccessControlUtils.addAccessControlEntry(superuser, childPath, testPrincipal, new String[] {privilegeName}, true);
+ superuser.save();
+
+ userSession.refresh(false);
+ userSession.getNode(childPath).addNode(nodeName4, NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+ userSession.save();
+
+ // 3 - revoke privilege to change node type information
+ // EXERCISE: change the permission setup again such that the rest of the test passes
+ superuser.save();
+
+ userSession.refresh(false);
+ n = userSession.getNode(childPath);
+ n.addNode(nodeName3);
+ userSession.save();
+
+ try {
+ n.addNode(nodeName1, NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+ userSession.save();
+ fail("Adding node with explicitly the primary type should fail");
+ } catch (AccessDeniedException e) {
+ // success
+ } finally {
+ userSession.refresh(false);
+ }
+
+
+ AccessControlUtils.addAccessControlEntry(superuser, childPath, testPrincipal, new String[] {privilegeName}, true);
+
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L4_PrivilegesAndPermissionsTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L5_SpecialPermissionsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L5_SpecialPermissionsTest.java?rev=1686235&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L5_SpecialPermissionsTest.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L5_SpecialPermissionsTest.java Thu Jun 18 14:30:16 2015
@@ -0,0 +1,289 @@
+/*
+ * 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.permission;
+
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.List;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.AccessControlPolicy;
+import javax.jcr.security.Privilege;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionHistory;
+import javax.jcr.version.VersionManager;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.api.JackrabbitSession;
+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.security.ExerciseUtility;
+import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.junit.Test;
+
+/**
+ * <pre>
+ * Module: Authorization (Permission Evaluation)
+ * =============================================================================
+ *
+ * Title: Special Permissions
+ * -----------------------------------------------------------------------------
+ *
+ * Goal:
+ * So far exercises mostly dealt with regalar read/write privileges. After having
+ * completed this exercise you should a better understanding on permission
+ * evaluation for non-regular write operations.
+ *
+ * Exercises:
+ *
+ * - {@link #testVersioning()}
+ * Performing version operations requires {@link Privilege#JCR_VERSION_MANAGEMENT}
+ * to be granted at the target node. Use this test to verify this.
+ *
+ * - {@link #testReadVersionInformation()}
+ * Testing read access to version storage at /jcr:system/jcr:versionStore
+ * Use {@link #testVersioning()} again to take a closer look on how versions
+ * and version-histories are being retrieved from the version store and how
+ * the corresponding read-access is being evaluated.
+ *
+ * Question: Can you explain what the difference is compared to Jackrabbit 2.x? (hint: oak-doc and jira)
+ * Question: Can you identify cases where access to /jcr:system/jcr:versionstore explicitly needed to be granted?
+ * If yes: explain why and the impact it may have from a security point of view.
+ *
+ * - {@link #testUserManagement()}
+ * Fix the test case such that there is no privilege escalation from testUser
+ * to the admin user :-)
+ *
+ * - {@link #testRepositoryLevelPrivileges()}
+ * The following privileges need to be granted globally for the whole repository
+ * as the associated operations also take effect on the whole repository.
+ * In order to do so, you need to use the 'null' paths... verify in this test
+ * that granting those privileges at 'childPath' does not have the desired effect.
+ *
+ *
+ * Additional Exercises:
+ * -----------------------------------------------------------------------------
+ *
+ * - Write additional test cases for the following privileges:
+ * - {@link Privilege#JCR_READ_ACCESS_CONTROL}
+ * - {@link Privilege#JCR_MODIFY_ACCESS_CONTROL}
+ * - {@link Privilege#JCR_LOCK_MANAGEMENT}
+ * - {@link org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants#REP_INDEX_DEFINITION_MANAGEMENT}
+ *
+ * Related Exercises:
+ * -----------------------------------------------------------------------------
+ *
+ * - {@link org.apache.jackrabbit.oak.security.privilege.L3_BuiltInPrivilegesTest#testMapItems()}
+ *
+ * </pre>
+ *
+ *
+ * @see org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants
+ * @see org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions
+ */
+public class L5_SpecialPermissionsTest extends AbstractJCRTest {
+
+ private User testUser;
+ private User testUser2;
+ private Principal testPrincipal;
+ private Principal testGroupPrincipal;
+ private Session testSession;
+
+ private String childPath;
+ private String grandChildPath;
+ private String propertyPath;
+ private String childPropertyPath;
+
+ private List<String> paths = new ArrayList();
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ Property p = testRootNode.setProperty(propertyName1, "val");
+ propertyPath = p.getPath();
+
+ Node child = testRootNode.addNode(nodeName1);
+ childPath = child.getPath();
+
+ p = child.setProperty(propertyName2, "val");
+ childPropertyPath = p.getPath();
+
+ Node grandChild = child.addNode(nodeName2);
+ grandChildPath = grandChild.getPath();
+
+ testUser = ExerciseUtility.createTestUser(((JackrabbitSession) superuser).getUserManager());
+ testUser2 = ExerciseUtility.createTestUser(((JackrabbitSession) superuser).getUserManager());
+ Group testGroup = ExerciseUtility.createTestGroup(((JackrabbitSession) superuser).getUserManager());
+ testGroup.addMember(testUser);
+ superuser.save();
+
+ testPrincipal = testUser.getPrincipal();
+ testGroupPrincipal = testGroup.getPrincipal();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ try {
+ if (testSession != null && testSession.isLive()) {
+ testSession.logout();
+ }
+ UserManager uMgr = ((JackrabbitSession) superuser).getUserManager();
+ if (testUser != null) {
+ testUser.remove();
+ }
+ if (testUser2 != null) {
+ testUser2.remove();
+ }
+ Authorizable testGroup = uMgr.getAuthorizable(testGroupPrincipal);
+ if (testGroup != null) {
+ testGroup.remove();
+ }
+
+ removePolicies(paths);
+
+ superuser.save();
+ } finally {
+ super.tearDown();
+ }
+ }
+
+ private void removePolicies(List<String> paths) throws RepositoryException {
+ AccessControlManager acMgr = superuser.getAccessControlManager();
+ for (String path : paths) {
+ AccessControlPolicy[] policies = acMgr.getPolicies(path);
+ for (AccessControlPolicy plc : policies) {
+ if (plc instanceof JackrabbitAccessControlList) {
+ acMgr.removePolicy(path, plc);
+ }
+ }
+ }
+ }
+
+ private Session createTestSession() throws RepositoryException {
+ if (testSession == null) {
+ testSession = superuser.getRepository().login(ExerciseUtility.getTestCredentials(testUser.getID()));
+ }
+ return testSession;
+ }
+
+ public void testVersioning() throws Exception {
+ // EXERCISE: fix the test case
+ superuser.getNode(childPath).addMixin(JcrConstants.MIX_VERSIONABLE);
+ superuser.getNode(grandChildPath).addMixin(JcrConstants.MIX_VERSIONABLE);
+
+ String privName = Privilege.JCR_VERSION_MANAGEMENT;
+ AccessControlUtils.addAccessControlEntry(superuser, grandChildPath, testGroupPrincipal, new String[]{privName}, true);
+ superuser.save();
+
+ Session s = createTestSession();
+
+ Node n = s.getNode(childPath);
+ Version v = n.checkin();
+ n.checkout();
+
+ n = s.getNode(grandChildPath);
+ v = n.checkin();
+ n.checkout();
+ }
+
+ @Test
+ public void testReadVersionInformation() throws RepositoryException {
+ Node childNode = superuser.getNode(childPath);
+ childNode.addMixin(JcrConstants.MIX_VERSIONABLE);
+ superuser.save();
+ childNode.checkin();
+ childNode.checkout();
+
+ // EXERCISE: uncomment the following permission setup and test the impact it has!
+ // EXERCISE: discuss and explain your findings
+// AccessControlUtils.addAccessControlEntry(superuser, "/jcr:system", testGroupPrincipal, new String[] {Privilege.JCR_READ}, false);
+// paths.add("/jcr:system");
+// superuser.save();
+//
+ Session s = createTestSession();
+
+ // EXERCISE: uncomment to verify the permission setup is as expected
+ //assertFalse(s.nodeExists(VersionConstants.VERSION_STORE_PATH));
+
+ VersionManager versionManager = s.getWorkspace().getVersionManager();
+ VersionHistory vh = versionManager.getVersionHistory(childPath);
+ Version rootVersion = vh.getRootVersion();
+ Version baseVersion = versionManager.getBaseVersion(childPath);
+ }
+
+ @Test
+ public void testUserManagement() throws RepositoryException {
+ // EXERCISE: fix the permission setup and explain why!
+
+ // grant full access to all users for 'testGroup'...
+ paths.add(UserConstants.DEFAULT_USER_PATH);
+ AccessControlUtils.addAccessControlEntry(superuser,
+ UserConstants.DEFAULT_USER_PATH, testGroupPrincipal,
+ new String[]{Privilege.JCR_ALL}, true);
+ // ... but prevent the test user to write the admin user
+ String adminPath = ((JackrabbitSession) superuser).getUserManager().getAuthorizable(superuser.getUserID()).getPath();
+ paths.add(adminPath);
+ AccessControlUtils.addAccessControlEntry(superuser,
+ adminPath, EveryonePrincipal.getInstance(),
+ new String[]{PrivilegeConstants.REP_WRITE}, false);
+
+
+ // execute the test verifying that pw of 'testUser2' can be change
+ // but not the pw of the admin user
+ JackrabbitSession s = (JackrabbitSession) createTestSession();
+
+ User u2 = s.getUserManager().getAuthorizable(testUser2.getID(), User.class);
+ u2.changePassword("gugus");
+ s.save();
+
+ try {
+ User admin = s.getUserManager().getAuthorizable(superuser.getUserID(), User.class);
+ admin.changePassword("gugus");
+ s.save();
+ fail("privilege escalation!");
+ } catch (AccessDeniedException e) {
+ // success
+ } finally {
+ s.refresh(false);
+ }
+ }
+
+ public void testRepositoryLevelPrivileges() throws RepositoryException {
+ // EXERCISE : setup the permissions such that test-session can register a
+ // - new namespace|node type|privilege (note: workspace management not yet supported)
+
+ // EXERCISE: refactory the test to verify that granting these privs at 'childPath' doesn;t have the desired effect.
+
+ JackrabbitSession s = (JackrabbitSession) createTestSession();
+
+ NamespaceRegistry nsRegistry = s.getWorkspace().getNamespaceRegistry();
+ nsRegistry.registerNamespace("jr", "http://jackrabbit.apache.org");
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L5_SpecialPermissionsTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L6_AdministratativeAccessTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L6_AdministratativeAccessTest.java?rev=1686235&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L6_AdministratativeAccessTest.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L6_AdministratativeAccessTest.java Thu Jun 18 14:30:16 2015
@@ -0,0 +1,109 @@
+/*
+ * 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.permission;
+
+import javax.jcr.AccessDeniedException;
+
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+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.plugins.nodetype.NodeTypeConstants;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+import org.apache.jackrabbit.oak.util.NodeUtil;
+import org.junit.Test;
+
+/**
+ * <pre>
+ * Module: Authorization (Permission Evaluation)
+ * =============================================================================
+ *
+ * Title: Administrative Permissions
+ * -----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Learn how the default implementation handles administrative access and makes
+ * sure administrative session always have full access to the repository and
+ * cannot be locked out.
+ *
+ * Exercises:
+ *
+ * - {@link #testAdmininistrativePermissions()}
+ * Use this test to walk through both read and write access with an administrative
+ * session.
+ *
+ * Question: Can you identify where there administrative permissions are being evaluated?
+ * Question: Can you list the differences compared to regular permission evaluation?
+ * Question: Can you explain, where the different handling is started and what are the criteria?
+ *
+ *
+ * Additional Exercises:
+ * -----------------------------------------------------------------------------
+ *
+ * - {@link #testAdministrativeConfiguration()}
+ * For this test you have to modify the default configuration such that the
+ * test principal is treated as administrative principal upon evaluation.
+ * Make sure the test passes and verify the expected result.
+ *
+ * </pre>
+ */
+public class L6_AdministratativeAccessTest extends AbstractSecurityTest {
+
+ @Test
+ public void testAdmininistrativePermissions() throws AccessDeniedException, CommitFailedException {
+ // EXERCISE walk through the read access
+ Tree rootTree = root.getTree("/");
+
+ // EXERCISE walk through the add + remove
+ NodeUtil child = new NodeUtil(rootTree).addChild("test", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+ root.commit();
+
+ child.getTree().remove();
+ root.commit();
+ }
+
+ @Override
+ protected ConfigurationParameters getSecurityConfigParameters() {
+ // EXERCISE : change the configuration to make the test principal being treated as 'administrative' principal
+ return super.getSecurityConfigParameters();
+ }
+
+ @Test
+ public void testAdministrativeConfiguration() throws Exception {
+ // EXERCISE once you have defined the right permission-eval configuration options
+ // EXERCISE the test principal should be treated as 'administrative' principal and the test should pass.
+
+ ContentSession testSession = createTestSession();
+ try {
+ Root testRoot = testSession.getLatestRoot();
+ Tree rootTree = testRoot.getTree("/");
+
+ // EXERCISE walk through the add + remove
+ NodeUtil child = new NodeUtil(rootTree).addChild("test", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+ child.setString("prop", "val");
+ testRoot.commit();
+
+ child.getTree().remove();
+ testRoot.commit();
+
+ } finally {
+ testSession.close();
+ }
+
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L6_AdministratativeAccessTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L7_PermissionContentTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L7_PermissionContentTest.java?rev=1686235&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L7_PermissionContentTest.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L7_PermissionContentTest.java Thu Jun 18 14:30:16 2015
@@ -0,0 +1,81 @@
+/*
+ * 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.permission;
+
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.junit.Test;
+
+/**
+ * <pre>
+ * Module: Authorization (Permission Evaluation)
+ * =============================================================================
+ *
+ * Title: Representation of Permissions in the Repository
+ * -----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Understand how the default implementation represents permissions in the repository.
+ * This advanced exercise aims to provide you with some insights to the permission
+ * store and how permissions are being evaluated from the content stored
+ * therein.
+ *
+ * Exercises:
+ *
+ * - Overview
+ * Look {@code org/apache/jackrabbit/oak/plugins/nodetype/write/builtin_nodetypes.cnd}
+ * and try to identify the built in node types used to store permission
+ * content.
+ *
+ * Question: Can explain the meaning of all types?
+ * Question: Why are most item definitions protected?
+ * Question: Can you identify node types that are not used? Can you explain why?
+ *
+ * - {@link #testAdministrativeAccessOnly()}
+ * The permission store is hidden from regular users and can only be
+ * accessed using an administrative session. Use to test to find out how this
+ * is enforced by the implementation.
+ *
+ * Question: Can you imagine why the permission store should only be accessible
+ * to administrative sessions?
+ * Question: Can you identify the class(es) that actually enforce this?
+ * Question: Can you explain why the permission store is not 'hidden' like the
+ * index content? Compare these different approaches and discuss your findings.
+ *
+ * - {@link #testReadOnly()}
+ * The permission store is a system maintained structure and cannot be edited
+ * using JCR or Oak API calls. This test aims to illustrate this behavior.
+ *
+ * Question: Can you explain why the permission store is read-only?
+ * Question: Can you identify the class(es) responsible for enforcing the read-only nature?
+ *
+ * - {@link #TODO}
+ *
+ * </pre>
+ */
+public class L7_PermissionContentTest extends AbstractSecurityTest {
+
+ @Test
+ public void testReadOnly() {
+ // TODO
+ }
+
+ @Test
+ public void testAdministrativeAccessOnly() {
+ // TODO
+ }
+
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L7_PermissionContentTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/general/IntroductionTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/general/IntroductionTest.java?rev=1686235&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/general/IntroductionTest.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/general/IntroductionTest.java Thu Jun 18 14:30:16 2015
@@ -0,0 +1,50 @@
+/*
+ * 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.general;
+
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+
+/**
+ * <pre>
+ * Module: Security General
+ * =============================================================================
+ *
+ * Title: Introduction
+ * -----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Get an overview over the various security related parts and modules present
+ * in Oak and how they interact.
+ *
+ * Exercises:
+ *
+ * - {@link #TODO}
+ *
+ *
+ * Additional Exercises:
+ * -----------------------------------------------------------------------------
+ *
+ * TODO
+ *
+ * </pre>
+ *
+ * @see TODO
+ */
+public class IntroductionTest extends AbstractSecurityTest {
+
+
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/general/IntroductionTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L1_IntroductionTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L1_IntroductionTest.java?rev=1686235&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L1_IntroductionTest.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L1_IntroductionTest.java Thu Jun 18 14:30:16 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.security.principal;
+
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+
+/**
+ * <pre>
+ * Module: Principal Management
+ * =============================================================================
+ *
+ * Title: Introduction to Principal Management
+ * -----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Understand the usage of principal management in Oak and become familiar with
+ * the difference between the Jackrabbit {@link PrincipalManager} and the
+ * {@link PrincipalProvider} exposed by Oak SPI.
+ *
+ * Exercises:
+ *
+ * - Overview and Usages of Principal Management
+ * Search for usage of principal management API (e.g. the {@link org.apache.jackrabbit.api.security.principal.PrincipalManager}
+ * and {@link org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider}
+ * interface in Oak _and_ Jackrabbit JCR Commons. List your findings and discuss the impact.
+ *
+ * Question: Where is the principal manager|provider being used for?
+ * Question: Who is the expected API consumer?
+ * Question: What are the characteristics of this areas?
+ * Question: What can you say about the relation of principal management and authentication?
+ * Question: What can you say about the relation of principal management and authorization?
+ *
+ *
+ * - Configuration
+ * Look at the default implementation of the {@link org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfigurationConfiguration}
+ * and try to identify the configurable parts. Compare your results with the
+ * Oak documentation.
+ *
+ * Question: Can you provide a list of configuration options?
+ *
+ * - Pluggability
+ * Become familar with the pluggable nature of the principal management
+ *
+ * Question: What means does Oak provide to change or extend the set of principals exposed?
+ * Question: What interfaces do you need to implement?
+ * Question: Is it possible to combine different principal implementations? How does that work?
+ *
+ *
+ * Additional Exercises:
+ * -----------------------------------------------------------------------------
+ *
+ * - Discuss why principal management API is read only.
+ *
+ * Question: How are principals exposed by the {@link PrincipalManager} collected?
+ * Question: How does the default implementation look like?
+ *
+ *
+ * Advanced Exercises:
+ * -----------------------------------------------------------------------------
+ *
+ * If you want to dig deeper into the principal management implementation details
+ * you may want to play around with plugging your custom principal provider instance
+ * or replacing the default setup altogether.
+ *
+ * - Write your your custom implemenation of the principal provider and deploy it
+ * in an OSGi based repository setup. Observe the effect it has on principal
+ * management, authentication and authorization.
+ *
+ *
+ * Related Exercises
+ * -----------------------------------------------------------------------------
+ *
+ * - {@link L2_PrincipalManagerTest}
+ * - {@link L4_PrincipalProviderTest}
+ * - {@link L3_EveryoneTest}
+ *
+ * </pre>
+ *
+ * @see org.apache.jackrabbit.api.security.principal.PrincipalManager
+ * @see org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider
+ */
+public class L1_IntroductionTest extends AbstractJCRTest {
+
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L1_IntroductionTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L2_PrincipalManagerTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L2_PrincipalManagerTest.java?rev=1686235&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L2_PrincipalManagerTest.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L2_PrincipalManagerTest.java Thu Jun 18 14:30:16 2015
@@ -0,0 +1,167 @@
+/*
+ * 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.principal;
+
+import java.security.Principal;
+import java.util.Set;
+import javax.jcr.RepositoryException;
+
+import com.google.common.collect.Sets;
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.principal.PrincipalIterator;
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.test.NotExecutableException;
+
+/**
+ * <pre>
+ * Module: Principal Management
+ * =============================================================================
+ *
+ * Title: Principal Manager
+ * -----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Get familiar with the {@link org.apache.jackrabbit.api.security.principal.PrincipalManager}
+ * interface.
+ *
+ * Exercises:
+ *
+ * - {@link #testHasPrincipal()}
+ * Walk through the test for an existing principal name to become familiar
+ * with the principal lookup.
+ * Complete the method {@link #getNonExistingPrincipalName()} such that the test passes.
+ *
+ *
+ * - {@link #testGetPrincipal()}
+ * Same as above for {@link PrincipalManager#getPrincipal(String)}
+ *
+ * - {@link #testFindPrincipals()}
+ * Become familiar with the principal query: Look at the API contract and
+ * try different variants of the {@link PrincipalManager#findPrincipals(String, int)} call.
+ *
+ * - {@link #testGetGroupMembership()}
+ * Retrive the principal groups our test principal is member of.
+ * Question: What is the expected result?
+ * Question: Is there a minimal set of principals? If yes, why?
+ *
+ *
+ * Additional Exercises
+ * -----------------------------------------------------------------------------
+ *
+ * - {@link #testMyPrincipal()}
+ * Make use of the characteristics of the default principal management
+ * implementation and adjust the test case such that it passes.
+ *
+ *
+ * Related Exercises
+ * -----------------------------------------------------------------------------
+ *
+ * - {@link L3_EveryoneTest}
+ *
+ * </pre>
+ *
+ * @see org.apache.jackrabbit.api.security.principal.PrincipalManager
+ */
+public class L2_PrincipalManagerTest extends AbstractJCRTest {
+
+ private PrincipalManager principalManager;
+
+ private String testPrincipalName;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ principalManager = ((JackrabbitSession) superuser).getPrincipalManager();
+
+ // NOTE: this method call doesn't make to much sense outside of a
+ // simple test with a very limited number of principals (!!)
+ PrincipalIterator principalIterator = principalManager.getPrincipals(PrincipalManager.SEARCH_TYPE_NOT_GROUP);
+ if (principalIterator.hasNext()) {
+ testPrincipalName = principalIterator.nextPrincipal().getName();
+ }
+
+ if (testPrincipalName == null) {
+ throw new NotExecutableException();
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ private String getNonExistingPrincipalName() {
+ // EXERCISE: return a non existing principal name (Q: what could you do instead of guessing?)
+ return null;
+ }
+
+ public void testHasPrincipal() throws RepositoryException {
+ assertTrue(principalManager.hasPrincipal(testPrincipalName));
+
+ assertFalse(principalManager.hasPrincipal(getNonExistingPrincipalName()));
+ }
+
+ public void testGetPrincipal() throws RepositoryException {
+ Principal principal = principalManager.getPrincipal(testPrincipalName);
+ assertNotNull(principal);
+
+ assertNull(principalManager.getPrincipal(getNonExistingPrincipalName()));
+ }
+
+ public void testFindPrincipals() throws RepositoryException {
+ String searchHint = testPrincipalName; // EXERCISE: play with the search hint
+ int searchType = PrincipalManager.SEARCH_TYPE_ALL; // EXERCISE: modify the type flag
+
+ PrincipalIterator principalIterator = principalManager.findPrincipals(testPrincipalName, searchType);
+
+ // EXERCISE: what is the expected query result depending on the search hint and the type-flag?
+ }
+
+ public void testGetGroupMembership() throws RepositoryException {
+ Principal principal = principalManager.getPrincipal(testPrincipalName);
+
+ PrincipalIterator groups = principalManager.getGroupMembership(principal);
+ // EXERCISE: what group principals do you expect here?
+ }
+
+ public void testMyPrincipal() throws RepositoryException {
+ String principalName = "myPrincipal";
+
+ // EXERCISE : fix the test case
+ // HINT : take advantage of the default implemenation (i.e. it's relation to user management)
+
+ try {
+ Principal testPrincipal = principalManager.getPrincipal(principalName);
+ assertNotNull(testPrincipal);
+
+ Set<String> groupNames = Sets.newHashSet("myGroup", EveryonePrincipal.NAME);
+ PrincipalIterator groups = principalManager.getGroupMembership(testPrincipal);
+ while (groups.hasNext()) {
+ groupNames.remove(groups.nextPrincipal().getName());
+ }
+
+ assertTrue(groupNames.isEmpty());
+ } finally {
+ // EXERCISE: cleanup
+ }
+ }
+
+
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L2_PrincipalManagerTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L3_EveryoneTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L3_EveryoneTest.java?rev=1686235&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L3_EveryoneTest.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L3_EveryoneTest.java Thu Jun 18 14:30:16 2015
@@ -0,0 +1,162 @@
+/*
+ * 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.principal;
+
+import java.security.Principal;
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.principal.PrincipalIterator;
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+
+/**
+ * <pre>
+ * Module: Principal Management
+ * =============================================================================
+ *
+ * Title: Everyone Test
+ * -----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Understand the role of the {@link org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal}
+ *
+ * Exercises:
+ *
+ * - {@link #testEveryoneExists()}
+ * Test to illustrate the that everyone principal always exists and always is
+ * an instanceof {@link java.security.acl.Group} even if there is no corresponding
+ * authorizable.
+ * Discuss the meaning of the everyone principal and why having a corresponding authorizable is optional.
+ * Note the difference between java.security.acl.Group and org.apache.jackrabbit.api.security.user.Group.
+ *
+ * - {@link #testEveryoneName()}
+ * Test to illustrate that the name of the everyone principal is constant.
+ * Complete the test case by typing the expected name.
+ *
+ * - {@link #testAccessByName()}
+ * Even though there exists a dedicated method to retrieve the everyone principal
+ * you can equally access it by name.
+ * Use the principal management API to retrieve the everyone principal by name.
+ * Discuss the drawback of this approach in an environment where you don't have access to the Oak constants.
+ *
+ * - {@link #testEveryoneIsMemberofEveryone()}
+ * Test case illustrating the dynamic nature of the everyone principal.
+ * Walk through the test
+ * Try to extend the test such that the default principal management exposes additional user|group principals.
+ *
+ * - {@link #testEveryoneAsAuthorizableGroup()}
+ * Additional test illustrating that the dynamic nature of the everyone principal
+ * does not change if there exists a corresponding authorizable group.
+ * > Create a new authorizable that corresponds to the everyone principal (Q: what parameters are constants?)
+ * > Verify that principal exposed by the authorizable corresponds to the everyone principal.
+ * > Assert that the dynamic nature of the principal has not changed.
+ * > Test if the dynamic nature also applies to the authorizable
+ *
+ *
+ * Additional Exercises:
+ * -----------------------------------------------------------------------------
+ *
+ * The following exercises can easily be performed in a Sling based repository
+ * installation (e.g. Granite|CQ) with the same setup as in this test class.
+ *
+ * - Test if there exists an everyone authorizable group.
+ * If this is the case try what happens if you remove that authorizable and discuss the consequences.
+ * Question: Can you explain why it exists?
+ *
+ * </pre>
+ *
+ * @see org.apache.jackrabbit.oak.security.user.L3_UserVsPrincipalTest
+ */
+public class L3_EveryoneTest extends AbstractJCRTest {
+
+ private PrincipalManager principalManager;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ principalManager = ((JackrabbitSession) superuser).getPrincipalManager();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testEveryoneExists() throws RepositoryException {
+ Principal everyone = principalManager.getEveryone();
+
+ assertNotNull(everyone);
+ assertTrue(everyone instanceof java.security.acl.Group);
+
+ Authorizable everyoneAuthorizable = ((JackrabbitSession) superuser).getUserManager().getAuthorizable(everyone);
+ assertNull(everyoneAuthorizable);
+ }
+
+ public void testEveryoneName() throws RepositoryException {
+ Principal everyone = principalManager.getEveryone();
+
+ String expectedName = null; // EXERCISE type the expected authorizable name using constants defined by oak.
+ assertEquals(expectedName, everyone.getName());
+ }
+
+ public void testAccessByName() throws RepositoryException {
+ Principal everyone = principalManager.getEveryone();
+
+ assertTrue(principalManager.hasPrincipal(everyone.getName()));
+
+ Principal everyoneByName = null; // EXERCISE: retrieve the everyone principal by name
+ assertEquals(everyone, everyoneByName);
+ }
+
+ public void testEveryoneIsMemberofEveryone() throws RepositoryException {
+ java.security.acl.Group everyone = (java.security.acl.Group) principalManager.getEveryone();
+ PrincipalIterator it = principalManager.getPrincipals(PrincipalManager.SEARCH_TYPE_ALL);
+
+ // EXERCISE: discuss the dynamic nature of the everyone group principal
+ while (it.hasNext()) {
+ Principal principal = it.nextPrincipal();
+ if (everyone.equals(principal)) {
+ assertFalse(everyone.isMember(principal));
+ } else {
+ assertTrue(everyone.isMember(principal));
+ }
+ }
+ }
+
+ public void testEveryoneAsAuthorizableGroup() throws RepositoryException {
+ // EXERCISE: create an authorizable that corresponds to the everyone principal.
+ org.apache.jackrabbit.api.security.user.Group everyoneAuthorizable = null;
+ superuser.save();
+
+ try {
+ java.security.acl.Group everyone = (java.security.acl.Group) principalManager.getEveryone();
+
+ assertEquals(everyone, everyoneAuthorizable.getPrincipal());
+
+ // EXERCISE: verify that the everyone principal is still a dynamic group
+ // EXERCISE: test if the dyanmic nature also applies to the authorizable
+ } finally {
+ if (everyoneAuthorizable != null) {
+ everyoneAuthorizable.remove();
+ superuser.save();
+ }
+ }
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L3_EveryoneTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L4_PrincipalProviderTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L4_PrincipalProviderTest.java?rev=1686235&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L4_PrincipalProviderTest.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L4_PrincipalProviderTest.java Thu Jun 18 14:30:16 2015
@@ -0,0 +1,117 @@
+/*
+ * 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.principal;
+
+import java.security.Principal;
+
+import org.apache.jackrabbit.api.security.principal.PrincipalIterator;
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider;
+import org.apache.jackrabbit.test.NotExecutableException;
+import org.junit.Test;
+
+/**
+ * <pre>
+ * Module: Principal Management
+ * =============================================================================
+ *
+ * Title: Principal Provider
+ * -----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Get familiar with the {@link org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider} interface.
+ *
+ * Exercises:
+ *
+ * - {@link #testCorrespondance()}
+ * List the corresponding calls between {@link PrincipalManager} and {@link PrincipalProvider}.
+ * List also those methods that have no correspondance in either interface.
+ * Try to identify the reason for having a JCR-level manager and an Oak-level provider interface.
+ *
+ *
+ * Additional Exercises
+ * -----------------------------------------------------------------------------
+ *
+ * - Take a closer look at the {@link org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration}
+ * and the available implementations.
+ *
+ * Question: Can you identify how they are used and how principal management can
+ * be extended both in an OSGi-based and regular java setup?
+ *
+ *
+ * Advanced Exercises:
+ * -----------------------------------------------------------------------------
+ *
+ * - Complete the {@link org.apache.jackrabbit.oak.security.principal.CustomPrincipalProvider}
+ * stub and deploy the exercise bundle in a Sling base repository installation
+ * (e.g. Cq|Granite).
+ * > Try to identify the tools that allow you to explore your custom principals
+ * > Play with the dynamic group membership as you define it in the principal provider and verify that the subjects calculated upon login are correct
+ * > Play with the authorization part of the principal management granting/revoking access for one of your custom principals
+ * </pre>
+ *
+ * @see org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider
+ * @see org.apache.jackrabbit.oak.security.principal.CustomPrincipalProvider
+ * @see org.apache.jackrabbit.oak.security.principal.CustomPrincipalConfiguration
+ */
+public class L4_PrincipalProviderTest extends AbstractSecurityTest {
+
+ private PrincipalProvider principalProvider;
+ private PrincipalManager principalManager;
+
+ private String testPrincipalName;
+
+ @Override
+ public void before() throws Exception {
+ super.before();
+
+ principalProvider = getConfig(PrincipalConfiguration.class).getPrincipalProvider(root, NamePathMapper.DEFAULT);
+ principalManager = getConfig(PrincipalConfiguration.class).getPrincipalManager(root, NamePathMapper.DEFAULT);
+
+ // NOTE: this method call doesn't make to much sense outside of a
+ // simple test with a very limited number of principals (!!)
+ PrincipalIterator principalIterator = principalManager.getPrincipals(PrincipalManager.SEARCH_TYPE_NOT_GROUP);
+ if (principalIterator.hasNext()) {
+ testPrincipalName = principalIterator.nextPrincipal().getName();
+ }
+
+ if (testPrincipalName == null) {
+ throw new NotExecutableException();
+ }
+ }
+
+ @Override
+ public void after() throws Exception {
+ super.after();
+ }
+
+ @Test
+ public void testCorrespondance() {
+ boolean exists = principalManager.hasPrincipal(testPrincipalName);
+ Principal principal = principalManager.getPrincipal(testPrincipalName);
+ PrincipalIterator principalIterator = principalManager.findPrincipals(testPrincipalName, PrincipalManager.SEARCH_TYPE_ALL);
+ PrincipalIterator groups = principalManager.getGroupMembership(principal);
+ PrincipalIterator all = principalManager.getPrincipals(PrincipalManager.SEARCH_TYPE_ALL);
+
+ // EXERCISE: write the corresponding calls for the principal provider and verify the expected result
+ // EXERCISE: which methods have nor corresponding call in the other interface?
+ }
+
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L4_PrincipalProviderTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L1_IntroductionTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L1_IntroductionTest.java?rev=1686235&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L1_IntroductionTest.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L1_IntroductionTest.java Thu Jun 18 14:30:16 2015
@@ -0,0 +1,53 @@
+/*
+ * 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.privilege;
+
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+
+/**
+ * <pre>
+ * Module: Privilege Management
+ * =============================================================================
+ *
+ * Title: Introduction
+ * -----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Become familiar with the Privilege Management API defined in
+ * JCR Access Control Management and by the extensions present in Jackrabbit API.
+ * Having completed this section should also be familiar with the internals of
+ * privilege management in Oak.
+ *
+ *
+ * Exercises:
+ *
+ * - TODO
+ *
+ *
+ * Related Exercises:
+ * -----------------------------------------------------------------------------
+ *
+ * - {@link L2_PrivilegeManagementTest}
+ * - {@link L7_PrivilegeDiscoveryTest}
+ *
+ * </pre>
+ *
+ */
+public class L1_IntroductionTest extends AbstractSecurityTest {
+
+
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L1_IntroductionTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L2_PrivilegeManagementTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L2_PrivilegeManagementTest.java?rev=1686235&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L2_PrivilegeManagementTest.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L2_PrivilegeManagementTest.java Thu Jun 18 14:30:16 2015
@@ -0,0 +1,102 @@
+/*
+ * 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.privilege;
+
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.JackrabbitWorkspace;
+import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.test.NotExecutableException;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.Privilege;
+
+/**
+ * <pre>
+ * Module: Privilege Management
+ * =============================================================================
+ *
+ * Title: Privilege Management (Basics)
+ * -----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Learn about the retrieving privileges in {@link javax.jcr.security.AccessControlManager)
+ * and the API defined by the {@link org.apache.jackrabbit.api.security.authorization.PrivilegeManager}
+ * API extension.
+ *
+ * Exercises:
+ *
+ * - {@link #testGetPrivilege()}
+ * Use this exercise to become familiar with the different ways to retrieve
+ * a privilege.
+ *
+ * - {@link #testGetSupportedAndRegisteredPrivileges()}
+ * Learn about the difference between supported and registered privileges.
+ * Based on the API contract compare the results of the 2 methods in the current
+ * implementation and discuss different ways of implementation.
+ *
+ * Question: How could you compare the 'supported' with the 'registered' privileges?
+ * Question: What can you say about the difference?
+ * Question: What can you say about the default implementation of {@link AccessControlManager#getSupportedPrivileges(String)}
+ *
+ *
+ * Related Exercises:
+ * -----------------------------------------------------------------------------
+ *
+ * - {@link L3_BuiltInPrivilegesTest}
+ * - {@link L4_CustomPrivilegeTest}
+ *
+ * </pre>
+ *
+ * @see javax.jcr.security.AccessControlManager
+ * @see org.apache.jackrabbit.api.security.authorization.PrivilegeManager
+ */
+public class L2_PrivilegeManagementTest extends AbstractJCRTest {
+
+ private AccessControlManager accessControlManager;
+ private PrivilegeManager privilegeManager;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ accessControlManager = superuser.getAccessControlManager();
+
+ if (!(superuser instanceof JackrabbitSession)) {
+ throw new NotExecutableException("not a JackrabbitSession");
+ }
+ privilegeManager = ((JackrabbitWorkspace) superuser.getWorkspace()).getPrivilegeManager();
+ }
+
+ public void testGetPrivilege() throws RepositoryException {
+ String privilegeName = Privilege.JCR_READ;
+
+ Privilege readPriv = null; // EXERCISE: retrieve privilege from 'accessControlManager'
+ Privilege readPriv2 = null; // EXERCISE: retrive the privilege from 'privilegeManager'
+
+ assertTrue(readPriv.equals(readPriv2));
+ }
+
+ public void testGetSupportedAndRegisteredPrivileges() throws RepositoryException {
+ Privilege[] supportedPrivilges = accessControlManager.getSupportedPrivileges(testRoot);
+ Privilege[] registered = privilegeManager.getRegisteredPrivileges();
+
+ // EXERCISE: compare the supported and the registered privileges
+ // EXERCISE: read the API contract for the 2 methods
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L2_PrivilegeManagementTest.java
------------------------------------------------------------------------------
svn:eol-style = native