The following concepts are crucial to a full understanding of
Veil2
:
This looks like a lot to understand, but you don't need to grasp
it all at once. Once you fully understand privileges and scopes, the rest can be dealt with as the
need arises. Few applications will need all of the features
provided by Veil2
, and you can probably ignore
the stuff you don't think you need.
Privileges are the atomic units of access control, limiting
access to specific data or operations. By convention, most
privileges are named “<action>
<object>
”. Actions will include:
Objects will usually be the names of tables and, for
execute
actions, the names of specific pieces
of functionality. Note that Veil2
takes no
notice of privilege names, using only the
privilege_id
. It is up to the implementation
to ensure that each privilege is used in a manner consistent
with its name.
A typical privilege might be select parties
which we could assume would allow select access to the
parties
table. Note that every privilege
assigned in Veil2
is assigned with a specific
scope, which is based on the context of the role assignment of the role providing that privilege.
A Veil2
-based security system is likely to
have tens or hundreds of distinct privileges.
A scope describes the applicability of a privilege. Scopes are mostly based upon existing relationships in your data.
Note that for every scope, there is an equivalent security context.
A scope may apply to an organization, a department, a project, or whatever you wish. Having a privilege in the scope of one department would presumably give you access rights to data for that department. It would not give you access to equivalent data for other departments.
Some scopes will allow access to large subsets of data, and some to very small subsets. We refer to this as the scope level. A scope that is very restrictive is considered a low-level scope, and one that is not, is a high-level scope. When we talk about scope promotion, this is always from a lower level to a higher level, which is to say that the scope becomes less restrictive, and likely to return a larger set of data.
One scope that is particularly low-level is personal scope.
This limits access to data that specifically relates to the
accessor (privilege holder). So if user X
has the select user
privilege in personal
scope, they will be able to see their own
users
record. Whether they can see other
users
records will depend on whether they
have the select users
privilege in any other
scopes.
Roles exist to manage collections of privileges. Because privileges apply at such a low level, managing access by assigning individual privileges is untenable. Instead we manage groups of privileges through roles. Privileges are assigned to roles, and roles are assigned to users. See role assignments; security contexts; and scope promotion, for information on how each privilege's scope is managed.
To make roles more flexible, we allow roles to be assigned to other roles. We call this role-mapping. This allows us to create low-level functional roles that have the privileges necessary to perform a specific low-level task, and we assign these roles to higher-level user roles which can then be assigned to users. By doing this, we minimize the number of different roles that we need to be able to assign to users.
Typical functional roles might include: view
order
, create order
,
approve order
, etc. These function level
roles might then be assigned to user roles such as
customer service rep
, customer
service manager
, product manager
,
etc. Typically you would only assign user level roles to users.
As the roles themselves do not care whether they are functional or user level, there is no limit to how deeply role to role mappings may be nested. This can be useful when you want to create a user-level role that combines the abilities of 2 or more existing user-level roles.
Veil2
does not care how roles are mapped to
each other, in fact, you can map Role A
to
Role B
and then Role B
to
Role A
, and Veil2
will
handle it just fine; it will just mean that the two roles are
equivalent - which is hardly useful. You may want to implement
some policies around this for your own system.
One of the possible use-cases for Veil2
is
to provide Virtual
Private Databases in a SaaS
environment. As such, it is possible that different clients
of such a service might want different user-level roles, and
different mappings between them and the base function-level
roles.
If you don't need this, you can skip ahead. Although
Veil2
provides this as a feature, you don't
have to use it and it is not enabled by default.
In Veil2
, each role to role mapping is done
within a specific mapping context
. The
default mapping context
is global, which
means that that role mapping applies to all users. By
changing this value we can make role mappings apply at
different context levels. Typically, we would set this to
operate at the context of a specific SaaS client, so that
users for each client would be able to define their own roles
and role to role mappings.
More on the implementation of this can be found here.
Users are assigned roles in a
number of ways, and Veil2
places no limits on
the mechanisms that an implementation may choose to use.
Assignments may be explicit, implicit or even a combination of
the two.
An explicit role assignment would consist of a record associating a role with the user being assigned the role, in a specific context (see security contexts below). This record would be for the sole purpose of assigning the role. This is what makes it explicit.
Implicit role assignments can be made in a number of ways. In
Veil2
each user, by default, is assigned the
personal
context
role, in their own personal context
as described below.
This is done by Veil2
itself, and is not the
result of any record relating the role to the user. Note that
although the role is assigned by default, it has no privileges. What personal
context
allows is up to your implementation.
Other forms of implicit role assignment will be through existing
data relationships. For instance, we might want project team
members to have certain privileges to the data for their
projects. This would be done through their assignment to the
project as a team member. It is possible that such a membership
record would have an explicit role associated with it, but it is
equally possible that “membership” is implied
simply by the existence of a team_member
record linking the user and the project. In such a case we
would create a team member
role, and the
assignment of this role to team members would be implicit.
More details on this can be found here.
A security context (or more usually just
context
) is the user-facing equivalent to a
scope. Where scopes apply
at the level of individual privileges, contexts apply to the user
and the user experience. Specifically, we talk about contexts
as they apply to:
role assignments;
Each role that is assigned to a user, whether implicitly or explicitly, is assigned within a given context.
authentication;
Different users of a Veil2
-based system
may authenticate using different web pages or apps. There
may be completely distinct sets of users in the context of
different corporate clients, with usernames only having to
be unique within the context of each corporation.
As described in contextual role mapping, your role to role mappings may be different for different users. The context that is used for a given session's role mappings is known as the mapping context.
It may be that although a user authenticates in the context of a corporation, their session exists within the context of a specific subdivision of that corporation. The access rights for the user will be determined from this session context. If they are allowed to create sessions in multiple contexts, their access rights may be different in each one.
In Veil2
there is a scope for every context,
and vice versa.
The distinction between scope and context may become clear
when we consider that a role can be assigned in a context that
has no meaning for that role's privileges. Consider a
team-member
role assigned in the context of a
specific project that contains the select
lookups
privilege. This privilege allows the accessor
select-access to lookup data which is not project-specific.
This privilege must operate in a different scope from the
context of its assignment, and so its operating scope will need
to be promoted (see scope promotion below).
It is largely because privileges may apply in different scopes from their role's assignment context, that contexts and scopes have distinct terms. While this may seem to be semantic pedantry, the opportunities for confusion when discussing scopes and contexts are such that the distinction is useful. The author has been there and resents that he will never get those hours back.
Veil2
provides 2 built-in security
contexts:
This is a non-relational context. Privileges assigned in
global context apply without limitation. If you are assigned
a role in global context, all of its privileges will apply in
global scope. If you have been assigned the select
customer
privilege (via a role) in global context,
you will be able to see all customer
records.
Global Context is powerful and dangerous. It is the level of access control provided by traditional security systems and it should be used with great care.
Personal context is an implied context. Each user has an
implicit assignment of the personal context
role in this context.
The personal context is all about the application user, ie the person that is using your application. It applies to data that is about that person. This would include their authentication credentials, contact information, etc. The purpose of the personal context is to give users access to their own data, and no-one else’s. Each user has their own personal context.
Sometimes the context of a role assignment or a session is not entirely appropriate for all of its purposes. In these cases, promotion is necessary.
There are 2 distinct situations where promotion occurs:
Privileges may give access to rows in a table, or to specific functionality. Often, a privilege that is needed for a particular role, will apply to an object that exists outside of the context of the role assignment. In such cases, the privilege must be promoted from the context of its assignment to apply in a higher-level scope.
Consider a role,
CSR
, that has been assigned to a user in
customer context
for customer
Z
. This hypothetical role assignment is supposed to
give the user the ability to manage customer
Z
and no other customer. Among the hypothetical
privileges for this role are:
select customer
;update customer
; ...
;select lookups
.
If we assume that select lookups
gives the
user the ability to view all lookup data, we can see that it
doesn’t really apply to the customer
context
. It is not related to customer-specific
data. In fact it should apply the same regardless of who we
might be a CSR
for. This privilege should
be applied in the global scope, but it has been assigned in
the customer context
for customer
Z
.
The context for the role assignment makes no sense for this
privilege, so it must be promoted to a higher-level scope. In
this case, the scope would be that of the global
context
.
As another example consider that a role that has been assigned
in project context
provides the
select department
privilege to view the
department details of the department that owns the project.
The department details cannot be viewed in project scope,
because projects are lower-level things: the department owns
the project and not the other way around. The solution is to
promote the select department
privilege to
operate in department scope. Note that if the select
project
privilege were promoted in the same way, it
would allow the user to view all projects for the department.
The level of promotion required for each privilege is specific to the object that the privilege exists to protect. So, each privilege identifies its target scope level. If the privilege is being assigned, via a role assignment, in a lower-level context, then promotion to the higher target scope level will automatically be performed when the user's privileges are first loaded.
The mapping context that we use for contextual role mapping is determined from our session context by promotion.
If the session context is not at the scope level of our target mapping context scope, a superior scope will be used based on the scope hierarchy. Note that global scope is considered the highest level/most superior scope.
Each accessor (database user) is associated with a specific context within which they authenticate. Typically, this context would represent the organization they work for. When authenticating an accessor, their authentication context must be provided along with their username or other identifier.
What this means is that usernames, etc do not have to be globally unique, but only unique within each authentication context.
If you don't need this, you can choose to allow all accessors to authenticate within the same context, usually the global context.
As described in Contextual Role Mapping above, the role names and role to role mappings that an accessor sees may depend on their authentication context.
More information on this, with examples, can be found here.
When a user authenticates, they begin a session, and this session
has a context. The session context determines what data the
user can see, as though the user is logged in to that context.
Often the session context will be the same as the authentication
context, but Veil2
does not require this.
For example, consider that our authentication context is at the level of a corporation (so usernames must be unique within the entire corporation), but that we log in to the web-site for a subdivision. Our authentication context would be the corporation context, and the session context would be the subdivision context.
The context of a user's session will determine the access rights for that session. Role assignments in contexts that are unrelated to the session context will be ignored.