Warning: This article is under deep rewriting. Its content has not been reviewed yet.

Access Control

eXo JCR is a complete implementation of the standard JSR 170: Content Repository for Java TM Technology API, including Level 1, Level 2 and Additional Features as is specified in the JCR Specification.

1 Standard Action Permissions

The JCR specification (JSR 170), does not have many requirements about Access Control. It only requires the implementation of the Session.checkPermission(String absPath, String actions) method. This method checks if a current session has permissions to perform some actions on absPath:

  • absPath : the string representation of a JCR absolute path
  • actions : eXo JCR interprets this string as a comma separated list of individual action names such as the 4 types defined in JSR 170 :
    • add_node : Permission to add a node
    • set_property : Permission to set a property
    • remove : Permission to remove an item (node or property)
    • read : Permission to retrieve a node or read a property value
Examples :

  • session.checkPermission("/Groups/organization", "add_node,set_property") will check if the session is allowed to add a child node to "organization" and to modify its properties. If one the two permissions is denied an AccessDeniedException is thrown.
  • session.checkPermission("/Groups/organization/exo:name", "read,set_property") will check if the session is allowed to read and change the "exo:name" property of the "organization" node.

2 eXo Access Control

The JSR170 specification does not define how permissions are managed or checked. So eXo JCR has implemented its own proprietary extension to manage and check permissions on nodes. In essence, this extension uses an Access Control List (ACL) policy model applied to eXo Organization model (see eXo Platform Organization Service).

2.1 Principal and Identity

At the heart of eXo Access Control, is the notion of the identity concept. Access to JCR is made through sessions acquired against a repository. Sessions can be authenticated through the standard (but optional) repository login mechanism. Each session is associated with a principal. The principal is an authenticated user or group that may act on JCR data. The identity is a string identifying this group or user.

There are 3 reserved identities that have special meanings in eXo JCR:

  • any : represents any authenticated session.
  • __anonim : represents a principal for non authenticated sessions. (No error, it's really "__anonim".)
  • __system : represents a principal for system sessions, typically used for administrative purposes. System session have full access (all permissions) to all nodes; therefore be careful when working with system sessions.

2.2 ACL

An access control list (ACL) is a list of permissions attached to an object. An ACL specifies which users, groups or system processes are granted access to JCR nodes, as well as what operations are allowed to be performed on given objects.

eXo JCR Access Control is based on two facets applied to nodes :

  • Privilegeable : Means that the user or group (also called principal) needs the appropriate privileges to access to this node. The privileges are defined as (positive) permissions that are granted to users or groups.
  • Ownable : The node has an owner. The owner has always full access (all permissions) to the node, independent of the privilegeable facet.

2.2.1 Privilegeable

A privilegeable node defines the permissions required for actions on this node. For this purpose it contains an ACL.

At JCR level, this is implemented by an exo:privilegeable mixin.

<nodeType name="exo:privilegeable" isMixin="true" hasOrderableChildNodes="false" primaryItemName="">
    <propertyDefinitions>
      <propertyDefinition name="exo:permissions" requiredType="Permission" autoCreated="true" mandatory="true"
        onParentVersion="COPY" protected="true" multiple="true">
        <valueConstraints/>  
     </propertyDefinition>        
    </propertyDefinitions>  
</nodeType>

A privilegeable node can have multiple exo:permissions values. The type of these values is the eXo JCR specific type Permission. The Permission type contains a list of ACL.

The possible values are corresponding to JCR standard actions:

  • read: The node or its properties can be read.
  • remove: The node or its properties can be removed.
  • add_node : Child nodes can be added to this node.
  • set_property : The node's properties can be modified, added or removed.

2.2.2 Ownable

An ownable node defines an owner identity. The owner has always full privileges. These privileges are independent of the permissions set by exo:permissions. At JCR level, the ownership is implemented by an exo:owneable mixin. This mixin holds an owner property.

<nodeType name="exo:owneable" isMixin="true" hasOrderableChildNodes="false" primaryItemName="">
    <propertyDefinitions>
      <propertyDefinition name="exo:owner" requiredType="String" autoCreated="true" mandatory="true" onParentVersion="COPY"
        protected="true" multiple="false">
        <valueConstraints/>
      </propertyDefinition>        
    </propertyDefinitions>
</nodeType>

The exo:owner property value contains exactly one identity string value. There might be a long list of different permissions for different identities (user or groups). All permissions are always positive permissions; denials are not possible. When checking for a permission of an action it's therefore perfectly sufficient that the principal of a session belongs to one the groups, to who the concerned action is granted.

2.2.3 ACL Inheritance

In order to grant or deny access to a node, eXo JCR applies a privilege resolving logic at node access time.

If a node is privilegeable, the node's ACL is used exclusively. If the ACL does not match the principal's identity the principal has no access (except if he is the owner of the node).

Non-privilegeable nodes inherit permissions from their parent node. If the parent node isn't privilegeable either, the resolving logic looks further up the node hierarchy and stops with the first privilegeable ancestor of the current node. All nodes potentially inherit from the root node of the workspace (TODO, Sergey, is it the root node of the workspace or the repository?).

The owner of a node is inherited following the same logic: If the node has no owner, the owner information of the closest owneable ancestor is inherited.

(Patrice Version: This inheritance is implemented by browsing up the node's hierarchy. At access time, if the local ACL does not match the current identity, the system looks up into the node's ancestor hierarchy for the first matching ACL.)

Warning: TODO : is this really the first matching ACL, or is it the first ACL ?

2.2.4 Default ACL of the root node

When no matching ACL is found in the ancestor hierarchy, the system may end up looking at the root node's ACL. As ACL are optional, even for the root node, if the root node as no ACL, the following rules are ultimately applied to resolve privileges :

  • __anonim identity (anonymous sessions) is granted READ permission
  • any identity (any authenticated session) is granted all permissions
Warning: TODO : Check those rules. The any rule seems pretty permissive

2.3 Notes

Access Control nodetypes are not extendible
The access control mechanism works for exo:owneable and exo:privilegeable nodetypes only, not for their subtypes! So you can NOT extend those nodetypes.

Autocreation
By default, newly created nodes are neither exo:privilegeable nor exo:owneable but it is possible to configure the repository to auto-create exo:privilegeable or/and exo:owneable thanks to eXo's JCR interceptors extension.

Warning: TODO : Link to an article that explains how this work

OR-based Privilege Inheritance
Note, that eXo's Access Control implementation supports an privilege inheritance that follows a strategy of either...or and has only an ALLOW privilege mechanism (there is no DENY feature). This means that a session is allowed to perform some operation on some node if its identity has an appropriate permission assigned to this node. Only if there is no exo:permission property assigned to the node itself, the permissions of the node's ancestors are used.

2.4 Example

2.4.1 XML Example

In the following example, you see a node named "Politics" which contains two nodes named "Cats" and "Dogs".

These examples are exported from eXo DMS using the "document view" representation of JCR. Each value of a multivalue property is separated by a whitespace, each whitespace is escaped by _x0020_.

<Politics  jcr:primaryType="nt:unstructured" jcr:mixinTypes="exo:owneable exo:datetime exo:privilegeable" exo:dateCreated="2009-10-08T18:02:43.687+02:00" 
exo:dateModified="2009-10-08T18:02:43.703+02:00" 
exo:owner="root" 
exo:permissions="any_x0020_read *:/platform/administrators_x0020_read *:/platform/administrators_x0020_add_node *:/platform/administrators_x0020_set_property *:/platform/administrators_x0020_remove">

<Cats jcr:primaryType="exo:article" 
jcr:mixinTypes="exo:owneable" 
exo:owner="marry" 
exo:summary="The_x0020_secret_x0020_power_x0020_of_x0020_cats_x0020_influences_x0020_the_x0020_leaders_x0020_of_x0020_the_x0020_world." 
exo:text="" exo:title="Cats_x0020_rule_x0020_the_x0020_world" />

<Dogs jcr:primaryType="exo:article" 
jcr:mixinTypes="exo:privilegeable" 
exo:permissions="manager:/organization_x0020_read manager:/organization_x0020_set_property"
exo:summary="Dogs" 
exo:text="" exo:title="Dogs_x0020_are_x0020_friends" />

</Politics>

The "Politics" node is exo:owneable and exo:privilegeable. It has both an exo:owner property and also an exo:permissions property. There is an exo:owner="root" property so that the user root is the owner. In the exo:permissions value you can see the ACL, a list of access controls. In this example the group *:/platform/administrators has all rights on this node (remember that the "*" means any kind of membership/role). Furthermore any has the read permission.

As you can see in the jcr:mixinTypes property the "Cats" node is exo:owneable; hence there is an exo:owner="marry" property so that the user marry is the owner. The "Cats" node is not exo:privilegeable and has no exo:permissions. In this case the inheritance mechanism enters the game: The "Cats" node has the same permissions as "Politics" node.

Finally the "Dogs" node is also a child node of "Politics". This node is not exo:owneable and inherits the owner of the "Politics" node (which is the user root). Otherwise "Dogs" is exo:privilegeable and does therefore have its own exo:permissions. That means only the users having a "manager" role in the group "/organization" and the user "root" have the rights to access this node - all others have no access rights.

2.4.2 Inheritance Examples

Here is an example showing the accessibility of two nodes (to show inheritance) for two sample users named manager and user:

The "+" symbol means that there is a child node "exo:owneable".

acl.GIF

2.5 Java API

eXo JCR's ExtendedNode interface which extends javax.jcr.Node interface provides additional methods for Access Control management.

Method signatureDescription
void setPermissions(Map<String, String[]> permissions)Assigns a set of Permissions to a node
void setPermission(String identity, String[] permission)Assigns some Identity's Permission to a node
void removePermission(String identity)Remove Identity's Permission
void removePermission(String identity, String permission)Remove the specified permission for a particular identity
void clearACL()Clears the current ACL so it becomes default
AccessControlList getACL()Returns the current ACL
void checkPermission(String actions)Checks Permission (AccessDeniedException will be thrown if denied)

The "identity" parameter is the user or group name. The permissions are the literal strings of the standard action permissions (add_node, set_property, remove, read.


Creator: Gennady Azarenkov on 05/26/2007
Copyright (c) 2000-2009. Allright reserved - eXo platform SAS
1.6.13286