You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by an...@apache.org on 2021/05/05 12:56:50 UTC
[sling-org-apache-sling-jcr-repoinit] 01/01: SLING-10299 : Allow
for removal of access control policies (not just individual entries)
This is an automated email from the ASF dual-hosted git repository.
angela pushed a commit to branch SLING-10299
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-repoinit.git
commit c1ccb1a2c4c23771c6b2099d38ce6fc6d85287c1
Author: angela <an...@adobe.com>
AuthorDate: Wed May 5 14:55:36 2021 +0200
SLING-10299 : Allow for removal of access control policies (not just individual entries)
---
pom.xml | 2 +-
.../apache/sling/jcr/repoinit/impl/AclUtil.java | 82 +++++++++-
.../apache/sling/jcr/repoinit/impl/AclVisitor.java | 37 +++++
.../sling/jcr/repoinit/impl/DoNothingVisitor.java | 15 ++
.../sling/jcr/repoinit/PrincipalBasedAclTest.java | 120 +++++++++++---
.../apache/sling/jcr/repoinit/RemoveAclTest.java | 174 +++++++++++++++++++++
6 files changed, 404 insertions(+), 26 deletions(-)
diff --git a/pom.xml b/pom.xml
index 6c5e80d..3733564 100644
--- a/pom.xml
+++ b/pom.xml
@@ -219,7 +219,7 @@
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.repoinit.parser</artifactId>
- <version>1.6.7-SNAPSHOT</version>
+ <version>1.6.9-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
diff --git a/src/main/java/org/apache/sling/jcr/repoinit/impl/AclUtil.java b/src/main/java/org/apache/sling/jcr/repoinit/impl/AclUtil.java
index cde2e34..7264163 100644
--- a/src/main/java/org/apache/sling/jcr/repoinit/impl/AclUtil.java
+++ b/src/main/java/org/apache/sling/jcr/repoinit/impl/AclUtil.java
@@ -40,9 +40,11 @@ import javax.jcr.security.Privilege;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlEntry;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlPolicy;
import org.apache.jackrabbit.api.security.authorization.PrincipalAccessControlList;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
import org.apache.jackrabbit.util.Text;
import org.apache.sling.repoinit.parser.operations.AclLine;
import org.apache.sling.repoinit.parser.operations.RestrictionClause;
@@ -166,6 +168,51 @@ public class AclUtil {
setAcl(session, principals, (String)null, privileges, isAllow, restrictionClauses);
}
+ /**
+ * Remove resource-based access control setup for the principal with the given name.
+ *
+ * @param session
+ * @param principalName
+ * @throws RepositoryException
+ */
+ public static void removeAcl(@NotNull Session session, @NotNull final String principalName) throws RepositoryException {
+ Principal principal = AccessControlUtils.getPrincipal(session, principalName);
+ if (principal == null) {
+ LOG.info("Principal {} does not exist.", principalName);
+ // using PrincipalImpl will prevent 'removePolicy' from failing with AccessControlException
+ // in case import-behavior is configured to be ABORT.
+ principal = new PrincipalImpl(principalName);
+ }
+
+ JackrabbitAccessControlManager acMgr = getJACM(session);
+ for (JackrabbitAccessControlPolicy policy : acMgr.getPolicies(principal)) {
+ // make sure not to remove the principal-based access control list but instead only drop
+ // resource-based access control content for the given principal
+ if (policy instanceof JackrabbitAccessControlList && !(policy instanceof PrincipalAccessControlList)) {
+ acMgr.removePolicy(policy.getPath(), policy);
+ }
+ }
+ }
+
+ /**
+ * Remove resource-based access control setup defined for the specified paths.
+ *
+ * @param session
+ * @param paths
+ * @throws RepositoryException
+ */
+ public static void removeAcl(@NotNull Session session, @NotNull List<String> paths) throws RepositoryException {
+ for (String jcrPath : getJcrPaths(session, paths)) {
+ LOG.info("Removing access control policy on {}", jcrPath);
+ JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(session, jcrPath);
+ if (acl == null) {
+ LOG.info("No ACL to remove at path {}", jcrPath);
+ } else {
+ session.getAccessControlManager().removePolicy(jcrPath, acl);
+ }
+ }
+ }
+
public static void removeEntries(@NotNull Session session, @NotNull List<String> principals, @NotNull List<String> paths) throws RepositoryException {
Set<String> principalNames = new HashSet<>(principals);
for (String jcrPath : getJcrPaths(session, paths)) {
@@ -202,7 +249,7 @@ public class AclUtil {
checkState(principal != null, "Principal not found: " + principalName);
}
- final PrincipalAccessControlList acl = getPrincipalAccessControlList(acMgr, principal);
+ final PrincipalAccessControlList acl = getPrincipalAccessControlList(acMgr, principal, true);
boolean modified = false;
for (AclLine line : lines) {
AclLine.Action action = line.getAction();
@@ -244,16 +291,41 @@ public class AclUtil {
}
}
- private static PrincipalAccessControlList getPrincipalAccessControlList(JackrabbitAccessControlManager acMgr, Principal principal) throws RepositoryException {
+ /**
+ * Remove principal-based access control setup for the principal with the given name.
+ *
+ * @param session
+ * @param principalName
+ * @throws RepositoryException
+ */
+ public static void removePrincipalAcl(@NotNull Session session, @NotNull String principalName) throws RepositoryException {
+ Principal principal = AccessControlUtils.getPrincipal(session, principalName);
+ if (principal == null) {
+ LOG.info("Cannot remove principal-based ACL. Principal {} does not exist.", principalName);
+ return;
+ }
+
+ JackrabbitAccessControlManager acMgr = getJACM(session);
+ PrincipalAccessControlList acl = getPrincipalAccessControlList(acMgr, principal, false);
+ if (acl == null) {
+ LOG.info("Cannot remove principal-based ACL for principal {}. No such policy exists.", principalName);
+ } else {
+ acMgr.removePolicy(acl.getPath(), acl);
+ }
+ }
+
+ @Nullable
+ private static PrincipalAccessControlList getPrincipalAccessControlList(@NotNull JackrabbitAccessControlManager acMgr,
+ @NotNull Principal principal, boolean includeApplicable) throws RepositoryException {
PrincipalAccessControlList acl = null;
- for (AccessControlPolicy policy : acMgr.getPolicies(principal)) {
+ for (JackrabbitAccessControlPolicy policy : acMgr.getPolicies(principal)) {
if (policy instanceof PrincipalAccessControlList) {
acl = (PrincipalAccessControlList) policy;
break;
}
}
- if (acl == null) {
- for (AccessControlPolicy policy : acMgr.getApplicablePolicies(principal)) {
+ if (acl == null && includeApplicable) {
+ for (JackrabbitAccessControlPolicy policy : acMgr.getApplicablePolicies(principal)) {
if (policy instanceof PrincipalAccessControlList) {
acl = (PrincipalAccessControlList) policy;
break;
diff --git a/src/main/java/org/apache/sling/jcr/repoinit/impl/AclVisitor.java b/src/main/java/org/apache/sling/jcr/repoinit/impl/AclVisitor.java
index 965bd80..a071a91 100644
--- a/src/main/java/org/apache/sling/jcr/repoinit/impl/AclVisitor.java
+++ b/src/main/java/org/apache/sling/jcr/repoinit/impl/AclVisitor.java
@@ -24,11 +24,15 @@ import java.util.Collections;
import java.util.List;
import javax.jcr.Node;
+import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.apache.sling.repoinit.parser.operations.AclLine;
import org.apache.sling.repoinit.parser.operations.CreatePath;
import org.apache.sling.repoinit.parser.operations.PathSegmentDefinition;
+import org.apache.sling.repoinit.parser.operations.RemoveAclPaths;
+import org.apache.sling.repoinit.parser.operations.RemoveAclPrincipalBased;
+import org.apache.sling.repoinit.parser.operations.RemoveAclPrincipals;
import org.apache.sling.repoinit.parser.operations.RestrictionClause;
import org.apache.sling.repoinit.parser.operations.SetAclPaths;
import org.apache.sling.repoinit.parser.operations.SetAclPrincipalBased;
@@ -154,4 +158,37 @@ class AclVisitor extends DoNothingVisitor {
throw new RuntimeException("Session.save failed: "+ e, e);
}
}
+
+ @Override
+ public void visitRemoveAclPrincipals(RemoveAclPrincipals s) {
+ for (String principalName : s.getPrincipals()) {
+ try {
+ log.info("Removing access control policy for {}", principalName);
+ AclUtil.removeAcl(session, principalName);
+ } catch (RepositoryException e) {
+ throw new RuntimeException("Failed to remove ACL ("+e.getMessage()+")");
+ }
+ }
+ }
+
+ @Override
+ public void visitRemoveAclPaths(RemoveAclPaths s) {
+ try {
+ AclUtil.removeAcl(session, s.getPaths());
+ } catch (RepositoryException e) {
+ throw new RuntimeException("Failed to remove ACL ("+e.getMessage()+")");
+ }
+ }
+
+ @Override
+ public void visitRemoveAclPrincipalBased(RemoveAclPrincipalBased s) {
+ for (String principalName : s.getPrincipals()) {
+ try {
+ log.info("Removing principal-based access control policy for {}", principalName);
+ AclUtil.removePrincipalAcl(session, principalName);
+ } catch (RepositoryException e) {
+ throw new RuntimeException("Failed to remove principal-based ACL ("+e.getMessage()+")");
+ }
+ }
+ }
}
diff --git a/src/main/java/org/apache/sling/jcr/repoinit/impl/DoNothingVisitor.java b/src/main/java/org/apache/sling/jcr/repoinit/impl/DoNothingVisitor.java
index c2ae6ed..424e978 100644
--- a/src/main/java/org/apache/sling/jcr/repoinit/impl/DoNothingVisitor.java
+++ b/src/main/java/org/apache/sling/jcr/repoinit/impl/DoNothingVisitor.java
@@ -31,6 +31,9 @@ import org.apache.sling.repoinit.parser.operations.OperationVisitor;
import org.apache.sling.repoinit.parser.operations.RegisterNamespace;
import org.apache.sling.repoinit.parser.operations.RegisterNodetypes;
import org.apache.sling.repoinit.parser.operations.RegisterPrivilege;
+import org.apache.sling.repoinit.parser.operations.RemoveAclPaths;
+import org.apache.sling.repoinit.parser.operations.RemoveAclPrincipalBased;
+import org.apache.sling.repoinit.parser.operations.RemoveAclPrincipals;
import org.apache.sling.repoinit.parser.operations.RemoveGroupMembers;
import org.apache.sling.repoinit.parser.operations.SetAclPaths;
import org.apache.sling.repoinit.parser.operations.SetAclPrincipalBased;
@@ -97,6 +100,18 @@ class DoNothingVisitor implements OperationVisitor {
}
@Override
+ public void visitRemoveAclPrincipals(RemoveAclPrincipals s) {
+ }
+
+ @Override
+ public void visitRemoveAclPaths(RemoveAclPaths s) {
+ }
+
+ @Override
+ public void visitRemoveAclPrincipalBased(RemoveAclPrincipalBased s) {
+ }
+
+ @Override
public void visitCreatePath(CreatePath cp) {
}
diff --git a/src/test/java/org/apache/sling/jcr/repoinit/PrincipalBasedAclTest.java b/src/test/java/org/apache/sling/jcr/repoinit/PrincipalBasedAclTest.java
index b0a9a84..bc95b9f 100644
--- a/src/test/java/org/apache/sling/jcr/repoinit/PrincipalBasedAclTest.java
+++ b/src/test/java/org/apache/sling/jcr/repoinit/PrincipalBasedAclTest.java
@@ -83,6 +83,7 @@ public class PrincipalBasedAclTest {
private Repository repository;
private JackrabbitSession adminSession;
+ private JackrabbitAccessControlManager acMgr;
private TestUtil U;
@@ -99,6 +100,7 @@ public class PrincipalBasedAclTest {
String uid = sp.getParameters(UserConfiguration.NAME).getConfigValue(UserConstants.PARAM_ADMIN_ID, UserConstants.DEFAULT_ADMIN_ID);
adminSession = (JackrabbitSession) repository.login(new SimpleCredentials(uid, uid.toCharArray()), null);
+ acMgr = AclUtil.getJACM(adminSession);
U = new TestUtil(adminSession);
Node tmp = adminSession.getRootNode().addNode("tmp_" + U.id);
@@ -180,6 +182,20 @@ public class PrincipalBasedAclTest {
assertTrue("Expecting '" + shouldMatch + "'' to match " + regex, shouldMatch.matches(regex));
}
+ private Authorizable getServiceUser(@NotNull String uid) throws RepositoryException {
+ UserManager uMgr = adminSession.getUserManager();
+ Authorizable a = uMgr.getAuthorizable(uid);
+ if (a != null) {
+ return a;
+ } else {
+ throw new RepositoryException("Expected service user " + uid + " to exist.");
+ }
+ }
+
+ private Principal getPrincipal(@NotNull String serviceUserId) throws RepositoryException {
+ return getServiceUser(serviceUserId).getPrincipal();
+ }
+
@Test
public void readGranted() throws Exception {
String setup =
@@ -595,7 +611,7 @@ public class PrincipalBasedAclTest {
+ "end";
U.parseAndExecute(setup);
- Principal principal = adminSession.getUserManager().getAuthorizable("otherSystemPrincipal").getPrincipal();
+ Principal principal = getPrincipal("otherSystemPrincipal");
for (AccessControlPolicy policy : acMgr.getPolicies(principal)) {
assertFalse(policy instanceof PrincipalAccessControlList);
}
@@ -606,7 +622,7 @@ public class PrincipalBasedAclTest {
@Test
public void testHomePath() throws Exception {
- Authorizable su = getServiceUser(U.adminSession, U.username);
+ Authorizable su = getServiceUser(U.username);
Principal principal = su.getPrincipal();
assertNull(getAcl(principal, U.adminSession));
@@ -728,7 +744,7 @@ public class PrincipalBasedAclTest {
+ "end";
U.parseAndExecute(setup);
- assertNull(getAcl(getServiceUser(U.adminSession, U.username).getPrincipal(), U.adminSession));
+ assertNull(getAcl(getPrincipal(U.username), U.adminSession));
}
@Test(expected = RuntimeException.class)
@@ -752,7 +768,7 @@ public class PrincipalBasedAclTest {
+ "end";
U.parseAndExecute(setup);
- PrincipalAccessControlList acl = getAcl(getServiceUser(U.adminSession, U.username).getPrincipal(), U.adminSession);
+ PrincipalAccessControlList acl = getAcl(getPrincipal(U.username), U.adminSession);
assertNotNull(acl);
assertTrue(acl.isEmpty());
}
@@ -765,7 +781,7 @@ public class PrincipalBasedAclTest {
+ "end";
U.parseAndExecute(setup);
- PrincipalAccessControlList acl = getAcl(getServiceUser(U.adminSession, U.username).getPrincipal(), U.adminSession);
+ PrincipalAccessControlList acl = getAcl(getPrincipal(U.username), U.adminSession);
assertNotNull(acl);
assertEquals(2, acl.size());
@@ -774,7 +790,7 @@ public class PrincipalBasedAclTest {
+ "end";
U.parseAndExecute(setup);
- acl = getAcl(getServiceUser(U.adminSession, U.username).getPrincipal(), U.adminSession);
+ acl = getAcl(getPrincipal(U.username), U.adminSession);
assertNotNull(acl);
assertEquals(1, acl.size());
}
@@ -787,7 +803,7 @@ public class PrincipalBasedAclTest {
+ "end";
U.parseAndExecute(setup);
- PrincipalAccessControlList acl = getAcl(getServiceUser(U.adminSession, U.username).getPrincipal(), U.adminSession);
+ PrincipalAccessControlList acl = getAcl(getPrincipal(U.username), U.adminSession);
assertNotNull(acl);
assertEquals(2, acl.size());
@@ -796,7 +812,7 @@ public class PrincipalBasedAclTest {
+ "end";
U.parseAndExecute(setup);
- acl = getAcl(getServiceUser(U.adminSession, U.username).getPrincipal(), U.adminSession);
+ acl = getAcl(getPrincipal(U.username), U.adminSession);
assertNotNull(acl);
assertEquals(1, acl.size());
}
@@ -809,7 +825,7 @@ public class PrincipalBasedAclTest {
+ "end";
U.parseAndExecute(setup);
- PrincipalAccessControlList acl = getAcl(getServiceUser(U.adminSession, U.username).getPrincipal(), U.adminSession);
+ PrincipalAccessControlList acl = getAcl(getPrincipal(U.username), U.adminSession);
assertNotNull(acl);
assertEquals(2, acl.size());
@@ -818,7 +834,7 @@ public class PrincipalBasedAclTest {
+ "end";
U.parseAndExecute(setup);
- acl = getAcl(getServiceUser(U.adminSession, U.username).getPrincipal(), U.adminSession);
+ acl = getAcl(getPrincipal(U.username), U.adminSession);
assertNotNull(acl);
assertTrue(acl.isEmpty());
}
@@ -836,7 +852,7 @@ public class PrincipalBasedAclTest {
+ "end";
U.parseAndExecute(setup);
- PrincipalAccessControlList acl = getAcl(getServiceUser(U.adminSession, U.username).getPrincipal(), U.adminSession);
+ PrincipalAccessControlList acl = getAcl(getPrincipal(U.username), U.adminSession);
assertNotNull(acl);
assertEquals(2, acl.size());
}
@@ -870,20 +886,84 @@ public class PrincipalBasedAclTest {
);
{
- PrincipalAccessControlList acl = getAcl(getServiceUser(U.adminSession, U.username).getPrincipal(), U.adminSession);
+ PrincipalAccessControlList acl = getAcl(getPrincipal(U.username), U.adminSession);
assertNotNull(acl);
assertEquals(0, acl.size());
}
-}
+ }
- private static Authorizable getServiceUser(@NotNull Session session, @NotNull String uid) throws RepositoryException {
- UserManager uMgr = ((JackrabbitSession) session).getUserManager();
- Authorizable a = uMgr.getAuthorizable(uid);
- if (a != null) {
- return a;
- } else {
- throw new RepositoryException("Expected service user " + uid + " to exist.");
+ @Test
+ public void testAddAndRemoveAcl() throws Exception {
+ U.parseAndExecute(""
+ + "set principal ACL for " + U.username + "\n"
+ + "allow jcr:write on "+path+"\n"
+ + "end\n"
+ + "remove principal ACL for " + U.username + "\n"
+ );
+
+ assertNull(getAcl(getPrincipal(U.username), U.adminSession));
+ }
+
+ @Test
+ public void testRemoveAcl() throws Exception {
+ PrincipalAccessControlList acl = getApplicableAcl(getPrincipal(U.username), U.adminSession);
+ acl.addEntry("/content", AccessControlUtils.privilegesFromNames(U.adminSession, Privilege.JCR_READ));
+ U.adminSession.getAccessControlManager().setPolicy(acl.getPath(), acl);
+ U.adminSession.save();
+
+ assertNotNull(getAcl(getPrincipal(U.username), U.adminSession));
+ U.parseAndExecute("remove principal ACL for " + U.username + "\n");
+ assertNull(getAcl(getPrincipal(U.username), U.adminSession));
+ }
+
+ @Test
+ public void testRemoveNonExistingAcl() throws Exception {
+ assertNull(getAcl(getPrincipal(U.username), U.adminSession));
+ // removing non-existing policy must not fail
+ U.parseAndExecute("remove principal ACL for " + U.username + "\n");
+ assertNull(getAcl(getPrincipal(U.username), U.adminSession));
+ }
+
+ @Test
+ public void testRemoveAclNonExistingPrincipal() throws Exception {
+ assertNull(getAcl(getPrincipal(U.username), U.adminSession));
+ // removing policy for non-existing principal must not fail
+ U.parseAndExecute("remove principal ACL for non-existing-service-user\n");
+ assertNull(getAcl(getPrincipal(U.username), U.adminSession));
+ }
+
+ @Test
+ public void testRemoveResourceBasedAclByPrincipal() throws Exception {
+ U.parseAndExecute(""
+ + "create path (nt:unstructured) /var\n"
+ + "set ACL for " + U.username + "\n"
+ + "allow jcr:read on /var\n"
+ + "end\n"
+ + "set principal ACL for " + U.username + "\n"
+ + "allow jcr:read on /var\n"
+ + "end\n");
+
+ assertEquals(1, acMgr.getPolicies("/var").length);
+
+ U.parseAndExecute("remove ACL for "+U.username+"\n");
+ // resource-based acl at /var must be removed as it only contains a single entry for U.userName
+ assertEquals(0, acMgr.getPolicies("/var").length);
+
+ // removing resource-based ac-setup by principal must not delete any principal-based ac setup.
+ Principal p = getPrincipal(U.username);
+ AccessControlPolicy[] policies = acMgr.getPolicies(p);
+ assertEquals(1, policies.length);
+ assertTrue(policies[0] instanceof PrincipalAccessControlList);
+ }
+
+ @Nullable
+ private static PrincipalAccessControlList getApplicableAcl(@NotNull Principal principal, @NotNull Session session) throws RepositoryException {
+ for (AccessControlPolicy policy : AclUtil.getJACM(session).getApplicablePolicies(principal)) {
+ if (policy instanceof PrincipalAccessControlList) {
+ return (PrincipalAccessControlList) policy;
+ }
}
+ return null;
}
@Nullable
diff --git a/src/test/java/org/apache/sling/jcr/repoinit/RemoveAclTest.java b/src/test/java/org/apache/sling/jcr/repoinit/RemoveAclTest.java
new file mode 100644
index 0000000..aaa9fad
--- /dev/null
+++ b/src/test/java/org/apache/sling/jcr/repoinit/RemoveAclTest.java
@@ -0,0 +1,174 @@
+/*
+ * 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 com.google.common.collect.Lists;
+import org.apache.jackrabbit.api.JackrabbitRepository;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
+import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.oak.jcr.Jcr;
+import org.apache.jackrabbit.oak.security.internal.SecurityProviderBuilder;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
+import org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
+import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.apache.jackrabbit.oak.spi.xml.ImportBehavior;
+import org.apache.jackrabbit.oak.spi.xml.ProtectedItemImporter;
+import org.apache.sling.jcr.repoinit.impl.AclUtil;
+import org.apache.sling.jcr.repoinit.impl.TestUtil;
+import org.apache.sling.repoinit.parser.RepoInitParsingException;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.security.AccessControlPolicy;
+import java.security.Principal;
+import java.util.Collection;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+@RunWith(Parameterized.class)
+public class RemoveAclTest {
+
+ @Parameterized.Parameters(name = "ImportBehavior={0}")
+ public static Collection<Object[]> parameters() {
+ return Lists.newArrayList(
+ new Object[] {ImportBehavior.NAME_IGNORE},
+ new Object[] {ImportBehavior.NAME_BESTEFFORT},
+ new Object[] {ImportBehavior.NAME_ABORT}
+ );
+ }
+
+ private final String importBehaviorName;
+
+ private Repository repository;
+ private Session adminSession;
+ private JackrabbitAccessControlManager acMgr;
+
+ private TestUtil U;
+ private String userA;
+
+ public RemoveAclTest(String name) {
+ this.importBehaviorName = name;
+ }
+
+ @Before
+ public void setup() throws RepositoryException, RepoInitParsingException {
+ SecurityProvider sp = createSecurityProvider();
+ repository = new Jcr().with(sp).createRepository();
+
+ String uid = sp.getParameters(UserConfiguration.NAME).getConfigValue(UserConstants.PARAM_ADMIN_ID, UserConstants.DEFAULT_ADMIN_ID);
+ adminSession = repository.login(new SimpleCredentials(uid, uid.toCharArray()), null);
+ acMgr = AclUtil.getJACM(adminSession);
+ U = new TestUtil(adminSession);
+
+ userA = "userA_" + U.id;
+
+ U.parseAndExecute("create service user " + U.username);
+ U.parseAndExecute("create service user " + userA);
+ U.parseAndExecute(""
+ + "create path (nt:unstructured) /content\n"
+ + "create path (nt:unstructured) /var\n"
+ + "set ACL for " + U.username + "\n"
+ + "allow jcr:read on /content, /var, home("+userA+")\n"
+ + "allow jcr:namespaceManagement on :repository\n"
+ + "end\n"
+ + "set ACL for " + userA + "\n"
+ + "allow jcr:read on /content, /var\n"
+ + "end\n");
+ }
+
+ private SecurityProvider createSecurityProvider() {
+ return SecurityProviderBuilder.newBuilder().with(ConfigurationParameters.of(AuthorizationConfiguration.NAME, ConfigurationParameters.of(ProtectedItemImporter.PARAM_IMPORT_BEHAVIOR, importBehaviorName))).build();
+ }
+
+ @After
+ public void after() throws Exception {
+ try {
+ adminSession.removeItem("/content");
+ adminSession.removeItem("/var");
+ adminSession.save();
+ U.cleanupUser();
+ U.cleanupServiceUser(userA);
+ } finally {
+ adminSession.logout();
+ if (repository instanceof JackrabbitRepository) {
+ ((JackrabbitRepository) repository).shutdown();
+ }
+ }
+ }
+
+ @Test
+ public void testRemoveAcl() throws Exception {
+ U.parseAndExecute("remove ACL on /content, :repository\n");
+
+ assertArrayEquals(new AccessControlPolicy[0], acMgr.getPolicies("/content"));
+ assertArrayEquals(new AccessControlPolicy[0], acMgr.getPolicies((String) null));
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void testRemoveAclNonExistingPath() throws Exception {
+ U.parseAndExecute("remove ACL on /nonExisting\n");
+ }
+
+ @Test
+ public void testRemoveAclByPrincipal() throws Exception {
+ U.parseAndExecute("remove ACL for "+userA+"\n");
+
+ // removing resource-based ac setup by principal must leave entries for other principals intact
+ for (String path : new String[] {"/content", "/var"}) {
+ JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(adminSession, path);
+ assertNotNull(acl);
+ assertEquals(1, acl.size()); // entry for U.username must not have been removed
+ assertEquals(U.username, acl.getAccessControlEntries()[0].getPrincipal().getName());
+ }
+ }
+
+ @Test
+ public void testRemoveAclByNonExistingPrincipal() throws Exception {
+ Principal p = new PrincipalImpl("non-existing-service-user");
+ assertEquals(0, acMgr.getPolicies(p).length);
+
+ // execution for non-existing principal must not fail
+ U.parseAndExecute("remove ACL for non-existing-service-user\n");
+
+ assertEquals(0, acMgr.getPolicies(p).length);
+ }
+
+ @Test
+ public void testRemoveUserAndAcl() throws Exception {
+ Principal p = new PrincipalImpl(userA);
+ assertEquals(1, acMgr.getPolicies(p).length);
+
+ U.parseAndExecute("delete service user "+userA+"\n");
+ assertEquals(1, acMgr.getPolicies(p).length);
+
+ U.parseAndExecute("remove ACL for "+userA+"\n");
+ assertEquals(0, acMgr.getPolicies(p).length);
+ }
+}
\ No newline at end of file