You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by tm...@apache.org on 2017/09/19 09:01:32 UTC
svn commit: r1808845 - in /sling/trunk/bundles:
extensions/repoinit/parser/src/main/javacc/
jcr/repoinit/src/main/java/org/apache/sling/jcr/repoinit/impl/
jcr/repoinit/src/test/java/org/apache/sling/jcr/repoinit/
Author: tmaret
Date: Tue Sep 19 09:01:32 2017
New Revision: 1808845
URL: http://svn.apache.org/viewvc?rev=1808845&view=rev
Log:
SLING-7061 - Access control setup of repository-level permissions (i.e. null path)
* Add parser and JCR implementation
Modified:
sling/trunk/bundles/extensions/repoinit/parser/src/main/javacc/RepoInitGrammar.jjt
sling/trunk/bundles/jcr/repoinit/src/main/java/org/apache/sling/jcr/repoinit/impl/AclUtil.java
sling/trunk/bundles/jcr/repoinit/src/main/java/org/apache/sling/jcr/repoinit/impl/AclVisitor.java
sling/trunk/bundles/jcr/repoinit/src/test/java/org/apache/sling/jcr/repoinit/GeneralAclTest.java
Modified: sling/trunk/bundles/extensions/repoinit/parser/src/main/javacc/RepoInitGrammar.jjt
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/repoinit/parser/src/main/javacc/RepoInitGrammar.jjt?rev=1808845&r1=1808844&r2=1808845&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/repoinit/parser/src/main/javacc/RepoInitGrammar.jjt (original)
+++ sling/trunk/bundles/extensions/repoinit/parser/src/main/javacc/RepoInitGrammar.jjt Tue Sep 19 09:01:32 2017
@@ -68,6 +68,7 @@ TOKEN:
| < MIXIN: "mixin" >
| < PATH: "path" >
| < END: "end" >
+| < REPOSITORY: "repository" >
| < USER: "user" >
| < NODETYPES: "nodetypes" >
| < REGISTER: "register" >
@@ -127,6 +128,7 @@ List<Operation> parse() :
serviceUserStatement(result)
| setAclPaths(result)
| setAclPrincipals(result)
+ | setAclRepository(result)
| createPathStatement(result)
| registerNamespaceStatement(result)
| registerNodetypesStatement(result)
@@ -400,6 +402,38 @@ List<String> aclOptions() :
}
}
+void setAclRepository(List<Operation> result) :
+{
+ List<AclLine> lines = new ArrayList<AclLine>();
+ List<String> principals;
+ List<String> privileges;
+ List<String> aclOptions;
+ AclLine line = null;
+
+}
+{
+ <SET> <REPOSITORY> <ACL> <FOR> principals = principalsList() aclOptions=aclOptions() <EOL>
+ (
+ ( <REMOVE> <STAR> )
+ {
+ line = new AclLine(AclLine.Action.REMOVE_ALL);
+ lines.add(line);
+ }
+ | ( line = privilegesLineOperation() privileges = namespacedItemsList() )
+ {
+ line.setProperty(AclLine.PROP_PRIVILEGES, privileges);
+ lines.add(line);
+ }
+ | ( blankLine() )
+ )+
+ <END>
+ ( <EOL> | <EOF> )
+
+ {
+ result.add(new SetAclPrincipals(principals, lines, aclOptions));
+ }
+}
+
void setAclPrincipals(List<Operation> result) :
{
List <String> principals;
Modified: sling/trunk/bundles/jcr/repoinit/src/main/java/org/apache/sling/jcr/repoinit/impl/AclUtil.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/repoinit/src/main/java/org/apache/sling/jcr/repoinit/impl/AclUtil.java?rev=1808845&r1=1808844&r2=1808845&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/repoinit/src/main/java/org/apache/sling/jcr/repoinit/impl/AclUtil.java (original)
+++ sling/trunk/bundles/jcr/repoinit/src/main/java/org/apache/sling/jcr/repoinit/impl/AclUtil.java Tue Sep 19 09:01:32 2017
@@ -100,52 +100,60 @@ public class AclUtil {
public static void setAcl(Session session, List<String> principals, List<String> paths, List<String> privileges, boolean isAllow, List<RestrictionClause> restrictionClauses)
throws RepositoryException {
-
- final String [] privArray = privileges.toArray(new String[privileges.size()]);
- final Privilege[] jcrPriv = AccessControlUtils.privilegesFromNames(session, privArray);
-
- for(String path : paths) {
+ for (String path : paths) {
if(!session.nodeExists(path)) {
throw new PathNotFoundException("Cannot set ACL on non-existent path " + path);
}
+ setAcl(session, principals, path, privileges, isAllow, restrictionClauses);
+ }
+ }
+
+ private static void setAcl(Session session, List<String> principals, String path, List<String> privileges, boolean isAllow, List<RestrictionClause> restrictionClauses)
+ throws RepositoryException {
+
+ final String [] privArray = privileges.toArray(new String[privileges.size()]);
+ final Privilege[] jcrPriv = AccessControlUtils.privilegesFromNames(session, privArray);
- JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(session, path);
+ JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(session, path);
- LocalRestrictions localRestrictions = createLocalRestrictions(restrictionClauses, acl, session);
+ LocalRestrictions localRestrictions = createLocalRestrictions(restrictionClauses, acl, session);
- AccessControlEntry[] existingAces = acl.getAccessControlEntries();
+ AccessControlEntry[] existingAces = acl.getAccessControlEntries();
- boolean changed = false;
- for (String name : principals) {
- final Principal principal;
- if (EveryonePrincipal.NAME.equals(name)) {
- principal = AccessControlUtils.getPrincipal(session, name);
- } else {
- final Authorizable authorizable = UserUtil.getAuthorizable(session, name);
- if (authorizable == null) {
- throw new IllegalStateException("Authorizable not found:" + name);
- }
- principal = authorizable.getPrincipal();
- }
- if (principal == null) {
- throw new IllegalStateException("Principal not found: " + name);
+ boolean changed = false;
+ for (String name : principals) {
+ final Principal principal;
+ if (EveryonePrincipal.NAME.equals(name)) {
+ principal = AccessControlUtils.getPrincipal(session, name);
+ } else {
+ final Authorizable authorizable = UserUtil.getAuthorizable(session, name);
+ if (authorizable == null) {
+ throw new IllegalStateException("Authorizable not found:" + name);
}
- LocalAccessControlEntry newAce = new LocalAccessControlEntry(principal, jcrPriv, isAllow, localRestrictions);
- if (contains(existingAces, newAce)) {
- LOG.info("Not adding {} to path {} since an equivalent access control entry already exists", newAce, path);
- continue;
- }
- acl.addEntry(newAce.principal, newAce.privileges, newAce.isAllow,
- newAce.restrictions.getRestrictions(), newAce.restrictions.getMVRestrictions());
- changed = true;
+ principal = authorizable.getPrincipal();
}
- if ( changed ) {
- getJACM(session).setPolicy(path, acl);
+ if (principal == null) {
+ throw new IllegalStateException("Principal not found: " + name);
}
-
+ LocalAccessControlEntry newAce = new LocalAccessControlEntry(principal, jcrPriv, isAllow, localRestrictions);
+ if (contains(existingAces, newAce)) {
+ LOG.info("Not adding {} to path {} since an equivalent access control entry already exists", newAce, path);
+ continue;
+ }
+ acl.addEntry(newAce.principal, newAce.privileges, newAce.isAllow,
+ newAce.restrictions.getRestrictions(), newAce.restrictions.getMVRestrictions());
+ changed = true;
+ }
+ if ( changed ) {
+ getJACM(session).setPolicy(path, acl);
}
}
+ public static void setRepositoryAcl(Session session, List<String> principals, List<String> privileges, boolean isAllow, List<RestrictionClause> restrictionClauses)
+ throws RepositoryException {
+ setAcl(session, principals, (String)null, privileges, isAllow, restrictionClauses);
+ }
+
// visible for testing
static boolean contains(AccessControlEntry[] existingAces, LocalAccessControlEntry newAce) throws RepositoryException {
for (int i = 0 ; i < existingAces.length; i++) {
Modified: sling/trunk/bundles/jcr/repoinit/src/main/java/org/apache/sling/jcr/repoinit/impl/AclVisitor.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/repoinit/src/main/java/org/apache/sling/jcr/repoinit/impl/AclVisitor.java?rev=1808845&r1=1808844&r2=1808845&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/repoinit/src/main/java/org/apache/sling/jcr/repoinit/impl/AclVisitor.java (original)
+++ sling/trunk/bundles/jcr/repoinit/src/main/java/org/apache/sling/jcr/repoinit/impl/AclVisitor.java Tue Sep 19 09:01:32 2017
@@ -64,12 +64,28 @@ class AclVisitor extends DoNothingVisito
}
}
+ private void setRepositoryAcl(AclLine line, Session s, List<String> principals, List<String> privileges, boolean isAllow) {
+ try {
+ log.info("Adding repository level ACL '{}' entry '{}' for {}", isAllow ? "allow" : "deny", privileges, principals);
+ List<RestrictionClause> restrictions = line.getRestrictions();
+ AclUtil.setRepositoryAcl(s, principals, privileges, isAllow, restrictions);
+ } catch(Exception e) {
+ throw new RuntimeException("Failed to set repository level ACL (" + e.toString() + ") " + line, e);
+ }
+ }
+
@Override
public void visitSetAclPrincipal(SetAclPrincipals s) {
final List<String> principals = s.getPrincipals();
for(AclLine line : s.getLines()) {
final boolean isAllow = line.getAction().equals(AclLine.Action.ALLOW);
- setAcl(line, session, principals, require(line, PROP_PATHS), require(line, PROP_PRIVILEGES), isAllow);
+ final List<String> paths = line.getProperty(PROP_PATHS);
+ if (paths != null && ! paths.isEmpty()) {
+ setAcl(line, session, principals, paths, require(line, PROP_PRIVILEGES), isAllow);
+ } else {
+ setRepositoryAcl(line, session, principals, require(line, PROP_PRIVILEGES), isAllow);
+ }
+
}
}
Modified: sling/trunk/bundles/jcr/repoinit/src/test/java/org/apache/sling/jcr/repoinit/GeneralAclTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/repoinit/src/test/java/org/apache/sling/jcr/repoinit/GeneralAclTest.java?rev=1808845&r1=1808844&r2=1808845&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/repoinit/src/test/java/org/apache/sling/jcr/repoinit/GeneralAclTest.java (original)
+++ sling/trunk/bundles/jcr/repoinit/src/test/java/org/apache/sling/jcr/repoinit/GeneralAclTest.java Tue Sep 19 09:01:32 2017
@@ -25,6 +25,8 @@ import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
+import javax.jcr.nodetype.NodeTypeManager;
+import javax.jcr.nodetype.NodeTypeTemplate;
import org.apache.sling.jcr.repoinit.impl.TestUtil;
import org.apache.sling.repoinit.parser.RepoInitParsingException;
@@ -146,6 +148,100 @@ public class GeneralAclTest {
}
}
+ @Test
+ public void addRepositoryAcl() throws Exception {
+ final String aclSetup =
+ "set repository ACL for " + userA + "," + userB + "\n"
+ + "allow jcr:namespaceManagement\n"
+ + "allow jcr:nodeTypeDefinitionManagement\n"
+ + "end"
+ ;
+
+ U.parseAndExecute(aclSetup);
+ verifyRegisterNamespace(userA, "a", "http://a", true);
+ verifyRegisterNamespace(userB, "b", "http://b", true);
+ verifyRegisterNamespace(U.username, "c", "http://c", false);
+ verifyRegisterNodeType(userA, "typeA", true);
+ verifyRegisterNodeType(userB, "typeB", true);
+ verifyRegisterNodeType(U.username, "typeC", false);
+ }
+
+ @Test
+ public void addRepositoryAclInMultipleBlocks() throws Exception {
+ final String aclSetup =
+ "set repository ACL for " + userA + "\n"
+ + "allow jcr:namespaceManagement,jcr:nodeTypeDefinitionManagement\n"
+ + "end\n"
+ + "set repository ACL for " + userB + "\n"
+ + "allow jcr:namespaceManagement\n"
+ + "end"
+ ;
+
+ U.parseAndExecute(aclSetup);
+ verifyRegisterNamespace(userA, "a", "http://a", true);
+ verifyRegisterNamespace(userB, "b", "http://b", true);
+ verifyRegisterNodeType(userA, "typeA", true);
+ verifyRegisterNodeType(userB, "typeB", false);
+ }
+
+ @Test
+ public void addRepositoryAclInSequence() throws Exception {
+ final String aclSetup =
+ "set repository ACL for " + U.username + "\n"
+ + "deny jcr:namespaceManagement,jcr:nodeTypeDefinitionManagement\n"
+ + "allow jcr:namespaceManagement,jcr:nodeTypeDefinitionManagement\n"
+ + "end\n"
+ + "set repository ACL for " + U.username + "\n"
+ + "deny jcr:namespaceManagement\n"
+ + "end"
+ ;
+
+ U.parseAndExecute(aclSetup);
+ verifyRegisterNodeType(U.username, "typeC", true);
+ verifyRegisterNamespace(U.username, "c", "http://c", false);
+ }
+
+ /**
+ * Verify the success/failure when registering a node type.
+ * Registering a node type requires to be granted the jcr:nodeTypeDefinitionManagement privilege.
+ */
+ private void verifyRegisterNodeType(String username, String typeName, boolean successExpected) {
+ Session userSession = null;
+ try {
+ userSession = U.loginService(username);
+ NodeTypeManager nodeTypeManager = userSession.getWorkspace().getNodeTypeManager();
+ NodeTypeTemplate type = nodeTypeManager.createNodeTypeTemplate();
+ type.setName(typeName);
+ nodeTypeManager.registerNodeType(type, true);
+ assertTrue("Register node type succeeded " + typeName, successExpected);
+ } catch (RepositoryException e) {
+ assertTrue("Error registering node type " + typeName + " " + e.getMessage(), !successExpected);
+ } finally {
+ if (userSession != null) {
+ userSession.logout();
+ }
+ }
+ }
+
+
+ /**
+ * Verify the success/failure when registering a namespace.
+ * Registering a namespace successfully requires to be granted the jcr:namespaceManagement privilege.
+ */
+ private void verifyRegisterNamespace(String username, String prefix, String uri, boolean successExpected) {
+ Session userSession = null;
+ try {
+ userSession = U.loginService(username);
+ userSession.getWorkspace().getNamespaceRegistry().registerNamespace(prefix, uri);
+ assertTrue("Register namespace succeeded " + prefix + uri, successExpected);
+ } catch (RepositoryException e) {
+ assertTrue("Error registering namespace " + prefix + uri + " " + e.getMessage(), !successExpected);
+ } finally {
+ if (userSession != null) {
+ userSession.logout();
+ }
+ }
+ }
/**
* Verifies success/failure of adding a child