You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by kw...@apache.org on 2023/01/10 08:37:01 UTC

[sling-org-apache-sling-repoinit-parser] branch master updated: SLING-10281 add "ensure principal ACL" with stricter semantics (#28)

This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-repoinit-parser.git


The following commit(s) were added to refs/heads/master by this push:
     new e09013b  SLING-10281 add "ensure principal ACL" with stricter semantics (#28)
e09013b is described below

commit e09013b0434d6088cbb8b189337ae6b322aa7722
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Tue Jan 10 09:36:55 2023 +0100

    SLING-10281 add "ensure principal ACL" with stricter semantics (#28)
---
 ...ipalBased.java => EnsureAclPrincipalBased.java} | 12 +++--
 .../parser/operations/OperationVisitor.java        |  2 +
 .../parser/operations/SetAclPrincipalBased.java    |  2 +
 .../repoinit/parser/operations/package-info.java   |  2 +-
 src/main/javacc/RepoInitGrammar.jjt                | 19 ++++++++
 .../parser/test/OperationToStringVisitor.java      | 18 ++++++-
 src/test/resources/testcases/test-74-output.txt    | 23 +++++++++
 src/test/resources/testcases/test-74.txt           | 55 ++++++++++++++++++++++
 8 files changed, 126 insertions(+), 7 deletions(-)

diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPrincipalBased.java b/src/main/java/org/apache/sling/repoinit/parser/operations/EnsureAclPrincipalBased.java
similarity index 81%
copy from src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPrincipalBased.java
copy to src/main/java/org/apache/sling/repoinit/parser/operations/EnsureAclPrincipalBased.java
index 5f8b937..552ce0c 100644
--- a/src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPrincipalBased.java
+++ b/src/main/java/org/apache/sling/repoinit/parser/operations/EnsureAclPrincipalBased.java
@@ -27,17 +27,19 @@ import org.osgi.annotation.versioning.ProviderType;
 
 /** Set ACL statement that groups a set of AclLines
  *  that all refer to the same set of principals.
+ *  Fails in case the principal ACLs cannot be applied for some reason.
+ *  @see SetAclPrincipalBased
  */
 @ProviderType
-public class SetAclPrincipalBased extends AclGroupBase {
+public class EnsureAclPrincipalBased extends AclGroupBase {
 
     private final List<String> principals;
 
-    public SetAclPrincipalBased(List<String> principals, List<AclLine> lines) {
+    public EnsureAclPrincipalBased(List<String> principals, List<AclLine> lines) {
         this(principals,lines,new ArrayList<>());
     }
 
-    public SetAclPrincipalBased(List<String> principals, List<AclLine> lines, List<String> aclOptions) {
+    public EnsureAclPrincipalBased(List<String> principals, List<AclLine> lines, List<String> aclOptions) {
         super(lines,aclOptions);
         this.principals = Collections.unmodifiableList(principals);
     }
@@ -53,7 +55,7 @@ public class SetAclPrincipalBased extends AclGroupBase {
     @NotNull
     @Override
     public String asRepoInitString() {
-        String topline = String.format("set principal ACL for %s%s%n",
+        String topline = String.format("ensure principal ACL for %s%s%n",
                 listToString(QuotableStringUtil.forRepoInitString(principals)), getAclOptionsString());
         return asRepoInit(topline, true);
     }
@@ -64,6 +66,6 @@ public class SetAclPrincipalBased extends AclGroupBase {
 
     @Override
     public void accept(OperationVisitor v) {
-        v.visitSetAclPrincipalBased(this);
+        v.visitEnsureAclPrincipalBased(this);
     }
 }
diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/OperationVisitor.java b/src/main/java/org/apache/sling/repoinit/parser/operations/OperationVisitor.java
index f2a3919..b009434 100644
--- a/src/main/java/org/apache/sling/repoinit/parser/operations/OperationVisitor.java
+++ b/src/main/java/org/apache/sling/repoinit/parser/operations/OperationVisitor.java
@@ -29,7 +29,9 @@ public interface OperationVisitor {
     void visitDeleteServiceUser(DeleteServiceUser s);
     void visitSetAclPrincipal(SetAclPrincipals s);
     void visitSetAclPaths(SetAclPaths s);
+    @Deprecated
     void visitSetAclPrincipalBased(SetAclPrincipalBased s);
+    default void visitEnsureAclPrincipalBased(EnsureAclPrincipalBased ensureAclPrincipalBased) { throw new UnsupportedOperationException(); }
     default void visitRemoveAcePrincipal(RemoveAcePrincipals s) { throw new UnsupportedOperationException(); }
     default void visitRemoveAcePaths(RemoveAcePaths s) { throw new UnsupportedOperationException(); }
     default void visitRemoveAcePrincipalBased(RemoveAcePrincipalBased s) { throw new UnsupportedOperationException(); }
diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPrincipalBased.java b/src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPrincipalBased.java
index 5f8b937..9d0d8c9 100644
--- a/src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPrincipalBased.java
+++ b/src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPrincipalBased.java
@@ -27,7 +27,9 @@ import org.osgi.annotation.versioning.ProviderType;
 
 /** Set ACL statement that groups a set of AclLines
  *  that all refer to the same set of principals.
+ *  @deprecated Use {@link EnsureAclPrincipalBased} instead with stricter semantics
  */
+@Deprecated
 @ProviderType
 public class SetAclPrincipalBased extends AclGroupBase {
 
diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/package-info.java b/src/main/java/org/apache/sling/repoinit/parser/operations/package-info.java
index 3904b7c..8e43410 100644
--- a/src/main/java/org/apache/sling/repoinit/parser/operations/package-info.java
+++ b/src/main/java/org/apache/sling/repoinit/parser/operations/package-info.java
@@ -15,6 +15,6 @@
  * limitations under the License.
  ******************************************************************************/
 
-@org.osgi.annotation.versioning.Version("6.1.0")
+@org.osgi.annotation.versioning.Version("6.2.0")
 package org.apache.sling.repoinit.parser.operations;
 
diff --git a/src/main/javacc/RepoInitGrammar.jjt b/src/main/javacc/RepoInitGrammar.jjt
index d068f57..c2b9181 100644
--- a/src/main/javacc/RepoInitGrammar.jjt
+++ b/src/main/javacc/RepoInitGrammar.jjt
@@ -68,6 +68,7 @@ TOKEN:
 |   < FOR: "for" >
 |   < CREATE: "create" >
 |   < DELETE: "delete" >
+|   < ENSURE: "ensure" >
 |   < DISABLE: "disable" >
 |   < SERVICE: "service" >
 |   < ADD: "add" >
@@ -144,6 +145,7 @@ List<Operation> parse() :
         | setAclPaths(result) 
         | setAclPrincipals(result)
         | setAclPrincipalBased(result)
+        | ensureAclPrincipalBased(result)
         | setAclRepository(result)
         | deleteAclPaths(result) 
         | deleteAclPrincipals(result)
@@ -607,6 +609,23 @@ void setAclPrincipalBased(List<Operation> result) :
     }
 }
 
+void ensureAclPrincipalBased(List<Operation> result) :
+{
+    List <String> principals;
+    List<AclLine> lines = new ArrayList<AclLine>();
+    List<String> aclOptions;
+}
+{
+    <ENSURE> <PRINCIPAL> <ACL> <FOR> principals = principalsList() aclOptions=aclOptions() <EOL>
+    ( removeStarLine(lines) | pathPrivilegesLine(lines, true) | blankLine() ) +
+    <END>
+    ( <EOL> | <EOF> )
+
+    {
+        result.add(new EnsureAclPrincipalBased(principals, lines, aclOptions));
+    }
+}
+
 void removeAcePaths(List<Operation> result) :
 {
     List<String> paths;
diff --git a/src/test/java/org/apache/sling/repoinit/parser/test/OperationToStringVisitor.java b/src/test/java/org/apache/sling/repoinit/parser/test/OperationToStringVisitor.java
index 0a17b17..419fa0d 100644
--- a/src/test/java/org/apache/sling/repoinit/parser/test/OperationToStringVisitor.java
+++ b/src/test/java/org/apache/sling/repoinit/parser/test/OperationToStringVisitor.java
@@ -32,6 +32,7 @@ import org.apache.sling.repoinit.parser.operations.DeleteGroup;
 import org.apache.sling.repoinit.parser.operations.DeleteServiceUser;
 import org.apache.sling.repoinit.parser.operations.DeleteUser;
 import org.apache.sling.repoinit.parser.operations.DisableServiceUser;
+import org.apache.sling.repoinit.parser.operations.EnsureAclPrincipalBased;
 import org.apache.sling.repoinit.parser.operations.RegisterNodetypes;
 import org.apache.sling.repoinit.parser.operations.OperationVisitor;
 import org.apache.sling.repoinit.parser.operations.RegisterNamespace;
@@ -103,7 +104,7 @@ class OperationToStringVisitor implements OperationVisitor {
         out.println();
         dumpAclLines(s.getLines());
     }
-    
+
     @Override
     public void visitSetAclPaths(SetAclPaths s) {
         out.print(s.getClass().getSimpleName());
@@ -134,6 +135,21 @@ class OperationToStringVisitor implements OperationVisitor {
         dumpAclLines(s.getLines());
     }
 
+    @Override
+    public void visitEnsureAclPrincipalBased(EnsureAclPrincipalBased s) {
+        out.print(s.getClass().getSimpleName());
+        out.print(" for ");
+        for(String p : s.getPrincipals()) {
+            out.print(p);
+            out.print(' ');
+        }
+
+        dumpAclOptions(s.getOptions());
+
+        out.println();
+        dumpAclLines(s.getLines());
+    }
+
     @Override
     public void visitRemoveAcePrincipal(RemoveAcePrincipals s) {
         out.print(s.getClass().getSimpleName());
diff --git a/src/test/resources/testcases/test-74-output.txt b/src/test/resources/testcases/test-74-output.txt
new file mode 100644
index 0000000..9349807
--- /dev/null
+++ b/src/test/resources/testcases/test-74-output.txt
@@ -0,0 +1,23 @@
+EnsureAclPrincipalBased for principal1 principal2 
+  AclLine REMOVE_ALL {paths=[/libs, /apps]}
+  AclLine ALLOW {paths=[/content], privileges=[jcr:read]}
+  AclLine DENY {paths=[/apps], privileges=[jcr:write]}
+  AclLine DENY {nodetypes=[sling:Folder, nt:unstructured], paths=[/apps, /content], privileges=[jcr:lockManagement]}
+  AclLine DENY {nodetypes=[sling:Folder, nt:unstructured], paths=[/apps, /content], privileges=[jcr:modifyProperties]} restrictions=[rep:itemNames=[prop1, prop2]]
+  AclLine REMOVE {paths=[/apps], privileges=[jcr:understand, some:other]}
+  AclLine ALLOW {paths=[/apps], privileges=[jcr:addChildNodes]} restrictions=[rep:ntNames=[sling:Folder, nt:unstructured]]
+  AclLine ALLOW {paths=[/apps], privileges=[jcr:modifyProperties]} restrictions=[rep:ntNames=[sling:Folder, nt:unstructured], rep:itemNames=[prop1, prop2]]
+  AclLine ALLOW {paths=[/apps, /content], privileges=[jcr:addChildNodes]} restrictions=[rep:glob=[/cat, /cat/, cat]]
+  AclLine ALLOW {paths=[/apps, /content], privileges=[jcr:addChildNodes]} restrictions=[rep:glob=[cat/, *, *cat]]
+  AclLine ALLOW {paths=[/apps, /content], privileges=[jcr:addChildNodes]} restrictions=[rep:glob=[/cat/*, */cat, *cat/*]]
+  AclLine ALLOW {paths=[/], privileges=[jcr:something]} restrictions=[rep:glob=[]]
+EnsureAclPrincipalBased for principal1 principal2 ACLOptions=[mergePreserve]
+  AclLine REMOVE_ALL {paths=[/libs, /apps]}
+  AclLine ALLOW {paths=[/content], privileges=[jcr:read]}
+EnsureAclPrincipalBased for principal1 principal2 ACLOptions=[mergePreserve, someOtherOption, someOther123, namespaced:option]
+  AclLine REMOVE_ALL {paths=[/libs, /apps]}
+  AclLine ALLOW {paths=[/content], privileges=[jcr:read]}
+EnsureAclPrincipalBased for principal1 principal2 
+  AclLine ALLOW {paths=[:repository], privileges=[jcr:namespaceManagement]}
+EnsureAclPrincipalBased for principal1 
+  AclLine ALLOW {paths=[:repository, /content], privileges=[jcr:all]}
\ No newline at end of file
diff --git a/src/test/resources/testcases/test-74.txt b/src/test/resources/testcases/test-74.txt
new file mode 100644
index 0000000..5170e58
--- /dev/null
+++ b/src/test/resources/testcases/test-74.txt
@@ -0,0 +1,55 @@
+# Set principal-based access control (see SLING-8602), requires
+# o.a.s.repoinit.parser 1.2.8 and
+# o.a.s.jcr.repoinit 1.1.14
+# precondition for o.a.s.jcr.repoinit: 
+# repository needs to support 'o.a.j.api.security.authorization.PrincipalAccessControlList'
+# Also, this only works for users selected by the Jackrabbit/Oak FilterProvider, see
+# https://jackrabbit.apache.org/oak/docs/security/authorization/principalbased.html#configuration
+# mostly a copy of test-33 but with "ensure" prefix instead of "set"
+
+ensure principal ACL for principal1,principal2
+    remove * on /libs,/apps
+    allow jcr:read on /content
+
+    deny jcr:write on /apps
+
+    # Optional nodetypes clause
+    deny jcr:lockManagement on /apps, /content nodetypes sling:Folder, nt:unstructured
+    # nodetypes clause with restriction clause
+    deny jcr:modifyProperties on /apps, /content nodetypes sling:Folder, nt:unstructured restriction(rep:itemNames,prop1,prop2)
+    remove jcr:understand,some:other on /apps
+
+    # multi value restriction
+    allow jcr:addChildNodes on /apps restriction(rep:ntNames,sling:Folder,nt:unstructured)
+
+    # multiple restrictions
+    allow jcr:modifyProperties on /apps restriction(rep:ntNames,sling:Folder,nt:unstructured) restriction(rep:itemNames,prop1,prop2)
+
+    # restrictions with glob patterns
+    allow jcr:addChildNodes on /apps,/content restriction(rep:glob,/cat,/cat/,cat)
+    allow jcr:addChildNodes on /apps,/content restriction(rep:glob,cat/,*,*cat)
+    allow jcr:addChildNodes on /apps,/content restriction(rep:glob,/cat/*,*/cat,*cat/*)
+
+    allow jcr:something on / restriction(rep:glob)
+end
+
+# Principal-based ACL syntax with options (SLING-6423)
+ensure principal ACL for principal1,principal2 (ACLOptions=mergePreserve)
+    remove * on /libs,/apps
+    allow jcr:read on /content
+end
+
+# With multiple options
+ensure principal ACL for principal1,principal2 (ACLOptions=mergePreserve,someOtherOption,someOther123,namespaced:option)
+    remove * on /libs,/apps
+    allow jcr:read on /content
+end
+
+# repository level
+ensure principal ACL for principal1,principal2
+    allow jcr:namespaceManagement on :repository 
+end
+
+ensure principal ACL for principal1
+    allow jcr:all on :repository,/content
+end
\ No newline at end of file