/*
* 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.core.security.authorization;
import org.apache.jackrabbit.api.JackrabbitWorkspace;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlPolicy;
import org.apache.jackrabbit.core.SessionImpl;
import org.apache.jackrabbit.core.security.AccessManager;
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.commons.name.NameConstants;
import org.apache.jackrabbit.test.NotExecutableException;
import javax.jcr.AccessDeniedException;
import javax.jcr.RepositoryException;
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.Workspace;
import javax.jcr.nodetype.NodeTypeManager;
import javax.jcr.nodetype.NodeTypeTemplate;
import javax.jcr.security.AccessControlEntry;
import javax.jcr.security.AccessControlList;
import javax.jcr.security.AccessControlManager;
import javax.jcr.security.AccessControlPolicy;
import javax.jcr.security.AccessControlPolicyIterator;
import javax.jcr.security.Privilege;
import java.security.Principal;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* <code>AbstractRepositoryOperationTest</code>...
*/
public abstract class AbstractRepositoryOperationTest extends AbstractEvaluationTest {
@Override
protected void setUp() throws Exception {
super.setUp();
}
@Override
protected void tearDown() throws Exception {
try {
for (AccessControlPolicy policy : acMgr.getPolicies(null)) {
acMgr.removePolicy(null, policy);
}
superuser.save();
} finally {
super.tearDown();
}
}
private Workspace getTestWorkspace() throws RepositoryException {
return getTestSession().getWorkspace();
}
private void assertDefaultPrivileges(Name privName) throws Exception {
Privilege[] privs = privilegesFromName(privName.toString());
// admin must be allowed
assertTrue(superuser.getAccessControlManager().hasPrivileges(null, privs));
// test user must not be allowed
assertFalse(getTestACManager().hasPrivileges(null, privs));
}
private void assertPrivilege(Name privName, boolean isAllow) throws Exception {
Privilege[] privs = privilegesFromName(privName.toString());
assertEquals(isAllow, getTestACManager().hasPrivileges(null, privs));
}
private void assertPermission(int permission, boolean isAllow) throws Exception {
AccessManager acMgr = ((SessionImpl) getTestSession()).getAccessManager();
try {
acMgr.checkRepositoryPermission(permission);
if (!isAllow) {
fail();
}
} catch (AccessDeniedException e) {
if (isAllow) {
fail();
}
}
}
private String getNewWorkspaceName(Workspace wsp) throws RepositoryException {
List<String> awn = Arrays.asList(wsp.getAccessibleWorkspaceNames());
String workspaceName = "new";
int i = 0;
while (awn.contains(workspaceName)) {
workspaceName = "new_" + i++;
}
return workspaceName;
}
private String getNewNamespacePrefix(Workspace wsp) throws RepositoryException {
String prefix = "prefix";
List<String> pfcs = Arrays.asList(wsp.getNamespaceRegistry().getPrefixes());
int i = 0;
while (pfcs.contains(prefix)) {
prefix = "prefix" + i++;
}
return prefix;
}
private String getNewNamespaceURI(Workspace wsp) throws RepositoryException {
String uri = "http://jackrabbit.apache.org/uri";
List<String> uris = Arrays.asList(wsp.getNamespaceRegistry().getURIs());
int i = 0;
while (uris.contains(uri)) {
uri = "http://jackrabbit.apache.org/uri_" + i++;
}
return uri;
}
private String getNewPrivilegeName(Workspace wsp) throws RepositoryException, NotExecutableException {
String privName = null;
AccessControlManager acMgr = wsp.getSession().getAccessControlManager();
for (int i = 0; i < 100; i++) {
try {
Privilege p = acMgr.privilegeFromName(privName);
privName = "privilege-" + i;
} catch (Exception e) {
break;
}
}
if (privName == null) {
throw new NotExecutableException("failed to define new privilege name.");
}
return privName;
}
public void testWorkspaceCreation() throws Exception {
assertDefaultPrivileges(NameConstants.JCR_WORKSPACE_MANAGEMENT);
String wspName = getNewWorkspaceName(superuser.getWorkspace());
try {
getTestWorkspace().createWorkspace(wspName);
fail("Workspace creation should be denied.");
} catch (AccessDeniedException e) {
// success
}
wspName = getNewWorkspaceName(superuser.getWorkspace());
try {
Workspace wsp = getTestWorkspace();
wsp.createWorkspace(wspName, wsp.getName());
fail("Workspace creation should be denied.");
} catch (AccessDeniedException e) {
// success
}
}
public void testWorkspaceCreationWithPrivilege() throws Exception {
assertDefaultPrivileges(NameConstants.JCR_WORKSPACE_MANAGEMENT);
assertPermission(Permission.WORKSPACE_MNGMT, false);
modifyPrivileges(null, NameConstants.JCR_WORKSPACE_MANAGEMENT.toString(), true);
// assert that permission have changed:
assertPrivilege(NameConstants.JCR_WORKSPACE_MANAGEMENT, true);
assertPermission(Permission.WORKSPACE_MNGMT, true);
try {
Workspace testWsp = getTestWorkspace();
testWsp.createWorkspace(getNewWorkspaceName(superuser.getWorkspace()));
} finally {
modifyPrivileges(null, NameConstants.JCR_WORKSPACE_MANAGEMENT.toString(), false);
}
assertPrivilege(NameConstants.JCR_WORKSPACE_MANAGEMENT, false);
assertPermission(Permission.WORKSPACE_MNGMT, false);
}
public void testWorkspaceDeletion() throws Exception {
assertDefaultPrivileges(NameConstants.JCR_WORKSPACE_MANAGEMENT);
assertPermission(Permission.WORKSPACE_MNGMT, false);
Workspace wsp = superuser.getWorkspace();
String workspaceName = getNewWorkspaceName(wsp);
wsp.createWorkspace(workspaceName);
try {
Workspace testWsp = getTestWorkspace();
List<String> wspNames = Arrays.asList(testWsp.getAccessibleWorkspaceNames());
if (wspNames.contains(workspaceName)) {
testWsp.deleteWorkspace(workspaceName);
fail("Workspace deletion should be denied.");
}
} catch (AccessDeniedException e) {
// success
} finally {
// clean up (not supported by jackrabbit-core)
try {
superuser.getWorkspace().deleteWorkspace(workspaceName);
} catch (Exception e) {
// workspace removal is not supported by jackrabbit-core.
}
}
}
public void testRegisterNodeType() throws Exception {
assertDefaultPrivileges(NameConstants.JCR_NODE_TYPE_DEFINITION_MANAGEMENT);
assertPermission(Permission.NODE_TYPE_DEF_MNGMT, false);
Workspace testWsp = getTestWorkspace();
NodeTypeManager ntm = testWsp.getNodeTypeManager();
NodeTypeTemplate ntd = ntm.createNodeTypeTemplate();
ntd.setName("testNodeType");
ntd.setMixin(true);
try {
ntm.registerNodeType(ntd, true);
fail("Node type registration should be denied.");
} catch (AccessDeniedException e) {
// success
}
try {
ntm.registerNodeType(ntd, false);
fail("Node type registration should be denied.");
} catch (AccessDeniedException e) {
// success
}
NodeTypeTemplate[] ntds = new NodeTypeTemplate[2];
ntds[0] = ntd;
ntds[1] = ntm.createNodeTypeTemplate();
ntds[1].setName("anotherNodeType");
ntds[1].setDeclaredSuperTypeNames(new String[] {"nt:file"});
try {
ntm.registerNodeTypes(ntds, true);
fail("Node type registration should be denied.");
} catch (AccessDeniedException e) {
// success
}
try {
ntm.registerNodeTypes(ntds, false);
fail("Node type registration should be denied.");
} catch (AccessDeniedException e) {
// success
}
}
public void testRegisterNodeTypeWithPrivilege() throws Exception {
assertDefaultPrivileges(NameConstants.JCR_NODE_TYPE_DEFINITION_MANAGEMENT);
assertPermission(Permission.NODE_TYPE_DEF_MNGMT, false);
modifyPrivileges(null, NameConstants.JCR_NODE_TYPE_DEFINITION_MANAGEMENT.toString(), true);
assertPrivilege(NameConstants.JCR_NODE_TYPE_DEFINITION_MANAGEMENT, true);
assertPermission(Permission.NODE_TYPE_DEF_MNGMT, true);
try {
Workspace testWsp = getTestWorkspace();
NodeTypeManager ntm = testWsp.getNodeTypeManager();
NodeTypeTemplate ntd = ntm.createNodeTypeTemplate();
ntd.setName("testNodeType");
ntd.setMixin(true);
ntm.registerNodeType(ntd, true);
NodeTypeTemplate[] ntds = new NodeTypeTemplate[2];
ntds[0] = ntd;
ntds[1] = ntm.createNodeTypeTemplate();
ntds[1].setName("anotherNodeType");
ntds[1].setDeclaredSuperTypeNames(new String[] {"nt:file"});
ntm.registerNodeTypes(ntds, true);
} finally {
modifyPrivileges(null, NameConstants.JCR_NODE_TYPE_DEFINITION_MANAGEMENT.toString(), false);
}
assertPrivilege(NameConstants.JCR_NODE_TYPE_DEFINITION_MANAGEMENT, false);
assertPermission(Permission.NODE_TYPE_DEF_MNGMT, false);
}
public void testUnRegisterNodeType() throws Exception {
assertDefaultPrivileges(NameConstants.JCR_NODE_TYPE_DEFINITION_MANAGEMENT);
assertPermission(Permission.NODE_TYPE_DEF_MNGMT, false);
NodeTypeManager ntm = superuser.getWorkspace().getNodeTypeManager();
NodeTypeTemplate ntd = ntm.createNodeTypeTemplate();
ntd.setName("testNodeType");
ntd.setMixin(true);
ntm.registerNodeType(ntd, true);
Workspace testWsp = getTestWorkspace();
try {
try {
NodeTypeManager testNtm = testWsp.getNodeTypeManager();
testNtm.unregisterNodeType(ntd.getName());
fail("Namespace unregistration should be denied.");
} catch (AccessDeniedException e) {
// success
}
try {
NodeTypeManager testNtm = testWsp.getNodeTypeManager();
testNtm.unregisterNodeTypes(new String[] {ntd.getName()});
fail("Namespace unregistration should be denied.");
} catch (AccessDeniedException e) {
// success
}
} finally {
// clean up (not supported by jackrabbit-core)
try {
ntm.unregisterNodeType(ntd.getName());
} catch (Exception e) {
// ns unregistration is not supported by jackrabbit-core.
}
}
}
public void testRegisterNamespace() throws Exception {
assertDefaultPrivileges(NameConstants.JCR_NAMESPACE_MANAGEMENT);
assertPermission(Permission.NODE_TYPE_DEF_MNGMT, false);
try {
Workspace testWsp = getTestWorkspace();
testWsp.getNamespaceRegistry().registerNamespace(getNewNamespacePrefix(testWsp), getNewNamespaceURI(testWsp));
fail("Namespace registration should be denied.");
} catch (AccessDeniedException e) {
// success
}
}
public void testRegisterNamespaceWithPrivilege() throws Exception {
assertDefaultPrivileges(NameConstants.JCR_NAMESPACE_MANAGEMENT);
assertPermission(Permission.NAMESPACE_MNGMT, false);
modifyPrivileges(null, NameConstants.JCR_NAMESPACE_MANAGEMENT.toString(), true);
assertPrivilege(NameConstants.JCR_NAMESPACE_MANAGEMENT, true);
assertPermission(Permission.NAMESPACE_MNGMT, true);
try {
Workspace testWsp = getTestWorkspace();
testWsp.getNamespaceRegistry().registerNamespace(getNewNamespacePrefix(testWsp), getNewNamespaceURI(testWsp));
} finally {
modifyPrivileges(null, NameConstants.JCR_NAMESPACE_MANAGEMENT.toString(), false);
}
assertPrivilege(NameConstants.JCR_NAMESPACE_MANAGEMENT, false);
assertPermission(Permission.NAMESPACE_MNGMT, false);
}
public void testUnregisterNamespace() throws Exception {
assertDefaultPrivileges(NameConstants.JCR_NAMESPACE_MANAGEMENT);
assertPermission(Permission.NAMESPACE_MNGMT, false);
Workspace wsp = superuser.getWorkspace();
String pfx = getNewNamespacePrefix(wsp);
wsp.getNamespaceRegistry().registerNamespace(pfx, getNewNamespaceURI(wsp));
try {
Workspace testWsp = getTestWorkspace();
testWsp.getNamespaceRegistry().unregisterNamespace(pfx);
fail("Namespace unregistration should be denied.");
} catch (AccessDeniedException e) {
// success
} finally {
// clean up (not supported by jackrabbit-core)
try {
superuser.getWorkspace().getNamespaceRegistry().unregisterNamespace(pfx);
} catch (Exception e) {
// ns unregistration is not supported by jackrabbit-core.
}
}
}
public void testRegisterPrivilege() throws Exception {
assertDefaultPrivileges(PrivilegeRegistry.REP_PRIVILEGE_MANAGEMENT_NAME);
assertPermission(Permission.PRIVILEGE_MNGMT, false);
try {
Workspace testWsp = getTestWorkspace();
((JackrabbitWorkspace) testWsp).getPrivilegeManager().registerPrivilege(getNewPrivilegeName(testWsp), false, new String[0]);
fail("Privilege registration should be denied.");
} catch (AccessDeniedException e) {
// success
}
}
public void testRegisterPrivilegeWithPrivilege() throws Exception {
assertDefaultPrivileges(PrivilegeRegistry.REP_PRIVILEGE_MANAGEMENT_NAME);
assertPermission(Permission.PRIVILEGE_MNGMT, false);
modifyPrivileges(null, PrivilegeRegistry.REP_PRIVILEGE_MANAGEMENT_NAME.toString(), true);
assertPrivilege(PrivilegeRegistry.REP_PRIVILEGE_MANAGEMENT_NAME, true);
assertPermission(Permission.PRIVILEGE_MNGMT, true);
try {
Workspace testWsp = getTestWorkspace();
((JackrabbitWorkspace) testWsp).getPrivilegeManager().registerPrivilege(getNewPrivilegeName(testWsp), false, new String[0]); } finally {
modifyPrivileges(null, PrivilegeRegistry.REP_PRIVILEGE_MANAGEMENT_NAME.toString(), false);
}
assertPrivilege(PrivilegeRegistry.REP_PRIVILEGE_MANAGEMENT_NAME, false);
assertPermission(Permission.PRIVILEGE_MNGMT, false);
}
public void testRepoPolicyAPI() throws Exception {
try {
// initial state: no repo level policy
AccessControlPolicy[] policies = acMgr.getPolicies(null);
assertNotNull(policies);
assertEquals(0, policies.length);
AccessControlPolicy[] effective = acMgr.getEffectivePolicies(null);
assertNotNull(effective);
assertEquals(0, effective.length);
AccessControlPolicyIterator it = acMgr.getApplicablePolicies(null);
assertNotNull(it);
assertTrue(it.hasNext());
AccessControlPolicy acp = it.nextAccessControlPolicy();
assertNotNull(acp);
assertTrue(acp instanceof JackrabbitAccessControlPolicy);
// modify the repo level policy
modifyPrivileges(null, NameConstants.JCR_NODE_TYPE_DEFINITION_MANAGEMENT.toString(), false);
modifyPrivileges(null, NameConstants.JCR_NAMESPACE_MANAGEMENT.toString(), true);
AccessControlPolicy[] plcs = acMgr.getPolicies(null);
assertNotNull(plcs);
assertEquals(1, plcs.length);
assertTrue(plcs[0] instanceof AccessControlList);
AccessControlList acl = (AccessControlList) plcs[0];
AccessControlEntry[] aces = acl.getAccessControlEntries();
assertNotNull(aces);
assertEquals(2, aces.length);
assertPrivilege(NameConstants.JCR_NAMESPACE_MANAGEMENT, true);
assertPermission(Permission.NAMESPACE_MNGMT, true);
assertPrivilege(NameConstants.JCR_NODE_TYPE_DEFINITION_MANAGEMENT, false);
assertPermission(Permission.NODE_TYPE_DEF_MNGMT, false);
effective = acMgr.getEffectivePolicies(null);
assertNotNull(effective);
assertEquals(1, effective.length);
assertTrue(effective[0] instanceof AccessControlList);
acl = (AccessControlList) effective[0];
aces = acl.getAccessControlEntries();
assertNotNull(aces);
assertEquals(2, aces.length);
// change the policy: removing the second entry in the access control list
acl = (AccessControlList) acMgr.getPolicies(null)[0];
AccessControlEntry toRemove = acl.getAccessControlEntries()[1];
acl.removeAccessControlEntry(toRemove);
acMgr.setPolicy(null, acl);
superuser.save();
acl = (AccessControlList) acMgr.getPolicies(null)[0];
aces = acl.getAccessControlEntries();
assertNotNull(aces);
assertEquals(1, aces.length);
assertPrivilege(NameConstants.JCR_NAMESPACE_MANAGEMENT, false);
assertPermission(Permission.NAMESPACE_MNGMT, false);
assertPrivilege(NameConstants.JCR_NODE_TYPE_DEFINITION_MANAGEMENT, false);
assertPermission(Permission.NODE_TYPE_DEF_MNGMT, false);
} catch (UnsupportedRepositoryOperationException e) {
throw new NotExecutableException();
} finally {
// remove it again
for (AccessControlPolicy plc : acMgr.getPolicies(null)) {
acMgr.removePolicy(null, plc);
}
superuser.save();
// back to initial state: no repo level policy
AccessControlPolicy[] policies = acMgr.getPolicies(null);
assertNotNull(policies);
assertEquals(0, policies.length);
AccessControlPolicy[] effective = acMgr.getEffectivePolicies(null);
assertNotNull(effective);
assertEquals(0, effective.length);
AccessControlPolicyIterator it = acMgr.getApplicablePolicies(null);
assertNotNull(it);
assertTrue(it.hasNext());
AccessControlPolicy acp = it.nextAccessControlPolicy();
assertNotNull(acp);
assertTrue(acp instanceof JackrabbitAccessControlPolicy);
}
}
public void testGetEffectivePoliciesByPrincipal() throws Exception {
if (!(acMgr instanceof JackrabbitAccessControlManager)) {
throw new NotExecutableException();
}
JackrabbitAccessControlManager jAcMgr = (JackrabbitAccessControlManager) acMgr;
Set<Principal> principalSet = Collections.singleton(testUser.getPrincipal());
try {
// initial state: no repo level policy
AccessControlPolicy[] policies = acMgr.getPolicies(null);
assertNotNull(policies);
assertEquals(0, policies.length);
AccessControlPolicy[] effective = jAcMgr.getEffectivePolicies(principalSet);
assertNotNull(effective);
assertEquals(0, effective.length);
AccessControlPolicyIterator it = acMgr.getApplicablePolicies(null);
assertTrue(it.hasNext());
// modify the repo level policy
modifyPrivileges(null, NameConstants.JCR_NODE_TYPE_DEFINITION_MANAGEMENT.toString(), false);
modifyPrivileges(null, NameConstants.JCR_NAMESPACE_MANAGEMENT.toString(), true);
// verify that the effective policies for the given principal set
// is properly calculated.
AccessControlPolicy[] eff = jAcMgr.getEffectivePolicies(principalSet);
assertNotNull(eff);
assertEquals(1, eff.length);
assertTrue(eff[0] instanceof AccessControlList);
AccessControlList acl = (AccessControlList) eff[0];
AccessControlEntry[] aces = acl.getAccessControlEntries();
assertNotNull(aces);
assertEquals(2, aces.length);
for (AccessControlEntry ace : aces) {
assertEquals(testUser.getPrincipal(), ace.getPrincipal());
}
} catch (UnsupportedRepositoryOperationException e) {
throw new NotExecutableException();
} finally {
// remove it again
for (AccessControlPolicy plc : acMgr.getPolicies(null)) {
acMgr.removePolicy(null, plc);
}
superuser.save();
// back to initial state: no repo level policy
AccessControlPolicy[] policies = acMgr.getPolicies(null);
assertNotNull(policies);
assertEquals(0, policies.length);
}
}
}