authorization and security enforcement
DESCRIPTION
In this session we will look at authorities and permissions and how they are combined to produce an access control list. We will move on to cover ACL inheritance, how and when ACLs are enforced and more general security configuration and customisation. The security configuration for Records Management will be used as an advanced example.TRANSCRIPT
1
Authorization and Security Enforcement
Andy HindSenior Developer, Alfresco
twitter: @andy_hind
2
What’s in the mix?
• Public services • Methods + Context (node, parent, ...)
• Principal• Authorities
• Groups, owner
• Permissions• Read, check out
• ACLs• Enforcement• What operations can I perform?• Configuration• Customisation - RM
3
Public Services
Security Enforcement
• wrapped base services• pre-execution checks
• Can I .... ?• Check with context• PublicServiceAccessService• Much more reliable than using hasPermission
• post-execution checks and filtering
• public-services-context.xml• public-services-security-context.xml
4
Public Services
Security Enforcement
<bean id="NodeService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<list>
<value>org.alfresco.service.cmr.repository.NodeService</value>
</list>
</property>
<property name="target">
<ref bean="nodeService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="NodeService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="NodeService_security"/>
</list>
</property>
</bean>
5
Public Services
Security Enforcement
<bean id="NodeService_security" class="org.alfresco.repo.security.permissions.impl.acegi.MethodSecurityInterceptor">
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
<property name="accessDecisionManager"><ref local="accessDecisionManager"/></property>
<property name="afterInvocationManager"><ref local="afterInvocationManager"/></property>
<property name="objectDefinitionSource">
<value>
org.alfresco.service.cmr.repository.NodeService.getStores=ACL_ALLOW,AFTER_ACL_NODE.sys:base.ReadProperties
org.alfresco.service.cmr.repository.NodeService.createStore=ACL_METHOD.ROLE_ADMINISTRATOR
org.alfresco.service.cmr.repository.NodeService.exists=ACL_ALLOW
org.alfresco.service.cmr.repository.NodeService.getNodeStatus=ACL_NODE.0.sys:base.ReadProperties
org.alfresco.service.cmr.repository.NodeService.getRootNode=ACL_NODE.0.sys:base.ReadProperties
org.alfresco.service.cmr.repository.NodeService.createNode=ACL_NODE.0.sys:base.CreateChildren
...
org.alfresco.service.cmr.repository.NodeService.*=ACL_DENY
</value>
</property>
</bean>
public ChildAssociationRef createNode(
NodeRef parentRef,
QName assocTypeQName,
QName assocQName,
QName nodeTypeQName)
throws InvalidNodeRefException, InvalidTypeException;
6
Public Services
Security Enforcement
<bean id="NodeService_security" class="org.alfresco.repo.security.permissions.impl.acegi.MethodSecurityInterceptor">
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
<property name="accessDecisionManager"><ref local="accessDecisionManager"/></property>
<property name="afterInvocationManager"><ref local="afterInvocationManager"/></property>
<property name="objectDefinitionSource">
<value>
org.alfresco.service.cmr.repository.NodeService.getStores=ACL_ALLOW,AFTER_ACL_NODE.sys:base.ReadProperties
org.alfresco.service.cmr.repository.NodeService.createStore=ACL_METHOD.ROLE_ADMINISTRATOR
org.alfresco.service.cmr.repository.NodeService.exists=ACL_ALLOW
org.alfresco.service.cmr.repository.NodeService.getNodeStatus=ACL_NODE.0.sys:base.ReadProperties
org.alfresco.service.cmr.repository.NodeService.getRootNode=ACL_NODE.0.sys:base.ReadProperties
org.alfresco.service.cmr.repository.NodeService.createNode=ACL_NODE.0.sys:base.CreateChildren
...
org.alfresco.service.cmr.repository.NodeService.*=ACL_DENY
</value>
</property>
</bean>
public ChildAssociationRef createNode(
NodeRef parentRef,
QName assocTypeQName,
QName assocQName,
QName nodeTypeQName)
throws InvalidNodeRefException, InvalidTypeException;
createNode=ACL_NODE.0.sys:base.CreateChildren
7
Public Services
Security Enforcement
<bean id="NodeService_security" class="org.alfresco.repo.security.permissions.impl.acegi.MethodSecurityInterceptor">
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
<property name="accessDecisionManager"><ref local="accessDecisionManager"/></property>
<property name="afterInvocationManager"><ref local="afterInvocationManager"/></property>
<property name="objectDefinitionSource">
<value>
org.alfresco.service.cmr.repository.NodeService.getStores=ACL_ALLOW,AFTER_ACL_NODE.sys:base.ReadProperties
org.alfresco.service.cmr.repository.NodeService.createStore=ACL_METHOD.ROLE_ADMINISTRATOR
org.alfresco.service.cmr.repository.NodeService.exists=ACL_ALLOW
org.alfresco.service.cmr.repository.NodeService.getNodeStatus=ACL_NODE.0.sys:base.ReadProperties
org.alfresco.service.cmr.repository.NodeService.getRootNode=ACL_NODE.0.sys:base.ReadProperties
org.alfresco.service.cmr.repository.NodeService.createNode=ACL_NODE.0.sys:base.CreateChildren
...
org.alfresco.service.cmr.repository.NodeService.*=ACL_DENY
</value>
</property>
</bean>
public ChildAssociationRef createNode(
NodeRef parentRef,
QName assocTypeQName,
QName assocQName,
QName nodeTypeQName)
throws InvalidNodeRefException, InvalidTypeException;
createNode=ACL_NODE.0.sys:base.CreateChildren
public ChildAssociationRef createNode( NodeRef parentRef,
8
Public Services
Security Enforcement
<bean id="NodeService_security" class="org.alfresco.repo.security.permissions.impl.acegi.MethodSecurityInterceptor">
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
<property name="accessDecisionManager"><ref local="accessDecisionManager"/></property>
<property name="afterInvocationManager"><ref local="afterInvocationManager"/></property>
<property name="objectDefinitionSource">
<value>
org.alfresco.service.cmr.repository.NodeService.getStores=ACL_ALLOW,AFTER_ACL_NODE.sys:base.ReadProperties
org.alfresco.service.cmr.repository.NodeService.createStore=ACL_METHOD.ROLE_ADMINISTRATOR
org.alfresco.service.cmr.repository.NodeService.exists=ACL_ALLOW
org.alfresco.service.cmr.repository.NodeService.getNodeStatus=ACL_NODE.0.sys:base.ReadProperties
org.alfresco.service.cmr.repository.NodeService.getRootNode=ACL_NODE.0.sys:base.ReadProperties
org.alfresco.service.cmr.repository.NodeService.createNode=ACL_NODE.0.sys:base.CreateChildren
...
org.alfresco.service.cmr.repository.NodeService.*=ACL_DENY
</value>
</property>
</bean>
public ChildAssociationRef createNode(
NodeRef parentRef,
QName assocTypeQName,
QName assocQName,
QName nodeTypeQName)
throws InvalidNodeRefException, InvalidTypeException;
org.alfresco.service.cmr.repository.NodeService.*=ACL_DENY
9
Authorities
• Principal• userName of the Person matched at log in• andy
• Groups• GROUP_woof
• “Role” • ROLE_ADMINISTRATOR
• Group, configuration• DynamicAuthority interface
• ROLE_OWNER• ROLE_LOCK_OWNER
10
Authorities
Zones
• authorities are in one or more zones• hide groups used as RBAC roles
• APP.DEFAULT• APP.SHARE• APP.RM• AUTH.ALF• AUTH.EXT.<ID>
• Dynamic authorities are not zoned
11
Permissions
Ownable – aspect/permissions/service/dynamic authority
<permissionSet type="cm:ownable" expose="selected">
<!-- Permission control to allow ownership of the node to be taken from others -->
<permissionGroup name="TakeOwnership" requiresType="false" expose="false">
<includePermissionGroup permissionGroup="SetOwner" type="cm:ownable" />
</permissionGroup>
<permissionGroup name="SetOwner" requiresType="false" expose="false"/>
<!-- The low level permission to control setting the owner of a node -->
<permission name="_SetOwner" expose="false" requiresType="false">
<grantedToGroup permissionGroup="SetOwner" />
<requiredPermission on="node" type="sys:base" name="_WriteProperties" />
</permission>
</permissionSet>
12
ACLs
Introduction
• All nodes have an ACL• An ACL applies to the node and ALL of its properties
• Content read and write are special• There are no property level permissions
• One global ACL (context free) – applies to all nodes• An ACL is a list of ACEs• Optionally an ACL inherits ACEs from its primary parent • ACE
• Authority – Permissions – Deny/Allow – (Unused context)
13
ACLs
Example
1
2
3
4 5
6
7 8
9
10 11
12 13
14
14
ACLs
Example
1
2
3
4 5
6
7 8
9
10 11
12 13
14
15
ACLs
Example
1
2
3
4 5
6
7 8
9
10 11
12 13
14
16
ACLs
Example
1
2
3
4 5
6
7 8
9
10 11
12 13
14
17
ACLs
Example
1
2
3
4 5
6
7 8
9
10 11
12 13
14
All – Read – Allow – 0
18
ACLs
Example
1
2
3
4 5
6
7 8
9
10 11
12 13
14
All – Read – Allow – 0
All – Read – Allow – 1
19
ACLs
Example
1
2
3
4 5
6
7 8
9
10 11
12 13
14
All – Read – Allow – 2ROLE_OWNER – All – Allow – 0
GROUP_A – Write – Allow – 0GROUP_A – CreateChildren – Allow – 0
20
ACLs
Example
1
2
3
4 5
6
7 8
9
10 11
12 13
14
All – Read – Allow – 0
All – Read – Allow – 1
All – Read – Allow – 2Andy – All – Allow – 0
Bob – Write – Allow – 0 Bob – WriteContent – Deny – 0
21
Configuration
Back to NodeService security enforcement
• org.alfresco.service.cmr.repository.NodeService.getStores• ACL_ALLOW,AFTER_ACL_NODE.sys:base.ReadProperties
• org.alfresco.service.cmr.repository.NodeService.createStore• ACL_METHOD.ROLE_ADMINISTRATOR
• org.alfresco.service.cmr.repository.NodeService.exists• ACL_ALLOW
• org.alfresco.service.cmr.repository.NodeService.getNodeStatus
• ACL_NODE.0.sys:base.ReadProperties
22
Configuration
Back to NodeService security enforcement (2)
•org.alfresco.service.cmr.repository.NodeService.createNode• ACL_NODE.0.sys:base.CreateChildren
•org.alfresco.service.cmr.repository.NodeService.moveNode• ACL_NODE.0.sys:base.DeleteNode• ACL_NODE.1.sys:base.CreateChildren
•org.alfresco.service.cmr.repository.NodeService.addChild• ACL_NODE.0.sys:base.CreateChildren• ACL_NODE.1.sys:base.ReadProperties
• org.alfresco.service.cmr.repository.NodeService.*• ACL_DENY
23
Configuration
Configuration options
• ACL_METHOD.<authority>• ACL_NODE.<#>.<permission>• ACL_PARENT.<#>.<permission>• ROLE_ . . .• GROUP_ . . .
• AFTER_ACL_NODE.<permission>• AFTER_ACL_PARENT.<permission>
24
History
• 2.2• AVM ACL for every nodes
• 3.0 • DM ACL for every node
•3.2 • RM
• 3.4• Query read improvements• Removed hibernate
• Future• Integrate read evaluation in the query• Read evaluation on the DB
25
Evaluation/Performance
• “system”• Global permissions
• “admin”
• Node ACLs and dynamic authorities• Bulk fetch of node properties
• AuthenticationUtil.runAs()
26
Extension
Common extensions
• Changing existing settings• Adding a new service and protection
• Types and aspects• Related permissions and permission groups• Dynamic authorities• Public service• Public service security configuration
• Replace/extend voting – RM
27
RM
Introduction
• Capabilities (50 +)• CreateModifyDestroyFoldersCapability
• Caveats • Supplementary marking
• Property with a list of allowable values• Authority assigned one or more values• Authority must have one or all matching values to read the record
• Classified records• Hierarchy of security levels
• Also uses normal ACLs
• Adds a new AccessDecisionVoter and related classes• RM.<Policy>.<#>.<#>...• RM_CAP.<Capability>.<#>.<capability>• RM_ALLOW, RM_DENY
28
RM
Modified NodeService protection example
•org.alfresco.service.cmr.repository.NodeService.createNode• ACL_NODE.0.sys:base.CreateChildren,RM.Create.0.3
• Create is a combination of RM capabilities• NodeService.createNode()• NodeService.addChild()• FileFolderService.copy()• FileFolderService.create()
• destination• node copied or linked OR type created• Checking for the CreateChildren permission is not enough
29
RM
Create policy has to consider
• Read access to target for link or copy• File records capability• Create modify destroy folders capability• Declare records in closed folders capability• Create/modify records in cutoff folders capability• Create/modify/destroy fileplan metadata capability• Change or delete references capability
30
Learn Morewiki.alfresco.comforums.alfresco.comtwitter: @AlfrescoECM