Expand my Community achievements bar.

Enhance your AEM Assets & Boost Your Development: [AEM Gems | June 19, 2024] Improving the Developer Experience with New APIs and Events
SOLVED

Composing ACLs to restrict editing of Adaptive Form Fragments

Avatar

Level 2

We are using Adaptive Forms and want to restrict fragment editing to a sub-set of users. We currently have just the OOTB forms-related user groups, i.e., forms-users, forms-super-users, forms-script-writers and so on, and I created a new group who should have the fragment edit permissions. I created an OSGI configuration repoinit script like below as a first pass, but it's still too permissive - a user that's a member of forms-users can still edit fragments found under that path. Ideally, what I want in plain English is for members of any of the other user groups to only be able to read fragments and pull them into forms, but not edit them. Only members of the fragment-editors group should be able to edit the fragments.

{
    "scripts": [
        "set ACL on /content/dam/formsanddocuments/<project>/<fragments_root>\n   remove * for forms-users\n  allow jcr:read for forms-users\n    allow jcr:write,jcr:read for fragment-editors\nend",
        "set ACL on /content/forms/af/<project>/<fragments_root>\n   remove * for forms-users\n  allow jcr:read for forms-users\n    allow jcr:write,jcr:read for fragment-editors\nend"
    ]
}

 

Resources consulted:

User, Groups, and Access Rights Administration 

Sling Repoinit 

 

This seems like a fairly simple issue but ACLs are always tricky to get right!

Topics

Topics help categorize Community content and increase your ability to discover relevant content.

1 Accepted Solution

Avatar

Correct answer by
Level 2

**UPDATE #2**

 

I decided to go ahead and work out the `rep:glob` string, so it ended up being much neater and easier to read:

 

{
    "scripts": [
        "create group test-fragments-editors with path /home/groups/forms",
        "set ACL on /content/dam/formsanddocuments/<project>\n   remove * for forms-users\n  deny jcr:all for forms-users restriction(rep:glob,/<fragments_root>)\n    allow jcr:read,crx:replicate for forms-users restriction(rep:glob,/<fragments_root>)\n    allow jcr:all for test-fragments-editors restriction(rep:glob,/<fragments_root>)\nend",
        "set ACL on /content/forms/af/<project>\n   remove * for forms-users\n  deny jcr:all for forms-users restriction(rep:glob,/<fragments_root>)\n    allow jcr:read,crx:replicate for forms-users restriction(rep:glob,/<fragments_root>)\n    allow jcr:all restriction(rep:glob,/<fragments_root>)for test-fragments-editors\nend""
    ]
}

 

 

Notes:

* this creates a rep:policy node under the <project> node that in turn has rep:restrictions nodes under the allow/deny children of the ACL that restricts the effects of the allow/deny to only the <fragments_root> and its descendants

* this also means that a new fragments directory created under the <fragments_root> will automatically inherit the parent ACL

* added the crx:replicate permission, otherwise a form that included a fragment that had never been replicated would not successfully replicate

 

One question I have (perhaps @Vijay_Katoch you could answer this?), is it safe to create user groups under the /home/groups/forms path or is that a path that might get blown away with an Adaptive Forms update? Since it's a repoinit script, we're probably safe anyway as long as that directory exists, because the group will get created on script install and server restart, but it never hurts to ask.

 

EDIT: I'm marking this as the Correct Reply since it solves my problem. I welcome feedback to improve it.

View solution in original post

5 Replies

Avatar

Level 2

@VIJ

I appreciate the input but it may not be possible for me to use third-party tools. If that is indeed the case, then I need to start by understanding why that simple example above does not work. For example, I was working under the assumption that permissions defined at a higher level in the tree, say, 

/content/dam

would be overridden by rep:policy nodes deeper in the tree, /content/dam/formsanddocuments/<project>/<fragments_root> or even applying a policy on a fragment itself, which I have also tried. If I am not mistaken, there is a OOTB way to see all of the permissions applied on a path, but I don't recall how to find that tool. I created a user whose only group membership is forms-users but that user could still edit the fragments.

Avatar

Level 2

**UPDATE**

 

So here is where I currently am:

{
    "scripts": [
        "create group test-fragments-editors with path /home/groups/forms",
        "set ACL on /content/dam/formsanddocuments/<project>/<fragments_root>/fragmentDirectory1,/content/dam/formsanddocuments/<project>/<fragments_root>/fragmentDirectory2,/content/dam/formsanddocuments/<project>/<fragments_root>/fragmentDirectory3\n   remove * for forms-users\n  deny jcr:all for forms-users\n    allow jcr:read for forms-users\n    allow jcr:write,jcr:read for test-fragments-editors\nend",
        "set ACL on /content/forms/af/<project>/<fragments_root>/fragmentDirectory1,/content/forms/af/<project>/<fragments_root>/fragmentDirectory2,/content/forms/af/<project>/<fragments_root>/fragmentDirectory3\n   remove * for forms-users\n  deny jcr:all for forms-users\n    allow jcr:read for forms-users\n    allow jcr:write,jcr:read for test-fragments-editors\nend""
    ]
}

 

Notes on the above:

  • created the user group as part of the script
  • drilled down one more level
  • added the explicit deny jcr:all - this was the key to stopping the inheritance of permissions from the higher layers of the tree

This works as expected, although there are a few gaps. It might be that I live with it as good enough for today, but for the edification of others who may see this later, I'll lay out what I might do differently or add in a future iteration. For one thing, if you have pre-existing users (my team does) on the author/publish instances, you can add them to the group in the script, too. One thing to keep in mind - if a script throws an exception, it will prevent Sling from starting, and I presume that users not existing might cause such an exception. I had a broken script from an unescaped parentheses (experimenting) early on but followed these instructions to remove the broken script, fixed it, then re-deployed the package, so you can recover. Just be certain to throughly test locally before installing on a non-local environment.

 

I may add a rep:glob string to make sure the restrictions apply to child nodes, and move the paths back to the fragment root level. Right now, a forms-user member can create new fragments at the fragments root level, but this script does successfully keep them from editing the existing fragments contained in the fragmentsDirectoryN, which was the original intent here. I have tested adding the existing fragments to forms, and it works. Today I am going to test to verify it has no impact on replicating a form to the publisher and viewing them and interacting with them on the pub node. Obviously, if new child directories are added to the fragment root under which new fragments are created, the script will have to be updated to include them. This creation could be part of the script, too, in order to keep them in sync.

Avatar

Correct answer by
Level 2

**UPDATE #2**

 

I decided to go ahead and work out the `rep:glob` string, so it ended up being much neater and easier to read:

 

{
    "scripts": [
        "create group test-fragments-editors with path /home/groups/forms",
        "set ACL on /content/dam/formsanddocuments/<project>\n   remove * for forms-users\n  deny jcr:all for forms-users restriction(rep:glob,/<fragments_root>)\n    allow jcr:read,crx:replicate for forms-users restriction(rep:glob,/<fragments_root>)\n    allow jcr:all for test-fragments-editors restriction(rep:glob,/<fragments_root>)\nend",
        "set ACL on /content/forms/af/<project>\n   remove * for forms-users\n  deny jcr:all for forms-users restriction(rep:glob,/<fragments_root>)\n    allow jcr:read,crx:replicate for forms-users restriction(rep:glob,/<fragments_root>)\n    allow jcr:all restriction(rep:glob,/<fragments_root>)for test-fragments-editors\nend""
    ]
}

 

 

Notes:

* this creates a rep:policy node under the <project> node that in turn has rep:restrictions nodes under the allow/deny children of the ACL that restricts the effects of the allow/deny to only the <fragments_root> and its descendants

* this also means that a new fragments directory created under the <fragments_root> will automatically inherit the parent ACL

* added the crx:replicate permission, otherwise a form that included a fragment that had never been replicated would not successfully replicate

 

One question I have (perhaps @Vijay_Katoch you could answer this?), is it safe to create user groups under the /home/groups/forms path or is that a path that might get blown away with an Adaptive Forms update? Since it's a repoinit script, we're probably safe anyway as long as that directory exists, because the group will get created on script install and server restart, but it never hurts to ask.

 

EDIT: I'm marking this as the Correct Reply since it solves my problem. I welcome feedback to improve it.

Avatar

Level 1
Level 1

One further update - I had to reorganize the script one more time because there appears to be a bug in the Sling Repoinit Script Parser. The short version is that the parser did not respect the order of deny-allow-allow defined in the "set ACL..." statements. And as anyone who has spent more than 10 minutes working with AEM ACL's knows, order is important

 

I have requested access to Sling's Jira board in order to submit an issue, but in the meantime, the fix was to put each ACL on a separate line.

 

{
    "scripts": [
        "create group test-fragments-editors with path /home/groups/forms",
        "set ACL on /content/dam/formsanddocuments/<project>\n   remove * for forms-users\nend",
        "set ACL on /content/dam/formsanddocuments/<project>\n   deny jcr:all for forms-users restriction(rep:glob,/<fragments_root>)\nend",
        "set ACL on /content/dam/formsanddocuments/<project>\n    allow jcr:read,crx:replicate for forms-users restriction(rep:glob,/<fragments_root>)\nend",
        "set ACL on /content/dam/formsanddocuments/<project>\n   allow jcr:all for test-fragments-editors restriction(rep:glob,/<fragments_root>)\nend",
        ...
    ]
}

 

As I understand it, the parser treats each individual line as a standalone script. I confirmed that this worked for my use case. This issue certainly may be a case of working as expected, but it walks and quacks like a bug in my mind, given how important order is to ACL management.