Mercurial > p > roundup > code
comparison doc/security.txt @ 910:299f4890427d
documentation reorg post-new-security
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Mon, 29 Jul 2002 23:30:14 +0000 |
| parents | 38a74d1351c5 |
| children | 43ab730ee194 |
comparison
equal
deleted
inserted
replaced
| 909:ef9c759c243e | 910:299f4890427d |
|---|---|
| 1 =================== | 1 =================== |
| 2 Security Mechanisms | 2 Security Mechanisms |
| 3 =================== | 3 =================== |
| 4 | 4 |
| 5 :Version: $Revision: 1.14 $ | 5 :Version: $Revision: 1.15 $ |
| 6 | 6 |
| 7 Current situation | 7 Current situation |
| 8 ================= | 8 ================= |
| 9 | 9 |
| 10 Current logical controls: | 10 Current logical controls: |
| 100 | 100 |
| 101 - much more work to implement | 101 - much more work to implement |
| 102 - most user interfaces have multiple uses which can't be covered by a | 102 - most user interfaces have multiple uses which can't be covered by a |
| 103 single permission | 103 single permission |
| 104 | 104 |
| 105 | |
| 106 Logical control | 105 Logical control |
| 107 --------------- | 106 --------------- |
| 108 | 107 |
| 109 At each point that requires an action to be performed, the security mechanisms | 108 At each point that requires an action to be performed, the security mechanisms |
| 110 are asked if the current user has permission. Since code must call the | 109 are asked if the current user has permission. Since code must call the |
| 120 | 119 |
| 121 - large number of possible permissions that may be defined, possibly | 120 - large number of possible permissions that may be defined, possibly |
| 122 mirroring actual user interface controls. | 121 mirroring actual user interface controls. |
| 123 - access to the hyperdb must be strictly controlled through program code | 122 - access to the hyperdb must be strictly controlled through program code |
| 124 that implements the logical controls. | 123 that implements the logical controls. |
| 125 | |
| 126 | |
| 127 Applying controls to users | |
| 128 ========================== | |
| 129 | |
| 130 Individual assignment of Permission to User is unwieldy. The concept of a | |
| 131 Role, which encompasses several Permissions and may be assigned to many Users, | |
| 132 is quite well developed in many projects. Roundup will take this path, and | |
| 133 allow the multiple assignment of Roles to Users, and multiple Permissions to | |
| 134 Roles. These definitions are not persistent - they're defined when the | |
| 135 application initialises. | |
| 136 | |
| 137 There will be two levels of Permission. The Class level permissions define | |
| 138 logical permissions associated with all nodes of a particular class (or all | |
| 139 classes). The Node level permissions define logical permissions associated | |
| 140 with specific nodes by way of their user-linked properties. | |
| 141 | |
| 142 The security module defines:: | |
| 143 | |
| 144 class Permission: | |
| 145 ''' Defines a Permission with the attributes | |
| 146 - name | |
| 147 - description | |
| 148 - klass (optional) | |
| 149 | |
| 150 The klass may be unset, indicating that this permission is not | |
| 151 locked to a particular hyperdb class. There may be multiple | |
| 152 Permissions for the same name for different classes. | |
| 153 ''' | |
| 154 | |
| 155 class Role: | |
| 156 ''' Defines a Role with the attributes | |
| 157 - name | |
| 158 - description | |
| 159 - permissions | |
| 160 ''' | |
| 161 | |
| 162 class Security: | |
| 163 def __init__(self, db): | |
| 164 ''' Initialise the permission and role stores, and add in the | |
| 165 base roles (for admin user). | |
| 166 ''' | |
| 167 | |
| 168 def getPermission(self, permission, classname=None): | |
| 169 ''' Find the Permission matching the name and for the class, if the | |
| 170 classname is specified. | |
| 171 | |
| 172 Raise ValueError if there is no exact match. | |
| 173 ''' | |
| 174 | |
| 175 def hasPermission(self, permission, userid, classname=None): | |
| 176 ''' Look through all the Roles, and hence Permissions, and see if | |
| 177 "permission" is there for the specified classname. | |
| 178 ''' | |
| 179 | |
| 180 def hasNodePermission(self, classname, nodeid, **propspec): | |
| 181 ''' Check the named properties of the given node to see if the | |
| 182 userid appears in them. If it does, then the user is granted | |
| 183 this permission check. | |
| 184 | |
| 185 'propspec' consists of a set of properties and values that | |
| 186 must be present on the given node for access to be granted. | |
| 187 | |
| 188 If a property is a Link, the value must match the property | |
| 189 value. If a property is a Multilink, the value must appear | |
| 190 in the Multilink list. | |
| 191 ''' | |
| 192 | |
| 193 def addPermission(self, **propspec): | |
| 194 ''' Create a new Permission with the properties defined in | |
| 195 'propspec' | |
| 196 ''' | |
| 197 | |
| 198 def addRole(self, **propspec): | |
| 199 ''' Create a new Role with the properties defined in 'propspec' | |
| 200 ''' | |
| 201 | |
| 202 def addPermissionToRole(self, rolename, permission): | |
| 203 ''' Add the permission to the role's permission list. | |
| 204 | |
| 205 'rolename' is the name of the role to add permission to. | |
| 206 ''' | |
| 207 | |
| 208 Modules such as ``cgi_client.py`` and ``mailgw.py`` define their own | |
| 209 permissions like so (this example is ``cgi_client.py``):: | |
| 210 | |
| 211 def initialiseSecurity(security): | |
| 212 ''' Create some Permissions and Roles on the security object | |
| 213 | |
| 214 This function is directly invoked by security.Security.__init__() | |
| 215 as a part of the Security object instantiation. | |
| 216 ''' | |
| 217 newid = security.addPermission(name="Web Registration", | |
| 218 description="Anonymous users may register through the web") | |
| 219 security.addToRole('Anonymous', newid) | |
| 220 | |
| 221 The instance dbinit module then has in ``open()``:: | |
| 222 | |
| 223 # open the database - it must be modified to init the Security class | |
| 224 # from security.py as db.security | |
| 225 db = Database(instance_config, name) | |
| 226 | |
| 227 # add some extra permissions and associate them with roles | |
| 228 ei = db.security.addPermission(name="Edit", klass="issue", | |
| 229 description="User is allowed to edit issues") | |
| 230 db.security.addPermissionToRole('User', ei) | |
| 231 ai = db.security.addPermission(name="View", klass="issue", | |
| 232 description="User is allowed to access issues") | |
| 233 db.security.addPermissionToRole('User', ai) | |
| 234 | |
| 235 In the dbinit ``init()``:: | |
| 236 | |
| 237 # create the two default users | |
| 238 user.create(username="admin", password=Password(adminpw), | |
| 239 address=instance_config.ADMIN_EMAIL, roles='Admin') | |
| 240 user.create(username="anonymous", roles='Anonymous') | |
| 241 | |
| 242 Then in the code that matters, calls to ``hasPermission`` and | |
| 243 ``hasNodePermission`` are made to determine if the user has permission | |
| 244 to perform some action:: | |
| 245 | |
| 246 if db.security.hasPermission('issue', 'Edit', userid): | |
| 247 # all ok | |
| 248 | |
| 249 if db.security.hasNodePermission('issue', nodeid, assignedto=userid): | |
| 250 # all ok | |
| 251 | |
| 252 Code in the core will make use of these methods, as should code in auditors in | |
| 253 custom templates. The htmltemplate will implement a new tag, ``<require>`` | |
| 254 which has the form:: | |
| 255 | |
| 256 <require permission="name,name,name" assignedto="$userid" status="open"> | |
| 257 HTML to display if the user has the permission. | |
| 258 <else> | |
| 259 HTML to display if the user does not have the permission. | |
| 260 </require> | |
| 261 | |
| 262 where: | |
| 263 | |
| 264 - the permission attribute gives a comma-separated list of permission names. | |
| 265 These are checked in turn using ``hasPermission`` and requires one to | |
| 266 be OK. | |
| 267 - the other attributes are lookups on the node using ``hasNodePermission``. If | |
| 268 the attribute value is "$userid" then the current user's userid is tested. | |
| 269 | |
| 270 Any of these tests must pass or the ``<require>`` check will fail. The section | |
| 271 of html within the side of the ``<else>`` that fails is remove from processing. | |
| 272 | |
| 273 Implementation as shipped | |
| 274 ------------------------- | |
| 275 | |
| 276 A set of Permissions are built in to the security module by default: | |
| 277 | |
| 278 - Edit (everything) | |
| 279 - View (everything) | |
| 280 | |
| 281 The default interfaces define: | |
| 282 | |
| 283 - Web Registration | |
| 284 - Email Registration | |
| 285 | |
| 286 These are hooked into the default Roles: | |
| 287 | |
| 288 - Admin (Edit everything, View everything) | |
| 289 - User () | |
| 290 - Anonymous (Web Registration, Email Registration) | |
| 291 | |
| 292 And finally, the "admin" user gets the "Admin" Role, and the "anonymous" user | |
| 293 gets the "Anonymous" assigned when the database is initialised on installation. | |
| 294 The two default schemas then define: | |
| 295 | |
| 296 - Edit issue, View issue (both) | |
| 297 - Edit file, View file (both) | |
| 298 - Edit msg, View msg (both) | |
| 299 - Edit support, View support (extended only) | |
| 300 | |
| 301 and assign those Permissions to the "User" Role. New users are assigned the | |
| 302 Roles defined in the config file as: | |
| 303 | |
| 304 - NEW_WEB_USER_ROLES | |
| 305 - NEW_EMAIL_USER_ROLES | |
| 306 | |
| 307 | |
| 308 Authentication of Users | |
| 309 ----------------------- | |
| 310 | |
| 311 Users must be authenticated correctly for the above controls to work. This is | |
| 312 not done in the current mail gateway at all. Use of digital signing of | |
| 313 messages could alleviate this problem. | |
| 314 | |
| 315 The exact mechanism of registering the digital signature should be flexible, | |
| 316 with perhaps a level of trust. Users who supply their signature through their | |
| 317 first message into the tracker should be at a lower level of trust to those | |
| 318 who supply their signature to an admin for submission to their user details. | |
| 319 | |
| 320 | |
| 321 Anonymous Users | |
| 322 --------------- | |
| 323 | |
| 324 The "anonymous" user must always exist, and defines the access permissions for | |
| 325 anonymous users. The three ``ANONYMOUS_`` configuration variables are | |
| 326 subsumed by this new functionality. | |
| 327 | 124 |
| 328 | 125 |
| 329 Action | 126 Action |
| 330 ====== | 127 ====== |
| 331 | 128 |
| 358 | 155 |
| 359 - use the new logical control mechanisms (only allowing write | 156 - use the new logical control mechanisms (only allowing write |
| 360 access by admin users, and read-only by everyone else) | 157 access by admin users, and read-only by everyone else) |
| 361 | 158 |
| 362 | 159 |
| 363 Use cases | |
| 364 ========= | |
| 365 | |
| 366 public | |
| 367 end users that can submit bugs, request new features, request support | |
| 368 developer | |
| 369 developers that can fix bugs, implement new features provide support | |
| 370 manager | |
| 371 approvers/managers that can approve new features and signoff bug fixes | |
| 372 admin | |
| 373 administrators that can add users and set user's roles | |
| 374 system | |
| 375 automated request handlers running various report/escalation scripts | |
| 376 privacy | |
| 377 issues that are only visible to some users | |
| 378 |
