blob: cdce414f0a85bed109f272d727c7b0b53633e086 [file] [log] [blame]
/*
* 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.sling.jcr.repoinit;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.sling.jcr.repoinit.impl.AclUtil;
import org.apache.sling.jcr.repoinit.impl.TestUtil;
import org.apache.sling.jcr.repoinit.impl.UserUtil;
import org.apache.sling.repoinit.parser.RepoInitParsingException;
import org.apache.sling.testing.mock.sling.ResourceResolverType;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.security.AccessControlList;
import javax.jcr.security.AccessControlPolicy;
import java.util.UUID;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;
public class RemoveTest {
@Rule
public final SlingContext context = new SlingContext(ResourceResolverType.JCR_OAK);
private TestUtil U;
private String path;
private String userHomePath;
private String groupId;
private String groupPrincipalName;
@Before
public void before() throws RepositoryException, RepoInitParsingException {
U = new TestUtil(context);
U.parseAndExecute("create service user " + U.username);
Node n = U.adminSession.getRootNode().addNode("tmp_" + U.id);
path = n.getPath();
UserManager uMgr = UserUtil.getUserManager(U.adminSession);
Group gr = uMgr.createGroup("group_"+UUID.randomUUID().toString());
groupId = gr.getID();
groupPrincipalName = gr.getPrincipal().getName();
U.adminSession.save();
String setup = "set ACL for " + U.username + "\n"
+ "deny jcr:read on "+path+"\n"
+ "deny jcr:all on :repository\n"
+ "allow jcr:read on home(" + U.username + ")\n"
+ "end\n"
+ "\n"
+ "set ACL for " + groupPrincipalName + "\n"
+ "allow jcr:read on "+path+" restriction(rep:glob,/*/foo/*)\n"
+ "allow jcr:namespaceManagement on :repository\n"
+ "allow jcr:read on home(" + U.username + ")\n"
+ "end";
U.parseAndExecute(setup);
userHomePath = uMgr.getAuthorizable(U.username).getPath();
assertPolicy(path, U.adminSession, 2);
assertPolicy(null, U.adminSession, 2);
assertPolicy(userHomePath, U.adminSession, 2);
}
@After
public void after() throws RepositoryException, RepoInitParsingException {
try {
U.adminSession.removeItem(path);
UserUtil.getUserManager(U.adminSession).getAuthorizable(groupId).remove();
U.adminSession.save();
} finally {
U.cleanupUser();
}
}
private static void assertPolicy(@Nullable String path, @NotNull Session session, int expectedSize) throws RepositoryException {
AccessControlPolicy[] policies = session.getAccessControlManager().getPolicies(path);
for (AccessControlPolicy policy : policies) {
if (policy instanceof AccessControlList) {
assertEquals(expectedSize, ((AccessControlList) policy).getAccessControlEntries().length);
return;
}
}
fail("No access control list found at " + path);
}
@Test
public void testRemoveAllByPath() throws RepoInitParsingException, RepositoryException {
String setup = "set ACL for " + U.username + "\n"
+ "remove * on "+path+",:repository, home("+U.username+")\n"
+ "end";
U.parseAndExecute(setup);
assertPolicy(path, U.adminSession, 1);
assertPolicy(null, U.adminSession, 1);
assertPolicy(userHomePath, U.adminSession, 1);
}
@Test
public void testRemoveAllByPrincipal() throws RepoInitParsingException, RepositoryException {
String setup = "set ACL on "+path+", home("+U.username+"), :repository\n"
+ "remove * for "+U.username+"\n" +
"end";
U.parseAndExecute(setup);
assertPolicy(path, U.adminSession, 1);
assertPolicy(null, U.adminSession, 1);
assertPolicy(userHomePath, U.adminSession, 1);
}
@Test
public void testRemoveAllByMultiplePrincipals() throws RepoInitParsingException, RepositoryException {
String setup = "set ACL on "+path+"\n"
+ "remove * for "+U.username+", "+groupPrincipalName+"\n" +
"end";
U.parseAndExecute(setup);
assertPolicy(path, U.adminSession, 0);
assertPolicy(null, U.adminSession, 2);
assertPolicy(userHomePath, U.adminSession, 2);
}
@Test(expected = RuntimeException.class)
public void testRemoveActionByPath() throws RepoInitParsingException, RepositoryException {
String setup = "set ACL for " + U.username + "\n"
+ "remove jcr:read on "+path+"\n"
+ "end";
U.parseAndExecute(setup);
}
@Test(expected = RuntimeException.class)
public void testRemoveByPath2() throws RepoInitParsingException, RepositoryException {
String setup = "set ACL for " + groupPrincipalName + "\n"
+ "remove jcr:versionManagement on :repository\n"
+ "end";
U.parseAndExecute(setup);
}
@Test(expected = RuntimeException.class)
public void testRemoveActionByPrincipal() throws RepoInitParsingException, RepositoryException {
String setup = "set ACL on home("+U.username+")\n"
+ "remove jcr:all for "+U.username+"\n" +
"end";
U.parseAndExecute(setup);
}
@Test
public void testRemoveByNonExistingPath() throws Exception {
String path = "/non/existing";
String setup = "remove ACE for " + U.username + "\n"
+ "deny jcr:read on "+path+"\n"
+ "end";
U.parseAndExecute(setup);
assertFalse(U.adminSession.nodeExists(path));
setup = "remove ACE on "+path+"\n"
+ "deny jcr:read for " + U.username + "\n"
+ "end";
U.parseAndExecute(setup);
assertFalse(U.adminSession.nodeExists(path));
setup = "set ACL on "+path+"\n" +
"remove * for "+U.username+"\n" +
"end";
U.parseAndExecute(setup);
assertFalse(U.adminSession.nodeExists(path));
}
@Test
public void testRemoveByPath() throws RepoInitParsingException, RepositoryException {
// non-matching ACE (path-mismatch) -> not removed (and no exception)
String setup = "remove ACE for " + U.username + "\n"
+ "deny jcr:read on /\n"
+ "end";
U.parseAndExecute(setup);
assertPolicy(path, U.adminSession, 2);
// non-matching ACE (privilege-mismatch) -> not removed (and no exception)
setup = "remove ACE for " + U.username + "\n"
+ "deny jcr:read,jcr:write on "+path+"\n"
+ "end";
U.parseAndExecute(setup);
assertPolicy(path, U.adminSession, 2);
// matching ACE -> removed
setup = "remove ACE for " + U.username + "\n"
+ "deny jcr:read on "+path+"\n"
+ "end";
U.parseAndExecute(setup);
assertPolicy(path, U.adminSession, 1);
}
@Test
public void testRemoveByRepository() throws RepoInitParsingException, RepositoryException {
// non-matching ACE (allow mismatch) -> not removed (and no exception)
String setup = "remove ACE for " + groupPrincipalName + "\n"
+ "deny jcr:namespaceManagement on :repository\n"
+ "end";
U.parseAndExecute(setup);
assertPolicy(null, U.adminSession, 2);
// matching ACE -> removed
setup = "remove ACE for " + groupPrincipalName + "\n"
+ "allow jcr:namespaceManagement on :repository\n"
+ "end";
U.parseAndExecute(setup);
assertPolicy(null, U.adminSession, 1);
}
@Test
public void testRemoveByPrincipalRepositoryPath() throws RepoInitParsingException, RepositoryException {
// non-matching ACE (privilege mismatch) -> not removed (and no exception)
String setup = "remove ACE for " + groupPrincipalName + "\n"
+ "allow jcr:versionManagement on :repository\n"
+ "end";
U.parseAndExecute(setup);
assertPolicy(null, U.adminSession, 2);
// matching ACE -> removed
setup = "remove ACE for " + groupPrincipalName + "\n"
+ "allow jcr:namespaceManagement on :repository\n"
+ "end";
U.parseAndExecute(setup);
assertPolicy(null, U.adminSession, 1);
}
@Test
public void testRemoveByHomePath() throws RepoInitParsingException, RepositoryException {
// no-matching ACE (restriction mismatch) -> not removed
String setup = "remove ACE on home("+U.username+")\n"
+ "allow jcr:read for "+U.username+" restriction(rep:itemNames, prop1)\n" +
"end";
U.parseAndExecute(setup);
assertPolicy(userHomePath, U.adminSession, 2);
setup = "remove ACE on home("+U.username+")\n"
+ "allow jcr:read for "+U.username+"\n" +
"end";
U.parseAndExecute(setup);
assertPolicy(userHomePath, U.adminSession, 1);
}
@Test
public void testRemoveEntryWithRestriction() throws Exception {
String setup = "remove ACE for " + groupPrincipalName + "\n"
+ "allow jcr:read on "+path+" restriction(rep:glob, /*/foo/*)\n"
+ "end";
U.parseAndExecute(setup);
assertPolicy(path, U.adminSession, 1);
}
}