Pyramid ACL » History » Version 1
Thomas Mielke, 10/05/2019 08:10 PM
1 | 1 | Thomas Mielke | # Pyramid ACL |
---|---|---|---|
2 | 1 | Thomas Mielke | |
3 | 1 | Thomas Mielke | {{toc}} |
4 | 1 | Thomas Mielke | |
5 | 1 | Thomas Mielke | ## Background |
6 | 1 | Thomas Mielke | |
7 | 1 | Thomas Mielke | In Pyramid, every traversal resource might have an [Access Conrol List](https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/security.html#assigning-acls-to-your-resource-objects), which is a set of rules containing |
8 | 1 | Thomas Mielke | |
9 | 1 | Thomas Mielke | * an action (Allow, Deny) |
10 | 1 | Thomas Mielke | * a principal (an arbitrary string usually denoting a role, group or userid) |
11 | 1 | Thomas Mielke | * a set of permissions to allow or deny |
12 | 1 | Thomas Mielke | |
13 | 1 | Thomas Mielke | An example of a rule: |
14 | 1 | Thomas Mielke | |
15 | 1 | Thomas Mielke | (Allow, 'some_group', 'some_permission') |
16 | 1 | Thomas Mielke | |
17 | 1 | Thomas Mielke | Every view in pyramid might be [protected](https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/security.html#protecting-views-with-permissions) by a permission. |
18 | 1 | Thomas Mielke | The permission is tested against the principals of the current web user, when the view is entered (after traversal and view lookup). |
19 | 1 | Thomas Mielke | |
20 | 1 | Thomas Mielke | ## Overview |
21 | 1 | Thomas Mielke | |
22 | 1 | Thomas Mielke | In Portal we have two different levels of Access Roles: |
23 | 1 | Thomas Mielke | |
24 | 1 | Thomas Mielke | * global web user roles |
25 | 1 | Thomas Mielke | * instance level object roles |
26 | 1 | Thomas Mielke | |
27 | 1 | Thomas Mielke | The names of the permissions should reflect the action of the web user (e.g. 'edit_artist') and should be unique, if possible. |
28 | 1 | Thomas Mielke | The only exception is the permission 'authenticated', which is granted for web users after login and might be used for all views, which should be accessible for authenticated web users in general. |
29 | 1 | Thomas Mielke | |
30 | 1 | Thomas Mielke | ## Global Level |
31 | 1 | Thomas Mielke | |
32 | 1 | Thomas Mielke | A web user has one or more roles corresponding to the portal plugins (e.g. licenser for portal.plugin.repertoire). |
33 | 1 | Thomas Mielke | Each plugin should have it's own role to ensure that the web user is only able to use the corresponding parts of the application. |
34 | 1 | Thomas Mielke | |
35 | 1 | Thomas Mielke | ### Persistence |
36 | 1 | Thomas Mielke | |
37 | 1 | Thomas Mielke | The web user roles are persisted in tryton: |
38 | 1 | Thomas Mielke | |
39 | 1 | Thomas Mielke | * WebUserRole (web.user.role) |
40 | 1 | Thomas Mielke | |
41 | 1 | Thomas Mielke | The web user roles are imported via `collection_society.xml`. |
42 | 1 | Thomas Mielke | The imported standard roles are: |
43 | 1 | Thomas Mielke | |
44 | 1 | Thomas Mielke | * licenser (for portal.plugin.repertoire) |
45 | 1 | Thomas Mielke | * licensee (for portal.plugin.events) |
46 | 1 | Thomas Mielke | |
47 | 1 | Thomas Mielke | ### Retrieval |
48 | 1 | Thomas Mielke | |
49 | 1 | Thomas Mielke | The web user roles can be retrieved via the roles method of the WebUser Model: |
50 | 1 | Thomas Mielke | |
51 | 1 | Thomas Mielke | web_user.current_roles(request) |
52 | 1 | Thomas Mielke | |
53 | 1 | Thomas Mielke | For convenience, the list of roles are added as request property: |
54 | 1 | Thomas Mielke | |
55 | 1 | Thomas Mielke | request.roles |
56 | 1 | Thomas Mielke | |
57 | 1 | Thomas Mielke | ### Application |
58 | 1 | Thomas Mielke | |
59 | 1 | Thomas Mielke | The principals are automatically assigned to a web user via [callback](https://docs.pylonsproject.org/projects/pyramid/en/latest/api/authentication.html#pyramid.authentication.AuthTktAuthenticationPolicy) of the [groupfinder](https://docs.pylonsproject.org/projects/pyramid/en/latest/tutorials/wiki/authorization.html#add-users-and-groups) method of WebUser, after the web user has been authenticated. |
60 | 1 | Thomas Mielke | |
61 | 1 | Thomas Mielke | To set permissions on a resource to a principal: |
62 | 1 | Thomas Mielke | |
63 | 1 | Thomas Mielke | class SomeResource(ResourceBase): |
64 | 1 | Thomas Mielke | |
65 | 1 | Thomas Mielke | __acl__ = [ |
66 | 1 | Thomas Mielke | (Allow, '<PRINCIPAL>', ( |
67 | 1 | Thomas Mielke | '<PERMISSION1>', |
68 | 1 | Thomas Mielke | '<PERMISSION2>', |
69 | 1 | Thomas Mielke | ... |
70 | 1 | Thomas Mielke | )), |
71 | 1 | Thomas Mielke | ] |
72 | 1 | Thomas Mielke | |
73 | 1 | Thomas Mielke | To prevent inheritance of ACL from parent resources (e.g. for the main resource of a plugin), add DENY_ALL as the last rule: |
74 | 1 | Thomas Mielke | |
75 | 1 | Thomas Mielke | class SomeResource(ResourceBase): |
76 | 1 | Thomas Mielke | |
77 | 1 | Thomas Mielke | __acl__ = [ |
78 | 1 | Thomas Mielke | ..., |
79 | 1 | Thomas Mielke | DENY_ALL |
80 | 1 | Thomas Mielke | ] |
81 | 1 | Thomas Mielke | |
82 | 1 | Thomas Mielke | ## Instance Level |
83 | 1 | Thomas Mielke | |
84 | 1 | Thomas Mielke | Every web user might take one or more access roles for each acl capable object (e.g. Artist, Release, Creation, Content) via an access control entry. |
85 | 1 | Thomas Mielke | Every access role is associated with a set of permissions to be granted. |
86 | 1 | Thomas Mielke | |
87 | 1 | Thomas Mielke | Additional to the permissions codes used in the pyramid views directly (e.g. view_artist, view_release, etc.), there are permissions to reflect transitive rights for objects down the hierarchy (e.g. view_arist_creations, view_arist_releases). |
88 | 1 | Thomas Mielke | |
89 | 1 | Thomas Mielke | ### Persistence |
90 | 1 | Thomas Mielke | |
91 | 1 | Thomas Mielke | All access related objects are persisted in tryton and assigned to a model via the AccessControlList mixin, see also the [[Databasemodels#ACL|database model]]: |
92 | 1 | Thomas Mielke | |
93 | 1 | Thomas Mielke | * AccessControlEntry (ace) |
94 | 1 | Thomas Mielke | * AccessRole (ace.role) |
95 | 1 | Thomas Mielke | * AccessPermission (ace.permission) |
96 | 1 | Thomas Mielke | |
97 | 1 | Thomas Mielke | The access permissions are imported via `collection_society.xml` and readonly for the tryton client, as the codes of the permissions are hardcoded. |
98 | 1 | Thomas Mielke | The access roles are free to edit and each role might be associated with any set of existing permissions. |
99 | 1 | Thomas Mielke | The names of the access roles should be chosen according to the semantics of the role to be taken. |
100 | 1 | Thomas Mielke | |
101 | 1 | Thomas Mielke | The imported standard roles are: |
102 | 1 | Thomas Mielke | |
103 | 1 | Thomas Mielke | * Administrator (all permissions) |
104 | 1 | Thomas Mielke | * Stakeholder (view related permissions only) |
105 | 1 | Thomas Mielke | |
106 | 1 | Thomas Mielke | ### Retrieval |
107 | 1 | Thomas Mielke | |
108 | 1 | Thomas Mielke | To retrieve permission related information, every acl capable model has two instance methods: |
109 | 1 | Thomas Mielke | |
110 | 1 | Thomas Mielke | * `instance.permits()`: asks the instance, if a web user has a certain permission: |
111 | 1 | Thomas Mielke | |
112 | 1 | Thomas Mielke | instance.permits(web_user, permission_code) |
113 | 1 | Thomas Mielke | |
114 | 1 | Thomas Mielke | * `instance.permissions()`: asks the instance, what permissions a web_user has: |
115 | 1 | Thomas Mielke | |
116 | 1 | Thomas Mielke | instance.permissions(web_user, valid_permission_codes=False) |
117 | 1 | Thomas Mielke | |
118 | 1 | Thomas Mielke | The returned permissions might be constrained to permissions in the list of valid codes to tighten security. |
119 | 1 | Thomas Mielke | |
120 | 1 | Thomas Mielke | An example domain to include transitive permissions: |
121 | 1 | Thomas Mielke | |
122 | 1 | Thomas Mielke | [ |
123 | 1 | Thomas Mielke | 'OR', |
124 | 1 | Thomas Mielke | [ |
125 | 1 | Thomas Mielke | ('acl.web_user', '=', web_user_id), |
126 | 1 | Thomas Mielke | ('acl.roles.permissions.code', '=', '<PERMISSION>') |
127 | 1 | Thomas Mielke | ], [ |
128 | 1 | Thomas Mielke | ('<FIELD>.acl.web_user', '=', web_user_id), |
129 | 1 | Thomas Mielke | ('<FIELD>.acl.roles.permissions.code', '=', '<PERMISSION>'), |
130 | 1 | Thomas Mielke | ] |
131 | 1 | Thomas Mielke | ] |
132 | 1 | Thomas Mielke | |
133 | 1 | Thomas Mielke | ### Application |
134 | 1 | Thomas Mielke | |
135 | 1 | Thomas Mielke | The permissions are set within the `__acl__` method of a resource and bound to the [authenticated userid](https://docs.pylonsproject.org/projects/pyramid/en/latest/api/request.html#pyramid.request.Request.authenticated_userid): |
136 | 1 | Thomas Mielke | |
137 | 1 | Thomas Mielke | class SomeResource(ResourceBase): |
138 | 1 | Thomas Mielke | _permit = ['only', 'allow', 'these', 'permissions'] |
139 | 1 | Thomas Mielke | |
140 | 1 | Thomas Mielke | def __acl__(self): |
141 | 1 | Thomas Mielke | return [ |
142 | 1 | Thomas Mielke | (Allow, self.request.authenticated_userid, |
143 | 1 | Thomas Mielke | <INSTANCE>.permissions(self.request.web_user, self._permit)) |
144 | 1 | Thomas Mielke | ] |