Access Control Lists

Document created by resplin Employee on Jun 6, 2015
Version 1Show Document
  • View in full screen mode

Obsolete Pages{{Obsolete}}

The official documentation is at: http://docs.alfresco.com



Authorization2.22.9


Status


Currently the schema changes are in 2.2 (and also merged into HEAD / 2.9.0C_dev) and AVM ACLs have moved to the new model.
The updated schema also supports the old ACL style for the DM world which will be updated at a later date.




Introduction


The implementation of access control lists is being refactored. Documentation for the initial version can be found here Access Control Lists V1.



The previous version relied heavily on caching of permission evaluations. At evaluation time, the implementation could use the cache immediately, or during the evaluation of a permission on a node as it walked the node's ancestors checking permissions, stopping as soon as a cached result resolved the permission request.



Changing a permission caused the cache to be flushed and to start from cold. A more complex flushing strategy could be used and the cache structure could be improved. We could also prefer to cache Read related permissions and prefer to cache permissions based on authority type ('all' preferred to 'groups' preferred to 'users'). However, this general approach can suffer in very large installations when the cache hit may be poor due to the number of documents found in a search, where those documents are in the repository (and how permissions are cached for the node's ancestors), the size of the cache (cache miss), and how the access sequence evicts entries from the cache (cache churn). Any node with uncached permissions requires a get of permission details on the node which may go to the parent node, when the first cache hit could take place. As well as the cache of permission evaluations, this relies on the hibernate cache of ACLs and parent information for good performance. There is no way to include permission checks in a query or easily find all nodes that someone can read.



The goals are:


  • to produce a more performant implementation, particularly for enforcing ACLs in the AVM repository
  • include the potential for permission enforcement at query time (rather than post query)
  • include the potential for permission enforcement on the DB at query time
  • provide a generic pattern for other concepts that may be inherited from a node, such as rules, categories, ...
  • minimise the impact of setting permissions
  • assign well known ACLs to a node regardless of node location




Requirements


The requirements are:


  • to remove any need to find the parent of a node at permission evaluation time;
    • in the AVM repo there are many parents and finding the parents of a node is more costly;
  • An object has a single look up to find the flattened ACLs that apply to it
  • to support ACL objects in their own right;
    • Then an ACL for many items could be managed in well known place
    • This could make applying permission changes very fast as this type of ACL would not be inherited(if permission changes do not trigger copy on write versioning)
    • Move and copy are fast as no ACL assignments need to be untangled (moving a folder from one inherited context to another)
    • Move and copy are fast as the ACLs are as set (and not from an inherited context which needs to evaluated and folded)
  • to support versioning for ACLs by default;
    • there may be support for unversioned changes to propagate changes to old versions of a document - this is a reasonable option for performance reasons if versioning would cause copy on write that is of no interest (if versioning is of no interest)
    • that updates to ACLs can imply a new version of a file or folder in the AVM repo;
  • support to explain permission and display effective permissions for a node
    • Why authority X is denied or allowed permission Y for ACL Z
    • How is ACL Z made up? (What ACLs are folded, what is redefined, etc)
  • to still have good performance when applying permission changes to children
    • particularly if versioning of ACLs is not required
  • ideally to apply ACLs at query time and remove/improve post-search enforcement of permissions
    • This may have consistency issues with indexes maintained in the background.



And also extend what we have now to support:


  • explicitly declared permission object which can be shared by nodes, regardless of inheritance;
  • support permissions that apply to a node but are not inherited to children;
    • The permissions for a home folder may be different from those inherited to its children
  • distinguish: shared inherited ACLs, shared inheritable ACLs, shared ACLs and object specific ACLs.
  • use auditable names for arguments to specify which method arguments should be used for permission checks and not just position (all public APIs have suitable annotations)
  • support a more complex permission evaluation context (so permissions could be type sensitive)
    • User can create nodes a given type (e.g. create files but not folders)
  • Any deny denies and any allow allows in the configuration
  • Move global permissions into the DB

Implementation


  • Attributes identify IDs of ACL objects
    • EffectiveACL - Shared ACL id (Shared ACL)
    • InheritedACL - Shared ACL id (Shared ACL)
      • Indexed as ACL
      • Supports deny and allow
      • Inherited ACL can be different from the one that applies to this object
    • SpecificACL - Shared ACL id (Unshared ACL)
      • Change is cheap as not inherited.
      • Only supports allow (removal of all inherited ACLs is the only form of deny - easy to query what is allowed as there is no compbination with shared ACLs)




  • New attribute type for the DD
    • ACL




  • ACL
    • Unshared ACL
      • No deny
    • Shared ACL
      • AdHoc ACL - inherited
        • Pick up inherited context
      • WellKnown - does not inherit (an AdHoc ACL may inherit from it?)
        • Independant of inherited context




  • fold all inherited ALCs down so one ACL get can normally answer permission questions
    • Folding is virtual based on ordering in the ACL
    • Efficient read performance and caching
    • Query support against ACLs
    • Few ACL objects compared with the number nodes
      • One defining ACL on each object where ACLs are set
      • A corresponding shared ACL that can be reused on nodes that purely inherit
    • AVM performance could be painful with ACL changes causing versioning
      • Efficient to calculate what needs folding - exisiting can find already folded, new ACLs would have to walk
    • Copy and Move are potentially complex operations - bith should use context
    • Link does not carry permissions as this can introduce security holes




  • In DB table
    • Auto versioning in the implementation.
    • Tidy up?




  • For inherited permission need to know which node is the owner of the ACL (it can only be changed there or ot needs to be over ridden in an interveening node). Defining ACL and position resolve this.




  • Adding a new ACL requires a hierarchy walk to find the dependancies
    • changing an existing one is not so bad
    • may be reduced in scope as not all nodes below any given node will inherit ACLs.




  • PermissionService
    • add support fo hasPermisison based on ACL ID 
    • NodeRef impl should get the ACL id and apply
    • Find which ACLs grant an authority a given permission
      • Can be used to incorporate permission evaluation into queries or for post filtering
    • Extended evaluation context
  • On create
    • Set the ACL behaviour from the parent
  • On link
    • No action - this would be a security hole - If I can link then I can create my own folder with any permissions - link to something and have any permission I like. If I have permission to change permission then I can do whatever I like (such as change how permissions are inherited)

Issues


  • If we relax any transactional behaviour when do permissions apply? If we enforce them at query time, the ACL references in the index may be out of date. If they are effective immediately we would have to post filter. We may need to support both.




  • Embedding permission checking in the AVNService implementation
    • removes easy configuration (which a few people have altered).
    • no unprotected service to use in other services (e.g. set acl must have write attribute permission - so the permissions set on the service layer are not the end of the story - and it can not be made to be so).
    • Probably need to be able to support an unprotected service somehow for these cases.
    • Permission evaluated at each part of the path and not just at the end differs from current path lookup
      • Configurable?
      • API to access by specific version ID and version independent ID.
      • Evaluation of path permissions as navigated will mean there is route of query to evaluate simple paths against the node service.




  • Multiple inheritance of permissions
    • NO
    • AVM has no primary parent which we use now to restrict ACL inheritance
    • Permissions and inheritance set at creation time (taken from the parent). Link leaves things unchanged.
    • On the new folder we could apply permissions to all children - and if we had that right set the permissions to be inherited via some other route.
    • ACLs can be used to determine the permission inheritance route when there are multiple paths as they store inherited from.




  • When should/might permission changes be applied to old versions in the AVM world? (by default they would not be). In the DM world permissions apply to the current version - permissions are not versioned but apply to a NodeRef. Changing permission on historical items could be done via branching. Unversioned ACLs would offer performance advantages when changed.




  • Do we keep the link between permissions and types and aspects?




  • Check the behaviour with snapshots and restore - does an ACL change get auto versioned as it changes - separate from AVM snap shotting and versioning as the change on the attribute of a node governs this?




  • Migrate existing ACLs
    • In code repo walk and set




  • More complex UI for ACL management is required - although the current implementation will expose the same API




  • Are object level permissions required at all?




  • Assigning ACLs GUIDS may allow us to build cross repository ACL support into a lucene index.
    • Aux index for ACLs - query which ACLs apply - restrict to just read
    • Restrict query against ACL ID in larger query
    • GUID avoids ACL ID cache from many repos when building an uber index
    • ACL index can be more up-to-date than the big index
    • ACL changes do not require a big reindex
    • At odds with ACL versioning
      • ACL version independant ID would resolve (this could be the GUID)
    • Large scale document index with ACLs that could do in query or post filter evaluation of read access with low impact subindex for changing read permissions even when ACLs are versioned. Assuming the latest ACLs apply to the index 'as soon as possible'.




  • Copy should probably create new inherited ACL entries to avoid loosing implied scope of inheritance. Move should do the same (Yes). This avoids implementing copy on write but more importantly makes dependency management much easier. Yes.




  • Unlink may not be cheap - it could remove the current inheritance route - should this remove the inherited ACLs or transform them to defined ....




  • This does not address property specific or type/aspect specific ACLs.
    • Read access at the property level would have to be folded into the query




  • Authority ids may be deleted/changed
    • Individual ACEs could have an active flag - then it is possible to keep entries (which may later be auto assigned to someone else)
    • Making an ACE inactive should not cause versioning - and applies historically
    • Same for replacing an authority (which we should also support)
      • Could also support aliasing
      • user name implies group memberships and aliases




  • Version on will potentially cause many new versions of AVM objects as ACLs are changed
    • Split object to ACL mapping into a dedicated table
    • use OID to evaluate permissions
    • caching and query based look up (not hibernate object hydration)
    • ACL changes can be committed to one table as a bulk update/insert.




  • Members can include node local aces
    • Have to add attributes to manage
    • A node with node local permissions will have two ACLs - one for the node and one to be inherited by children if required.

Schema


  • alf_acl
    • type - int - enum - DEFINING, SHARED, FIXED, GLOBAL (only one of these for global permissions) and OLD.
    • id - long - id for this acl entry - unique for each acl (including versions of the same acl)
    • version - hibernate optimistic locking
    • latest - boolean - is this the latest version of the ACL identified by the acl_id
    • acl_id - string guide - version independent id - can be used to link to an ACL where the latest acl should always be applied (eg including acl references in an index). Also used to the store the name of well-known, FIXED acls.
    • inherited_acl - long - when creating a new node beneath one with this ACL what ACL to assign - support for a shared acl with the uninherited bits taken out.
    • is_versioned
    • inherits - does this acl inherit changes from above




  • alf_authority
    • id - long
    • authority - string
    • version - long




  • alf_authority_alias
    • alias - long
    • authority - long




  • alf_permission
    • type_qname - type/aspect QName as a string
    • name - string
    • id
    • version




  • alf_ace
    • permission - long
    • authority - long
    • allow - boolean (true for allow, false for deny)
    • id
    • authority_deleted - boolean (used to make aces for a removed authority inactive without reversioning)
    • version
    • context
    • applies - enum - OBJECT, OBJECT+CHILDREN, CHILDREN - may also be limited by context




  • alf_ace_context
    • id
    • class_context - QName - applies to objects of this type/aspect
    • property_context - QName - only applies to the named property
    • kvp_context

QName - applies to this type/aspect/property
-QName - applies if not this type/aspect/property
QName~ - applies to this class and all sub types
-QName~ does not apply to this class or its subtypes
Support () and no prefice + prefix and - prefix as lucene, ~ for sub type matching
Exclude for read related at the start




  • alf_acl_members
    • acl - id
    • ace - id
    • position



ACLs contain all related ACES in order - the order governs which ones are hidden etc.


Some Use Cases


  1. No objects have ACLS
    • No ACLs are added to objects as created
    • Only global permissions apply to objects




  1. No objects have ACLS
  2. Add the first inherited ACL with inherited ACEs
    • cascade update all children to use this ACL




  1. No objects have ACLS
  2. Add the first inherited ACL with inherited ACEs
  3. Add another ACE to this ACL (or delete an ACE)
    • ACL versions
    • cascade update refs to the new version




  1. No objects have ACLS
  2. Add the first inherited ACL with inherited ACEs
  3. Add new inherited ACL below
    • Current inherited ACL is on the node
    • Create new ACL
    • fold in inherited ACL
    • reference it
    • cascade updates
    • create dependacy entry




  1. insert acl between existing ACLS
    • as above but also fold into any existing acls found and cascade down
    • update dependancies




  1. Add the first shared ACL
    • cascade update all children to use this ACL




  1. Move a node
    • scan all children and decide what to do
      • Shared acls are copied as is (but thier children may have different behaviour so you have to look)
      • create new contextual acls as required
        • Eager copy




  1. Copy a node
    • as above




  1. Add a new inherited ACE to an existing ACL
  2. Delete an existing inherited acl
    • creates new version of the acl
    • cascade apply this change
      • update any direct use
      • update any acls that fold in this acl and as a result change (it may be there is no net effect)
      • update the use of these dependant acls that have new versions




  1. link in another parent
    • fill in the changes, work out the damage and which acls have reversioned - update refs to updated acls
    • conflict for multiple inheritance
    • mark effective - collision ??




  1. unlink
    • similar to link




  1. Add an ACL to a node that did not have one
    • cascade apply, fold and update references




  1. Remove an ACL
    • Find affected nodes and re-assign an acl




  1. delete auhtority
    • mark ace's invalid




  1. Add an object specific ace
    • ACL version for the object moves on (no other acls are affected)




  1. Remove an object specific ace

Attachments

    Outcomes