Friday, May 29, 2015

JackRabbit Access Control

While researching JackRabbit Access Control I struggled with a lot of new concepts then I found this article is very useful, one thing left for me is to read it patiently

Summary: TBC




The original source: http://wiki.apache.org/jackrabbit/AccessControl

The 'cached' version of source:

Basic privileges:

  • jcr:read The privilege to retrieve a node and get its properties and their values.
  • jcr:modifyProperties The privilege to create, remove and modify the values of the properties of a node.
  • jcr:addChildNodes The privilege to create child nodes of a node.
  • jcr:removeNode The privilege to remove a node.
  • jcr:removeChildNodes The privilege to remove child nodes of a node.
  • jcr:write An aggregate privilege that contains: jcr:readjcr:modifyPropertiesjcr:addChildNodesjcr:removeNodejcr:removeChildNodes
  • jcr:all An aggregate privilege that contains all available permissions, including jcr:readjcr:write and the advanced permssions.

Resource-based ACLs

Advantages:
  • fully supported by the JCR API / specification
  • very widely available ACL model (eg. file systems)
  • simple resource inheritance
  • default mechanism in Jackrabbit, no configuration needed
Disadvantages:
  • cannot assign ACLs to non-existent nodes
  • cumbersome when many users need un-groupable ACLs on a few resources (e.g. "subscriptions"), lots of ACL entries per resource
  • permissions are stored right inside the content (can be cumbersome for backups, etc.)

Resource-based ACLs are stored per resource/node in a special child node rep:policy. This one will have a list of rep:GrantACE child nodes (usually named allowallow0,...) for grant access control entries and rep:DenyACE child nodes (usually named denydeny0,...) for deny access control entries.
Each ACE node has a rep:principalName STRING property pointing to the user or group this ACE belongs to, and a rep:privileges NAME multi-value property, containing all the privileges of this ACE.

Example for your examination (for both cases: Resource-based, and Principal-based)



AccessControlManager aMgr = session.getAccessControlManager();

// create a privilege set with jcr:all
Privilege[] privileges = new Privilege[] { aMgr.privilegeFromName(Privilege.JCR_ALL) };
AccessControlList acl;
try {
    // get first applicable policy (for nodes w/o a policy)
    acl = aMgr.getApplicablePolicies(path).nextAccessControlPolicy();
} catch (NoSuchElementException e) {
    // else node already has a policy, get that one
    acl = aMgr.getPolicies(path)[0];
}
// remove all existing entries
for (AccessControlEntry e : acl.getAccessControlEntries()) {
    acl.removeAccessControlEntry(e);
}
// add a new one for the special "everyone" principal
acl.addAccessControlEntry(EveryonePrincipal.getInstance(), privileges);

// the policy must be re-set
aMgr.setPolicy(path, acl);

// and the session must be saved for the changes to be applied
session.save();


Principal-based ACLs

Advantages:
  • permissions can be assigned to non-existent nodes
  • permissions are stored separately from the content (good for content replication, backup etc.)
  • good for having many users with un-groupable ACLs (e.g. "subscriptions"); resources don't get filled up with ACL entries
Disadvantages:
  • additional Jackrabbit API has to be used for setting ACLs
  • modeling resource inheritance requires more ACLs than resource-based

An access control list (rep:ACL) is stored for each user and group (this is transparent, currently it's mirroring the users's home path at /rep:accesscontrol//rep:policy/). This consists of entries (rep:ACE), which are either allow (rep:GrantACE) or deny (rep:DenyACE) entries.
The rep:ACE nodetype (used by both resource- and principal-based ACLs) defines the following two properties for principal-based usage. These exact same names need to be used as restrictions when using the Jackrabbit API (JackrabbitAccessControlList.addEntry()):
  • rep:nodePath defines the (base) path of a subtree the ACL applies to (mandatory, PATH property)
  • rep:glob defines a glob pattern to restrict the subtree, both child nodes & properties (only a path matching is done) (optional, STRING property)
For the glob pattern, see http://jackrabbit.apache.org/api/2.2/org/apache/jackrabbit/core/security/authorization/GlobPattern.html (NodePath is the rep:nodePath and restriction is the rep:glob).
// usual entry point into the Jackrabbit API
JackrabbitSession js = (JackrabbitSession) session;

// get user/principal for whom to read/set ACLs

// Note: the ACL security API works using Java Principals as high-level abstraction and does not
// assume the users are actually stored in the JCR with the Jackrabbit UserManagement; an example
// are external users provided by a custom LoginModule via LDAP
PrincipalManager pMgr = js.getPrincipalManager();
Principal principal = pMgr.getPrincipal(session.getUserID());

// alternatively: get the current user as Authorizable from the user management
// (there is a one-to-one mapping between Authorizables and Principals)
User user = ((User) js.getUserManager().getAuthorizable(session.getUserID()));
Principal principal = user.getPrincipal();

// get the Jackrabbit access control manager
JackrabbitAccessControlManager acMgr = (JackrabbitAccessControlManager) session.getAccessControlManager();

JackrabbitAccessControlPolicy[] ps = acMgr.getPolicies(principal); // or getApplicablePolicies()
JackrabbitAccessControlList list = (JackrabbitAccessControlList) ps[0];

// list entries
JackrabbitAccessControlEntry[] entries = (JackrabbitAccessControlEntry[]) list.getAccessControlEntries();
JackrabbitAccessControlEntry entry = entries[0];

// remove entry
list.removeAccessControlEntry(entry);

// add entry
Privilege[] privileges = new Privileges[] { acMgr.privilegeFromName(Privilege.JCR_READ) };
Map restrictions = new HashMap();
ValueFactory vf = session.getValueFactory();
restrictions.put("rep:nodePath", vf.createValue("/some/path", PropertyType.PATH));
restrictions.put("rep:glob", vf.createValue("*"));
list.addEntry(principal, privileges, true /* allow or deny */, restrictions);

// reorder entries
list.orderBefore(entry, entry2);

// finally set policy again & save
acMgr.setPolicy(list.getPath(), list);
session.save();
























Digital Inspiration Technology Guide

Change the world with your passion