| | 1 | = Fine grained permissions |
| | 2 | [[PageOutline(2-5, Contents, floated)]] |
| | 3 | [[TracGuideToc]] |
| | 4 | |
| | 5 | There is a general mechanism in place that allows custom **permission policies** to grant or deny any action on any Trac resource, or even specific versions of a resource. |
| | 6 | |
| | 7 | That mechanism is `authz_policy`, which is an optional module in `tracopt.perm.authz_policy.*`, so it is installed by default. It can be activated via the //Plugins// panel in the Trac administration module. |
| | 8 | |
| | 9 | == Permission Policies |
| | 10 | |
| | 11 | A great diversity of permission policies can be implemented and Trac comes with a few examples. |
| | 12 | |
| | 13 | The active policies are determined by a [TracIni#trac-permission_policies-option configuration setting]: |
| | 14 | |
| | 15 | {{{#!ini |
| | 16 | [trac] |
| | 17 | permission_policies = ReadonlyWikiPolicy, DefaultPermissionPolicy, LegacyAttachmentPolicy |
| | 18 | }}} |
| | 19 | |
| | 20 | * [#ReadonlyWikiPolicy] controls readonly access to wiki pages. |
| | 21 | * !DefaultPermissionPolicy checks for the traditional coarse-grained permissions described in TracPermissions. |
| | 22 | * !LegacyAttachmentPolicy uses the coarse-grained permissions to check permissions on attachments. |
| | 23 | |
| | 24 | Among the optional choices, there is [#AuthzPolicy], a very generic permission policy, based on an Authz-style system. See |
| | 25 | [trac:source:branches/1.2-stable/tracopt/perm/authz_policy.py authz_policy.py] for details. |
| | 26 | |
| | 27 | Another permission policy [#AuthzSourcePolicy], uses the [http://svnbook.red-bean.com/nightly/en/svn.serverconfig.pathbasedauthz.html path-based authorization] defined by Subversion to enforce permissions on the version control system. |
| | 28 | |
| | 29 | See also [trac:source:branches/1.2-stable/sample-plugins/permissions sample-plugins/permissions] for more examples. |
| | 30 | |
| | 31 | === !AuthzPolicy |
| | 32 | ==== Configuration |
| | 33 | * Put a [http://swapoff.org/files/authzpolicy.conf conf] file in a secure location on the server, not readable by users other than the webuser. If the file contains non-ASCII characters, the UTF-8 encoding should be used. |
| | 34 | * Update your `trac.ini`: |
| | 35 | 1. modify the [TracIni#trac-section permission_policies] entry in the `[trac]` section: |
| | 36 | {{{#!ini |
| | 37 | [trac] |
| | 38 | permission_policies = AuthzPolicy, ReadonlyWikiPolicy, DefaultPermissionPolicy, LegacyAttachmentPolicy |
| | 39 | }}} |
| | 40 | 1. add a new `[authz_policy]` section and point the `authz_file` option to the conf file: |
| | 41 | {{{#!ini |
| | 42 | [authz_policy] |
| | 43 | authz_file = /some/trac/env/conf/authzpolicy.conf |
| | 44 | }}} |
| | 45 | 1. enable the plugin through [/admin/general/plugin WebAdmin] or by editing the `[components]` section: |
| | 46 | {{{#!ini |
| | 47 | [components] |
| | 48 | tracopt.perm.authz_policy.* = enabled |
| | 49 | }}} |
| | 50 | |
| | 51 | ==== Usage Notes |
| | 52 | |
| | 53 | Note the order in which permission policies are specified: policies are implemented in the sequence provided and therefore may override earlier policy specifications. |
| | 54 | |
| | 55 | A policy will return either `True`, `False` or `None` for a given permission check. `True` is returned if the policy explicitly grants the permission. `False` is returned if the policy explicitly denies the permission. `None` is returned if the policy is unable to either grant or deny the permission. |
| | 56 | |
| | 57 | NOTE: Only if the return value is `None` will the ''next'' permission policy be consulted. If none of the policies explicitly grants the permission, the final result will be `False`, i.e. permission denied. |
| | 58 | |
| | 59 | The `authzpolicy.conf` file is a `.ini` style configuration file: |
| | 60 | {{{#!ini |
| | 61 | [wiki:PrivatePage@*] |
| | 62 | john = WIKI_VIEW, !WIKI_MODIFY |
| | 63 | jack = WIKI_VIEW |
| | 64 | * = |
| | 65 | }}} |
| | 66 | * Each section of the config is a glob pattern used to match against a Trac resource descriptor. These descriptors are in the form: |
| | 67 | {{{ |
| | 68 | <realm>:<id>@<version>[/<realm>:<id>@<version> ...] |
| | 69 | }}} |
| | 70 | |
| | 71 | Resources are ordered left to right, from parent to child. If any component is inapplicable, `*` is substituted. If the version pattern is not specified explicitly, all versions (`@*`) is added implicitly. Example: Match the WikiStart page: |
| | 72 | {{{#!ini |
| | 73 | [wiki:*] |
| | 74 | [wiki:WikiStart*] |
| | 75 | [wiki:WikiStart@*] |
| | 76 | [wiki:WikiStart] |
| | 77 | }}} |
| | 78 | |
| | 79 | Example: Match the attachment `wiki:WikiStart@117/attachment:FOO.JPG@*` on WikiStart: |
| | 80 | {{{#!ini |
| | 81 | [wiki:*] |
| | 82 | [wiki:WikiStart*] |
| | 83 | [wiki:WikiStart@*] |
| | 84 | [wiki:WikiStart@*/attachment:*] |
| | 85 | [wiki:WikiStart@117/attachment:FOO.JPG] |
| | 86 | }}} |
| | 87 | |
| | 88 | * Sections are checked against the current Trac resource descriptor '''IN ORDER''' of appearance in the configuration file. '''ORDER IS CRITICAL'''. |
| | 89 | |
| | 90 | * Once a section matches, the current username is matched against the keys (usernames) of the section, '''IN ORDER'''. |
| | 91 | * If a key (username) is prefixed with a `@`, it is treated as a group. |
| | 92 | * If a value (permission) is prefixed with a `!`, the permission is denied rather than granted. |
| | 93 | |
| | 94 | The username will match any of 'anonymous', 'authenticated', <username> or '*', using normal Trac permission rules. || '''Note:''' Other groups which are created by user (e.g. by 'adding subjects to groups' on web interface page //Admin / Permissions//) cannot be used. See [trac:ticket:5648 #5648] for details about this missing feature. || |
| | 95 | |
| | 96 | For example, if the `authz_file` contains: |
| | 97 | {{{#!ini |
| | 98 | [wiki:WikiStart@*] |
| | 99 | * = WIKI_VIEW |
| | 100 | |
| | 101 | [wiki:PrivatePage@*] |
| | 102 | john = WIKI_VIEW |
| | 103 | * = !WIKI_VIEW |
| | 104 | }}} |
| | 105 | and the default permissions are set like this: |
| | 106 | {{{ |
| | 107 | john WIKI_VIEW |
| | 108 | jack WIKI_VIEW |
| | 109 | # anonymous has no WIKI_VIEW |
| | 110 | }}} |
| | 111 | |
| | 112 | Then: |
| | 113 | * All versions of WikiStart will be viewable by everybody, including anonymous |
| | 114 | * !PrivatePage will be viewable only by john |
| | 115 | * other pages will be viewable only by john and jack |
| | 116 | |
| | 117 | Groups: |
| | 118 | {{{#!ini |
| | 119 | [groups] |
| | 120 | admins = john, jack |
| | 121 | devs = alice, bob |
| | 122 | |
| | 123 | [wiki:Dev@*] |
| | 124 | @admins = TRAC_ADMIN |
| | 125 | @devs = WIKI_VIEW |
| | 126 | * = |
| | 127 | |
| | 128 | [*] |
| | 129 | @admins = TRAC_ADMIN |
| | 130 | * = |
| | 131 | }}} |
| | 132 | |
| | 133 | Then: |
| | 134 | - everything is blocked (whitelist approach), but |
| | 135 | - admins get all TRAC_ADMIN everywhere and |
| | 136 | - devs can view wiki pages. |
| | 137 | |
| | 138 | Some repository examples (Browse Source specific): |
| | 139 | {{{#!ini |
| | 140 | # A single repository: |
| | 141 | [repository:test_repo@*] |
| | 142 | john = BROWSER_VIEW, FILE_VIEW |
| | 143 | # John has BROWSER_VIEW and FILE_VIEW for the entire test_repo |
| | 144 | |
| | 145 | # The default repository (requires Trac 1.0.2 or later): |
| | 146 | [repository:@*] |
| | 147 | john = BROWSER_VIEW, FILE_VIEW |
| | 148 | # John has BROWSER_VIEW and FILE_VIEW for the entire default repository |
| | 149 | |
| | 150 | # All repositories: |
| | 151 | [repository:*@*] |
| | 152 | jack = BROWSER_VIEW, FILE_VIEW |
| | 153 | # Jack has BROWSER_VIEW and FILE_VIEW for all repositories |
| | 154 | }}} |
| | 155 | |
| | 156 | Very granular repository access: |
| | 157 | {{{#!ini |
| | 158 | # John has BROWSER_VIEW and FILE_VIEW access to trunk/src/some/location/ only |
| | 159 | [repository:test_repo@*/source:trunk/src/some/location/*@*] |
| | 160 | john = BROWSER_VIEW, FILE_VIEW |
| | 161 | |
| | 162 | # John has BROWSER_VIEW and FILE_VIEW access to only revision 1 of all files at trunk/src/some/location only |
| | 163 | [repository:test_repo@*/source:trunk/src/some/location/*@1] |
| | 164 | john = BROWSER_VIEW, FILE_VIEW |
| | 165 | |
| | 166 | # John has BROWSER_VIEW and FILE_VIEW access to all revisions of 'somefile' at trunk/src/some/location only |
| | 167 | [repository:test_repo@*/source:trunk/src/some/location/somefile@*] |
| | 168 | john = BROWSER_VIEW, FILE_VIEW |
| | 169 | |
| | 170 | # John has BROWSER_VIEW and FILE_VIEW access to only revision 1 of 'somefile' at trunk/src/some/location only |
| | 171 | [repository:test_repo@*/source:trunk/src/some/location/somefile@1] |
| | 172 | john = BROWSER_VIEW, FILE_VIEW |
| | 173 | }}} |
| | 174 | |
| | 175 | Note: In order for Timeline to work/visible for John, we must add CHANGESET_VIEW to the above permission list. |
| | 176 | |
| | 177 | ==== Missing Features |
| | 178 | Although possible with the !DefaultPermissionPolicy handling (see Admin panel), fine-grained permissions still miss those grouping features (see [trac:ticket:9573 #9573], [trac:ticket:5648 #5648]). Patches are partially available, see authz_policy.2.patch, part of [trac:ticket:6680 #6680]. |
| | 179 | |
| | 180 | You cannot do the following: |
| | 181 | {{{#!ini |
| | 182 | [groups] |
| | 183 | team1 = a, b, c |
| | 184 | team2 = d, e, f |
| | 185 | team3 = g, h, i |
| | 186 | departmentA = team1, team2 |
| | 187 | }}} |
| | 188 | |
| | 189 | Permission groups are not supported either, so you cannot do the following: |
| | 190 | {{{#!ini |
| | 191 | [groups] |
| | 192 | permission_level_1 = WIKI_VIEW, TICKET_VIEW |
| | 193 | permission_level_2 = permission_level_1, WIKI_MODIFY, TICKET_MODIFY |
| | 194 | [*] |
| | 195 | @team1 = permission_level_1 |
| | 196 | @team2 = permission_level_2 |
| | 197 | @team3 = permission_level_2, TICKET_CREATE |
| | 198 | }}} |
| | 199 | |
| | 200 | === !AuthzSourcePolicy (mod_authz_svn-like permission policy) #AuthzSourcePolicy |
| | 201 | |
| | 202 | `AuthzSourcePolicy` can be used for restricting access to the repository. Granular permission control needs a definition file, which is the one used by Subversion's mod_authz_svn. |
| | 203 | More information about this file format and about its usage in Subversion is available in the [http://svnbook.red-bean.com/en/1.7/svn.serverconfig.pathbasedauthz.html Path-Based Authorization] section in the Server Configuration chapter of the svn book. |
| | 204 | |
| | 205 | Example: |
| | 206 | {{{#!ini |
| | 207 | [/] |
| | 208 | * = r |
| | 209 | |
| | 210 | [/branches/calc/bug-142] |
| | 211 | harry = rw |
| | 212 | sally = r |
| | 213 | |
| | 214 | [/branches/calc/bug-142/secret] |
| | 215 | harry = |
| | 216 | }}} |
| | 217 | |
| | 218 | * '''/''' = ''Everyone has read access by default'' |
| | 219 | * '''/branches/calc/bug-142''' = ''harry has read/write access, sally read only'' |
| | 220 | * '''/branches/calc/bug-142/secret''' = ''harry has no access, sally has read access (inherited as a sub folder permission)'' |
| | 221 | |
| | 222 | ==== Trac Configuration |
| | 223 | |
| | 224 | To activate granular permissions you __must__ specify the {{{authz_file}}} option in the `[svn]` section of trac.ini. If this option is set to null or not specified, the permissions will not be used. |
| | 225 | |
| | 226 | {{{#!ini |
| | 227 | [svn] |
| | 228 | authz_file = /path/to/svnaccessfile |
| | 229 | }}} |
| | 230 | |
| | 231 | If you want to support the use of the `[`''modulename''`:/`''some''`/`''path''`]` syntax within the `authz_file`, add: |
| | 232 | |
| | 233 | {{{#!ini |
| | 234 | authz_module_name = modulename |
| | 235 | }}} |
| | 236 | |
| | 237 | where ''modulename'' refers to the same repository indicated by the `<name>.dir` entry in the `[repositories]` section. As an example, if the `somemodule.dir` entry in the `[repositories]` section is `/srv/active/svn/somemodule`, that would yield the following: |
| | 238 | |
| | 239 | {{{ #!ini |
| | 240 | [svn] |
| | 241 | authz_file = /path/to/svnaccessfile |
| | 242 | authz_module_name = somemodule |
| | 243 | ... |
| | 244 | [repositories] |
| | 245 | somemodule.dir = /srv/active/svn/somemodule |
| | 246 | }}} |
| | 247 | |
| | 248 | where the svn access file, {{{/path/to/svnaccessfile}}}, contains entries such as {{{[somemodule:/some/path]}}}. |
| | 249 | |
| | 250 | '''Note:''' Usernames inside the Authz file __must__ be the same as those used inside trac. |
| | 251 | |
| | 252 | As of version 0.12, make sure you have ''!AuthzSourcePolicy'' included in the permission_policies list in trac.ini, otherwise the authz permissions file will be ignored. |
| | 253 | |
| | 254 | {{{#!ini |
| | 255 | [trac] |
| | 256 | permission_policies = AuthzSourcePolicy, ReadonlyWikiPolicy, DefaultPermissionPolicy, LegacyAttachmentPolicy |
| | 257 | }}} |
| | 258 | |
| | 259 | ==== Subversion Configuration |
| | 260 | |
| | 261 | The same access file is typically applied to the corresponding Subversion repository using an Apache directive like this: |
| | 262 | {{{#!apache |
| | 263 | <Location /repos> |
| | 264 | DAV svn |
| | 265 | SVNParentPath /usr/local/svn |
| | 266 | |
| | 267 | # our access control policy |
| | 268 | AuthzSVNAccessFile /path/to/svnaccessfile |
| | 269 | </Location> |
| | 270 | }}} |
| | 271 | |
| | 272 | For information about how to restrict access to entire projects in a multiple project environment see [trac:wiki:TracMultipleProjectsSVNAccess]. |
| | 273 | |
| | 274 | === ReadonlyWikiPolicy |
| | 275 | |
| | 276 | Since 1.1.2, the read-only attribute of wiki pages is enabled and enforced when `ReadonlyWikiPolicy` is in the list of active permission policies. The default for new Trac installations in 1.1.2 and later is: |
| | 277 | {{{ |
| | 278 | [trac] |
| | 279 | permission_policies = ReadonlyWikiPolicy, |
| | 280 | DefaultPermissionPolicy, |
| | 281 | LegacyAttachmentPolicy |
| | 282 | }}} |
| | 283 | |
| | 284 | When upgrading from earlier versions of Trac, `ReadonlyWikiPolicy` will be appended to the list of `permission_policies` when upgrading the environment, provided that `permission_policies` has the default value. If any non-default `permission_polices` are active, `ReadonlyWikiPolicy` **will need to be manually added** to the list. A message will be echoed to the console when upgrading the environment, indicating if any action needs to be taken. |
| | 285 | |
| | 286 | **!ReadonlyWikiPolicy must be listed //before// !DefaultPermissionPolicy**. The latter returns `True` to allow modify, delete or rename actions when the user has the respective `WIKI_*` permission, without consideration for the read-only attribute. |
| | 287 | |
| | 288 | The `ReadonlyWikiPolicy` returns `False` to deny modify, delete and rename actions on wiki pages when the page has the read-only attribute set and the user does not have `WIKI_ADMIN`, regardless of `WIKI_MODIFY`, `WIKI_DELETE` and `WIKI_RENAME` permissions. It returns `None` for all other cases. |
| | 289 | |
| | 290 | When active, the [#AuthzPolicy] should therefore come before `ReadonlyWikiPolicy`, allowing it to grant or deny the actions on individual resources, which is the usual ordering for `AuthzPolicy` in the `permission_policies` list. |
| | 291 | {{{ |
| | 292 | [trac] |
| | 293 | permission_policies = AuthzPolicy, |
| | 294 | ReadonlyWikiPolicy, |
| | 295 | DefaultPermissionPolicy, |
| | 296 | LegacyAttachmentPolicy |
| | 297 | }}} |
| | 298 | |
| | 299 | The placement of [#AuthzSourcePolicy] relative to `ReadonlyWikiPolicy` does not matter since they don't perform checks on the same realms. |
| | 300 | |
| | 301 | For all other permission policies, the user will need to decide the proper ordering. Generally, if the permission policy should be capable of overriding the check performed by `ReadonlyWikiPolicy`, it should come before `ReadonlyWikiPolicy` in the list. If the `ReadonlyWikiPolicy` should override the check performed by another permission policy, as is the case for `DefaultPermissionPolicy`, then `ReadonlyWikiPolicy` should come first. |
| | 302 | |
| | 303 | == Debugging permissions |
| | 304 | In trac.ini set: |
| | 305 | {{{#!ini |
| | 306 | [logging] |
| | 307 | log_file = trac.log |
| | 308 | log_level = DEBUG |
| | 309 | log_type = file |
| | 310 | }}} |
| | 311 | |
| | 312 | Display the trac.log to understand what checks are being performed: |
| | 313 | {{{#!sh |
| | 314 | tail -n 0 -f log/trac.log | egrep '\[perm\]|\[authz_policy\]' |
| | 315 | }}} |
| | 316 | |
| | 317 | See the sourced documentation of the plugin for more info. |
| | 318 | |
| | 319 | ---- |
| | 320 | See also: TracPermissions, |
| | 321 | [http://trac-hacks.org/wiki/FineGrainedPageAuthzEditorPlugin TracHacks:FineGrainedPageAuthzEditorPlugin] for a simple editor plugin. |