Expand my Community achievements bar.

July 31st AEM Gems Webinar: Elevate your AEM development to master the integration of private GitHub repositories within AEM Cloud Manager.
SOLVED

Groups and ACLs for external vendors?

Avatar

Level 2

I have 2 scenarios that require that users be granted read access explicitly before they can access content in AEM.  

We're expecting to run a large number of sites in our authoring environment and authors should by default only see what they've been granted access to so that they're not overwhelmed by content that's not relevant to their experience.  

Secondly, we're allowing vendors to access assets and content, and for security reasons they shouldn't by default see all content that's in the authoring environment.

Currently, the 2 options that appear to be available are to use either the content-authors group or a customization of the mp-* groups.  However, both are based on the contributor group which by default grants read access to jcr_root, then denies specific things.

Is there a group structure that is not based on contributor that supports this concept?  If I deny access to content then allow access to only a specific folder in content, /sites.html/content breaks.  I tried some permutations of rep:readNodes with the same result.  There are a lot of folders in /content by default, something in there must be required by TouchUI to load the interface, but I'm not sure what that is.

Any help would be appreciated.

edit: As a followup, I can't create groups that deny access to everything that isn't the one folder that I want to grant access to because users may be responsible for several sites, or several folders in the DAM, and as such will need to belong to multiple groups that allow access to a different set of folders.  If I deny things explicitly, it will be a maintenance nightmare as new sites or DAM folders are added (every user group would need to be edited to deny access to that new folder, or there may be conflicting permissions when a user is added to multiple groups).

1 Accepted Solution

Avatar

Correct answer by
Level 2

Jörg Hoh wrote...

Hi Jay,

Basically I agree with the documentation, that you shouldn't use "DENY", but there is one big exception to this rule: You should have a group, which grants the minimal applicable permission set. For example you model a group "login only", which only allows to login to AEM, but not to see any regular content (for example denying ALL permissions on /content/* using wildcard ACL). Make sure, that this group is the very frist group in the group list of every user.

And the you can design more groups which allow you to access specific pieces of content. Then the order of these groups does not matter anymore. Then you also don't have to rework the "login only" group, because all subtrees below /content are implicitly covered by the wildcard ACL, so you can create them at will.

(I really though, that this is covered somewhere in the official documentation ...)

kind regards,
Jörg

 

This keeps getting marked as the answer, but the answer really isn't here.

Here's what I'll mark as the answer:

If you're basing everything on the default contributor group (which has read access to everything in the JCR), and the only thing you need to restrict is write access to specific folders, following the official documentation is super easy: simply grant write access anywhere in the JCR that the user needs to be able to modify and boom, you're done.

If however you want to grant read access to only specific branches of a tree, you need to use denies at every level of the tree until you reach a point where everything becomes similar to the point above (i.e. the user can now read/write everything within a particular branch).  

So, for example, say you have hundreds of sites published from your author cluster.  Your authors would be overwhelmed (most likely) if they saw everything.  Maybe you have external vendors managing content for you, and they should only have access on a "need to know basis".  If this is the case, you need to lock down access to /content and /content/dam.  /content/dam is a child of /content (clearly), so if you want to prevent a user from seeing all sites in /sites.html, you need to deny read access to /content, but then you need to grant it back for /content/dam.

The approach then looks like the following:

  1. contributor
    1. deny jcr:read /content rep:glob=/* (deny all read access to all children of /content, but not content itself)
    2. grant jcr:read /content/dam (grant read access back to /content/dam)
    3. deny jcr:readNodes /content/dam rep:glob=/* (now deny access to all children of /content/dam)
    4. Also, you might want to do similar for /apps and /etc/designs, depends on how tightly locked down you want it to be.

Contributor is used as the example base group for most of the Geometrixx samples and provides for the least amount of re-work.  You might want to create a base-group that inherits from contributor to add the denies that I've added above, but you also might not want to have a group that provides full read access to the JCR by default. You now have a basic group with read access to everything except /content, which will cover most of the basic UX features of Touch-UI, but there will probably be explicit things outside that folder structure that the user might have access to but shouldn't.  Also, if Adobe adds extra explicit permissions for contributor in the future, you'll get the benefit of inheriting that for your users.

Now you can create project groups with specific access to things in /content and /content/dam, and those groups should all inherit from contributor.

  1. contributor
    1. geometrixx-media-reviwer
      1. grant jcr:read /content/geometrixx-media
      2. grant jcr:read /content/dam/geometrixx-media
    2. geometrixx-gov-reviewer
      1. grant jcr:read /content/geometrixx-gov
      2. grant jcr:read /content/dam/geometrixx-gov

Now you can assign one or more of these groups to one or more users and they'll then only see things that they're explicitly granted access to.

But wait, my use cases are more complicated, what if my geometrixx-media project also includes some peripheral print design, I want to store my digital assets with my print assets, what do I do?

Then you'll need to push those denies further down one more level and provide a group structure to support it.  For example

  1. contributor
    1. geometrixx-media-users
      1. grant jcr:read /content/dam/geometrixx-media
      2. deny jcr:readNodes /content/dam/geometrixx-media rep:glob=/*
      3. geometrixx-media-reviewers
        1. grant jcr:read /content/dam/geometrixx-media
      4. geometrixx-media-print-reviewers
        1. grant jcr:read /content/dam/geometrixx-media
        2. deny jcr:readNodes /content/dam/geometrixx-media rep:glob=/*
        3. grant jcr:read /content/dam/geometrixx-media/print
      5. geometrixx-media-website-reviewers
        1. grant jcr:read /content/geometrixx-media
        2. grant jcr:read /content/dam/geometrixx-media
        3. deny jcr:readNodes /content/dam/geometrixx-media rep:glob=/*
        4. grant jcr:read /content/dam/geometrixx-media/website

Unfortunately, this is due to the fact that jcr:readProperties doesn't actually do anything without also having jcr:readNodes. (jcr:read is an aggregate of jcr:readProperties and jcr:readNodes).  jcr:readNodes is also badly named, it's not just "readNodes", it's "readThisNodeAndReadAllChildNodes".  There's no way to do this super cleanly, you can't just grant non-recursive jcr:readProperties to a single node to allow someone to see that and nothing else, you need to also grant jcr:readNodes and then deny them on the children in order to access the node itself.

p.s. Good luck granting read access only to things that are necessary to log in.  Those things are liberally spread throughout the JCR, and some things are mixed in with author-accessible content.  For example, there are things in /etc/designs required for rendering Touch-UI, so you can't blanket deny /etc/designs, you need to deny things explicitly, and of course those things can change in the future.  Trying to figure out the "minimum access requirements" to log into AEM is effectively just endless trial and error.

View solution in original post

14 Replies

Avatar

Level 2

I think I've resolved my issue, but it goes against the Documentaion suggestion that only allows be used:

Use Deny sparingly. As far as possible use only Allow.

Using deny can cause unexpected effects if the permissions are applied in a different order than the order expected. If a user is a member of more than one group, the Deny statements from one group may cancel the Allow statement from another group or vice versa. It is hard to keep an overview when this happens and can easily lead to unforeseen results, whereas Allow assignments do not cause such conflicts.

Adobe recommends that you work with Allow rather than Deny see Best Practices.

When a new /content/dam/* or /content/* folder is added I can deny jcr:all to the contributor group, but as above it's possible that ACLs could be read in the wrong order.  So this clearly isn't the ideal.

Avatar

Employee Advisor

Hi Jay,

Basically I agree with the documentation, that you shouldn't use "DENY", but there is one big exception to this rule: You should have a group, which grants the minimal applicable permission set. For example you model a group "login only", which only allows to login to AEM, but not to see any regular content (for example denying ALL permissions on /content/* using wildcard ACL). Make sure, that this group is the very frist group in the group list of every user.

And the you can design more groups which allow you to access specific pieces of content. Then the order of these groups does not matter anymore. Then you also don't have to rework the "login only" group, because all subtrees below /content are implicitly covered by the wildcard ACL, so you can create them at will.

(I really though, that this is covered somewhere in the official documentation ...)

kind regards,
Jörg

Avatar

Level 7

Hello jayproulx,

Please mark resolve this question, so that it shows as resolved.

Thanks

Tuhin

Avatar

Level 2

This issue is not yet resolved, I'll mark it as resolved as soon as I've found a solution to my issue.

Avatar

Level 10

Joerg provided a good answer. Have you implemented his suggestion? What happened?

Avatar

Level 2

Hi Scott,

First of all, the answer is contradictory to the documentation: “Don’t use deny except for a certain group that all users should belong to which should do a wildcard deny”.  I’ve been working on trying to create a group of users by following the documentation and granting only read access where required.  Contributor has been the group that i’ve modeled my access after, however, removing jcr:read from / (and granting jcr:read to /apps and /libs, /etc)  ends up breaking all of the UI’s (sites.html, assets.html etc).

So despite the documentation, I have no choice but to use a wildcard deny on content.  I agree with the documentation, you don’t want to grant access to anything that the user shouldn’t have access to by default, but there doesn’t seem to be a scenario where that’s possible.  The only thing that works is Jörg’s suggested to use a wildcard deny on just /content/*, but what else does that give the user access to that they shouldn’t by default?  What are all of the other paths across the JCR that shouldn’t have read access by default?  The answer leaves us with a working UI but it’s weak when it comes to production access standards.  There’s also no documentation covered in the Security Checklist to cover those scenarios.

So, at the moment I don’t have an answer to the question...

Avatar

Level 2

As an aside, I’m also not receiving email updates when someone replies to this thread (in my inbox or spam), so I replied quickly previously from my phone when I received a satisfaction survey for this thread and saw that there were new replies.

Avatar

Level 2

In addition, there are commonly used folders like /etc/designs that contain a mix of AEM and project specific code.  It’s relatively easy to blanket deny /content/* and /apps/*, but the same doesn’t apply for /etc/designs/* since there are a number of folders in there that are used by the system.  We could deny all and then grant back all of the specific folders, but this sends us down a road where we’re using deny in all circumstances to define the base level of user access.

It seems to me that what we need is (as Jörg mentions above) a basic login group where we can build on top of the permissions as necessary for project specific access.  Is there no such group available out of the box?  Perhaps at least as an ACS download?  My only option at the moment is to build that group via trial and error.

Avatar

Level 10

We will work with the doc team to get this missing piece of information into the docs. As Joerg points out: 

(I really though, that this is covered somewhere in the official documentation ...)

Avatar

Correct answer by
Level 2

Jörg Hoh wrote...

Hi Jay,

Basically I agree with the documentation, that you shouldn't use "DENY", but there is one big exception to this rule: You should have a group, which grants the minimal applicable permission set. For example you model a group "login only", which only allows to login to AEM, but not to see any regular content (for example denying ALL permissions on /content/* using wildcard ACL). Make sure, that this group is the very frist group in the group list of every user.

And the you can design more groups which allow you to access specific pieces of content. Then the order of these groups does not matter anymore. Then you also don't have to rework the "login only" group, because all subtrees below /content are implicitly covered by the wildcard ACL, so you can create them at will.

(I really though, that this is covered somewhere in the official documentation ...)

kind regards,
Jörg

 

This keeps getting marked as the answer, but the answer really isn't here.

Here's what I'll mark as the answer:

If you're basing everything on the default contributor group (which has read access to everything in the JCR), and the only thing you need to restrict is write access to specific folders, following the official documentation is super easy: simply grant write access anywhere in the JCR that the user needs to be able to modify and boom, you're done.

If however you want to grant read access to only specific branches of a tree, you need to use denies at every level of the tree until you reach a point where everything becomes similar to the point above (i.e. the user can now read/write everything within a particular branch).  

So, for example, say you have hundreds of sites published from your author cluster.  Your authors would be overwhelmed (most likely) if they saw everything.  Maybe you have external vendors managing content for you, and they should only have access on a "need to know basis".  If this is the case, you need to lock down access to /content and /content/dam.  /content/dam is a child of /content (clearly), so if you want to prevent a user from seeing all sites in /sites.html, you need to deny read access to /content, but then you need to grant it back for /content/dam.

The approach then looks like the following:

  1. contributor
    1. deny jcr:read /content rep:glob=/* (deny all read access to all children of /content, but not content itself)
    2. grant jcr:read /content/dam (grant read access back to /content/dam)
    3. deny jcr:readNodes /content/dam rep:glob=/* (now deny access to all children of /content/dam)
    4. Also, you might want to do similar for /apps and /etc/designs, depends on how tightly locked down you want it to be.

Contributor is used as the example base group for most of the Geometrixx samples and provides for the least amount of re-work.  You might want to create a base-group that inherits from contributor to add the denies that I've added above, but you also might not want to have a group that provides full read access to the JCR by default. You now have a basic group with read access to everything except /content, which will cover most of the basic UX features of Touch-UI, but there will probably be explicit things outside that folder structure that the user might have access to but shouldn't.  Also, if Adobe adds extra explicit permissions for contributor in the future, you'll get the benefit of inheriting that for your users.

Now you can create project groups with specific access to things in /content and /content/dam, and those groups should all inherit from contributor.

  1. contributor
    1. geometrixx-media-reviwer
      1. grant jcr:read /content/geometrixx-media
      2. grant jcr:read /content/dam/geometrixx-media
    2. geometrixx-gov-reviewer
      1. grant jcr:read /content/geometrixx-gov
      2. grant jcr:read /content/dam/geometrixx-gov

Now you can assign one or more of these groups to one or more users and they'll then only see things that they're explicitly granted access to.

But wait, my use cases are more complicated, what if my geometrixx-media project also includes some peripheral print design, I want to store my digital assets with my print assets, what do I do?

Then you'll need to push those denies further down one more level and provide a group structure to support it.  For example

  1. contributor
    1. geometrixx-media-users
      1. grant jcr:read /content/dam/geometrixx-media
      2. deny jcr:readNodes /content/dam/geometrixx-media rep:glob=/*
      3. geometrixx-media-reviewers
        1. grant jcr:read /content/dam/geometrixx-media
      4. geometrixx-media-print-reviewers
        1. grant jcr:read /content/dam/geometrixx-media
        2. deny jcr:readNodes /content/dam/geometrixx-media rep:glob=/*
        3. grant jcr:read /content/dam/geometrixx-media/print
      5. geometrixx-media-website-reviewers
        1. grant jcr:read /content/geometrixx-media
        2. grant jcr:read /content/dam/geometrixx-media
        3. deny jcr:readNodes /content/dam/geometrixx-media rep:glob=/*
        4. grant jcr:read /content/dam/geometrixx-media/website

Unfortunately, this is due to the fact that jcr:readProperties doesn't actually do anything without also having jcr:readNodes. (jcr:read is an aggregate of jcr:readProperties and jcr:readNodes).  jcr:readNodes is also badly named, it's not just "readNodes", it's "readThisNodeAndReadAllChildNodes".  There's no way to do this super cleanly, you can't just grant non-recursive jcr:readProperties to a single node to allow someone to see that and nothing else, you need to also grant jcr:readNodes and then deny them on the children in order to access the node itself.

p.s. Good luck granting read access only to things that are necessary to log in.  Those things are liberally spread throughout the JCR, and some things are mixed in with author-accessible content.  For example, there are things in /etc/designs required for rendering Touch-UI, so you can't blanket deny /etc/designs, you need to deny things explicitly, and of course those things can change in the future.  Trying to figure out the "minimum access requirements" to log into AEM is effectively just endless trial and error.

Avatar

Level 2

Hi Jay,

I  appreciate your posting and thoroughness you put into it. You explain the basic idea quite well: First have a "deny all" rule (using wildcard ACLs where appropriate) and then give the group permission to the relevant of the repository. To be honest, I haven't had the time to write my posting in such a level of detail, but I am glad you did it :-)

Your approach works fine, but building your complete group structure in a tree-ish way only works well, if you operate on a single tree. But if you want to give customize your UI as well, and therefor you need to apply ACLs elsewhere, you start the perform the same changes to these nodes in multiple groups. For example if you want to remove the useradmin from the Classic UI interface of geometrixx-media-website-reviewers and geometrixx-media-print-reviewers, you might end up changing the ACLs of /libs/cq/security/content/securityadmin in both groups.

Therefor you can build your groups for /content in the way you described, but you should create standalone groups which deal with such content-agnostic things like disabling functionaliy, which is not tied to a special site, but rather on a role.

And regarding the read access only to login: I don't recommend to lock-down the complete /libs and /etc subtrees. But what is a regular supposed to do on a site, where she doesn't have a read or write permission to any content (below /content)? Therefor for the bare minumum give a user read access to /libs and /etc/, and control /apps/mysite, /etc/clientlibs/mysite, /etc/design/mysite and /content.

Jörg

Avatar

Level 2

Jörg Hoh wrote...

Hi Jay,

I  appreciate your posting and thoroughness you put into it. You explain the basic idea quite well: First have a "deny all" rule (using wildcard ACLs where appropriate) and then give the group permission to the relevant of the repository. To be honest, I haven't had the time to write my posting in such a level of detail, but I am glad you did it :-)

Your approach works fine, but building your complete group structure in a tree-ish way only works well, if you operate on a single tree. But if you want to give customize your UI as well, and therefor you need to apply ACLs elsewhere, you start the perform the same changes to these nodes in multiple groups. For example if you want to remove the useradmin from the Classic UI interface of geometrixx-media-website-reviewers and geometrixx-media-print-reviewers, you might end up changing the ACLs of /libs/cq/security/content/securityadmin in both groups.

Therefor you can build your groups for /content in the way you described, but you should create standalone groups which deal with such content-agnostic things like disabling functionaliy, which is not tied to a special site, but rather on a role.

And regarding the read access only to login: I don't recommend to lock-down the complete /libs and /etc subtrees. But what is a regular supposed to do on a site, where she doesn't have a read or write permission to any content (below /content)? Therefor for the bare minumum give a user read access to /libs and /etc/, and control /apps/mysite, /etc/clientlibs/mysite, /etc/design/mysite and /content.

Jörg

 

Yes, we're taking a different approach for customizing TouchUI navigation, we're creating a single, non-inherited (or carefully inherited) group that defines navigation permissions, otherwise we're seeing too many conflicts.  And the scenario I've described above only works when there is an unrestricted node where beyond that point we grant full read access.  You can't restrict a folder inside one of these unrestricted nodes because you'll then run into conflicts if there are multiple groups adding/removing access at that level.

Avatar

Level 1

Hi Jay,

We have a similar requirement.  "a user should not see any folder except one under a path." The approach mentioned by you is the optimal solution.

I tried using deny and rep:glob=/* but the parent folder was still denied, then followed the below post to

AEM: ACL Bug with Restrictions (rep:glob) with Oak | LinkedIn make the folder visible.

But the folder title is not displayed. I think reading the jcr:title property is also denied for the folder. Is there any additional ACL to be added to make the jcr:title readable?