create table persons ( person_id integer not null, person_name varchar(80) not null );
create view persons( person_id, person_name) as select person_id, person_name from persons where i_have_personal_priv(10013, person_id);
A query performed on the view will return rows only for those persons where the current user has privilege 10013 (SELECT_PERSONS
). We call the function i_have_personal_priv()
, an access function. Such functions are user-defined, and are used to determine whether the connected user has a specific privilege in any of a number of security contexts (see Security Contexts). The example above is taken from the Veil demo application (The Veil Demo Application) and checks for privilege in the global and personal contexts.
select connect_person('Wilma', 'AuthenticationTokenForWilma');
Prior to connection, or in the event of the connection failing, the session will have no privileges and will probably be unable to see any data. Like access functions, connection functions are user-defined and may be written in any language supported by PostgreSQL.
An example will probably help. Here is a definition of a privileges table and a subset of its data:
create table privileges ( privilege_id integer not null, privilege_name varchar(80) not null ); copy privileges (privilege_id, privilege_name) from stdin; 10001 select_privileges 10002 insert_privileges 10003 update_privileges 10004 delete_privileges . . . 10013 select_persons 10014 insert_persons 10015 update_persons 10016 delete_persons 10017 select_projects 10018 insert_projects 10019 update_projects 10020 delete_projects . . . 10100 can_connect \.
can_connect
privilege would not be able to authenticate using a connection function but this is entirely dependent on the implementation.
select_persons
privilege in the global context, they will be able to select every record in the persons table. Privileges in global context are exactly like database-level privileges: there is no row-level element to them.
select_persons
privilege in only the personal context, you will only be able to select your own persons record. Assignment of privileges in the personal context is often defined implicitly or globally, for all users, rather than granted explicitly to each user. It is likely that everyone should have the same level of access to their own data so it makes little sense to have to explicitly assign the privileges for each individual user.
create view privileges( privilege_id, privilege_name) as select privilege_id, privilege_name from privileges where i_have_global_priv(10001); . . . create view persons( person_id, person_name) as select person_id, person_name from persons where i_have_personal_priv(10013, person_id); . . . create view projects( project_id, project_name) as select project_id, project_name from projects where i_have_project_priv(10017, project_id); . . . create view assignments ( project_id, person_id, role_id) as select project_id, person_id, role_id from assignments where i_have_proj_or_pers_priv(10025, project_id, person_id);
In the privileges
view, we only check for privilege in the global context. This is a look-up view, and should be visible to all authenticated users.
The persons
view checks for privilege in both the global and personal contexts. It takes an extra parameter identifying the person who owns the record. If that person is the same as the connected user, then privileges in the personal context may be checked. If not, only the global context applies.
The projects
view checks global and project contexts. The project context is a relational context. In the demo application, a user gains privileges in the project context through assignments. An assignment is a relationship between a person and a project. Each assignment record has a role. This role describes the set of privileges the assignee (person) has within the project context.
The assignments
view checks all three contexts (global, personal and project). An assignment contains data about a person and a project so privileges may be acquired in either of the relational contexts, or globally.
project-readonly
might contain all of the select_xxx
privileges required to read all project data.A further refinement allows roles to be collections of sub-roles. Defining suitable roles for a system is left as an exercise for the reader.
Next: The Veil API