[[TOC]] [wiki:DeveloperGuidelinesS3Framework] | S3AAA = S3 Authentication, Authorization and Accounting = '''Authentication''' is the act of establishing or confirming someone's identity.[[BR]] '''Authorization''' is the concept of allowing access to resources only to those permitted to use them.[[BR]] '''Accounting''' refers to the tracking of user actions - an audit trail. == Overview == AAA functions for S3 are implemented in the {{{modules/s3/s3aaa.py}}} module. This module extends the web2py Auth class as AuthS3 (Authentication), and defines additional classes for role management, access control and audit. ||'''Component'''||'''Location'''||'''Function'''|| ||AuthS3||modules/s3/s3aaa.py||Authentication, Login|| ||S3Permission||modules/s3/s3aaa.py||Authorization of Access, ACLs|| ||S3Audit||modules/s3/s3aaa.py||Data access logging, audit trail|| ||S3RoleManager||modules/s3/s3aaa.py||RESTful method to manage roles and ACLs|| ||Admin controllers||controllers/admin.py||User Management, role management|| Epydocs can be found here: [http://pub.nursix.org/eden/s3] == Authentication == The AuthS3 class extends web2py's Auth class, which is documented here: * http://www.web2py.com/book/default/chapter/08#Authentication NB Whilst the Authentication functions of the Auth class are only slightly modified, the Authorisation & Audit functions are not used at all, so ignore those when working with Sahana. - ''more coming...'' === Current user === - ''coming soon...'' === Interactive Login === - ''coming soon...'' === HTTP Basic Authentication === It is possible to access privileged resources by providing the username/password within each request, rather than the usual method of having the login stored within the session. * http://en.wikipedia.org/wiki/Basic_access_authentication This is done by using the {{{login_bare()}}} method of AuthS3. - ''more coming...'' == Roles == Roles are defined in the {{{auth_group}}} table, which is defined by the {{{AuthS3}}} module (in {{{modules/s3/s3aaa.py}}}).[[BR]] Each role has an ID, a unique name and an optional description. Access permissions are granted to roles, while a user gets permissions by assigning roles to them. Role assignment is stored in the {{{auth_membership}}} table, which is defined by the {{{AuthS3}}} class (in {{{modules/s3/s3aaa.py}}}). At the start of every request, the IDs of all roles of the currently logged-in user are stored as list in {{{session.s3.roles}}} (in {{{models/00_utils.py}}}). In cases where the user logs in during the request (e.g. by HTTP Basic Auth), a refresh of this list is also triggered by the {{{login_bare()}}} method of {{{AuthS3}}}. Roles can be managed in the {{{S3RoleManager}}} graphical interface (Administration menu => User Management => Roles). The following roles are pre-defined in S3 and cannot be changed: ||'''ID'''||'''Name'''||'''Description'''|| ||1||Administrator||system administrator|| ||2||Authenticated||all authenticated users|| ||3||Anonymous||unauthenticated users|| ||4||Editor||data editor|| The first registered user gets the '''Administrator''' role assigned.[[BR]] Users with the Administrator role always have all permissions, and may access all pages in Eden. The Administrator may also manage Users, Roles and ACLs. Users with the '''Editor''' role may access all data with all methods, except they can not manage Users, Roles or ACLs. Every authenticated user gets automatically the '''Authenticated''' role assigned. This role assignment cannot be revoked. == Simple Authorization == Simple authorization means, that - anonymous users have read-only permission - authenticated users have full access - the Administrator may additionally access the user management This is the fallback model wherever there are no ACLs defined. == ACLs == Access Control Lists (ACLs) are bit arrays with each bit representing a permission to access data with a particular method: ||'''Bit'''||'''Value'''||'''Permission'''|| ||auth.permission.CREATE||0x01||may create new records|| ||auth.permission.READ||0x02||may read or list records|| ||auth.permission.UPDATE||0x04||may update existing records|| ||auth.permission.DELETE||0x08||may delete records|| ACLs are combinations of these bits (by bitwise OR), e.g. an ACL with the value 0x06 defines permissions to read and update records, while no permission to add or to delete any records. ACLs are stored per role and request destination in the {{{s3_permission}}} table, which is defined by the {{{S3Permission}}} class (in {{{modules/s3/s3aaa.py}}}). ACLs can be managed by the {{{S3RoleManager}}} graphical interface (Administration menu => User Management => Roles). For every destination (controller/function/table) two ACLs can be defined to apply depending on whether a user owns the record or not: - one ACL for users owning a record (Owner ACL = {{{oacl}}}) - one ACL for any other user not owning the record (User ACL = {{{uacl}}}). If a user owns a record, then the most permissive of the User ACL and the Owner ACL gets applied, otherwise only the User ACL applies. === !OrgAuth === !OrgAuth are security policies which allow multiple organizations using the same instance of Sahana Eden to control who can access their data and with which permissions. The !OrgAuth policies are all based on the following base concepts: A '''person entity''' is a type of records describing business entities which involve one or more individual persons. This can be, e.g., organisations, offices, teams, and of course persons. A '''realm''' of a person entity is the set of all records controlled ("owned") by this entity (="their data"). Which entity gains control over a record can be defined per record type, and even as deployment options. In an organizational structure, a person entity can be a sub-unit ('''organization unit''', OU) of another person entity. E.g. an office can be a sub-unit of an organisation, or a person a sub-unit of a team. In !OrgAuth policies, a user can be assigned a role ''for a realm''. That is, the permissions resulting from this role assignment are limited to the records within the realm - whilst they have no effect outside the realm. !OrgAuth policies 7 and 8 also implement a hierarchy of realms, where the realm of an entity includes the realms of all its OUs. !OrgAuth policy 8 additionally allows the delegation of access rights for a realm to other entities (rather than to particular users), thus facilitating controlled data sharing at the organization level. A detailed description of the !OrgAuth framework can be found here: [wiki:S3AAA/OrgAuth] === Record Ownership === Tables can implement a record ownership by adding two meta fields: ||'''Field name'''||'''Type'''||'''Description'''|| ||owned_by_user||integer (reference auth_user)||ID of the user who owns this record[[BR]](defaults to the ID of the user who created the record)|| ||owned_by_role||integer (reference auth_group)||ID of the group (role) who own the record|| These meta fields are contained in {{{s3_ownerstamp()}}} and also in {{{s3_meta_fields()}}}. A user is considered the ''owner'' of a record if they are either the individual owner of the record (user ID == {{{owned_by_user}}}), '''or''' they are a member of the owner role ({{{owned_by_role}}} in user roles). If a record has '''no owner''', i.e. if both {{{owned_by_user}}} and {{{owned_by_role}}} are '''None''', then all authenticated users are considered the owner of this record. In tables which do not define either of these meta-fields, ownership rules are not applied ({{{uacl}}} only). ''NOTE: you can have both an individual record owner and an owner role for the same record at the same time, where the individual owner doesn't need to have the owner role.'' ==== Session-Ownership ==== For anonymous users we can make the session own the records, so that a user can edit records they've just created, or read their cached feature queries. When using the framework, this happens automatically. For manual DAL calls, this can be set using: {{{ auth.s3_make_session_owner(table, record_id) }}} (This has no effect if the owned_by_user field is set) ==== Ownership vs. Access Permission ==== NOTE: '''Ownership''' for a record and '''access permissions''' on this record are independent from each other! The fact alone that a user owns a record doesn't give him any permissions on that record. He still needs to have a role assigned for which an ACL definition exists which gives him permissions on that table. But that also means that the role which determines the user's ownership of a record, and the role which determines the user's effective access permissions for that record, do not have to be the same (in fact, the ownership-determining role doesn't need to have any permissions on the table at all): the effective permissions would still be applied as per the most permissive role the user is assigned to. Example: Have these things: 1. A role ''OrgX Staff'', which is routinely assigned to staff members of organisation ''X'' 2. A role ''Boss'', which is assigned to all organisation admins (independent of the organisation!) 3. A role ''Clerk'', which is assigned to all helpdesk officers (independent of the organisation!) 4. A record ''Y'' in the table ''aaa_bbbbb'', which has its {{{owned_by_role}}} field set to ''OrgX Staff'' 5. An ACL for the ''aaa_bbbbb'' table, which sets {{{(uacl=CREATE, oacl=ALL)}}} for the ''Boss'' role 6. An ACL for the ''aaa_bbbbb'' table, which sets {{{(uacl=NONE, oacl=READ)}}} for the ''Clerk'' role With this configuration, a user who has the ''OrgX Staff'' role, would own record ''Y''. However, the fact that he owns the record doesn't give him any permission to access it. (Note that there is intentionally no ACL defined on ''aaa_bbbbb'' for role ''OrgX Staff''!) If the user would have both, the ''OrgX Staff'' and the ''Boss'' roles, then he would own the record ''Y'' (as per {{{owned_by_role}}}) and also be permitted to {{{read}}}, {{{update}}} and {{{delete}}} this record (as per ACL for ''Boss''), and additionally, he could add new records to ''aaa_bbbbb''. If instead the user would have the ''OrgX Staff'' and the ''Clerk'' roles, then he would also own the record ''Y'' (as per {{{owned_by_role}}}), but just be permitted to {{{read}}} that record (as per ACL for ''Clerk''). If the user would only be ''Boss'', then he could only create new records in ''aaa_bbbbb'', but could not access record ''Y'' (since that would require ownership of that record). If the user would only be ''Clerk'', then he could not see record ''Y'' at all. And he could not either create new records in ''aaa_bbbbb''. === Restrictions === ACLs can be defined for controllers, and for particular functions inside controllers (Controller ACLs).[[BR]] ACLs can additionally be defined for individual database tables (Table ACLs). ==== System-wide Policy ==== The system-wide permission model is configured as {{{security.policy}}} in deployment_settings in either {{{private/templates/