How Is Relational Security Different?
A relational security implementation differs from the typical access
controls built into an application in a number of ways:
how access rights are
assigned;
where the controls are
implemented;
how access is restricted;
the ease of being able to reason
about the access restrictions;
the comprehensiveness of the
access restrictions.
The Traditional Approach(What Is Relational Security Different From?)
For the purpose of subsequent discussion, we are going to define
a Traditional Application Security approach
below. The terminology in this section is necessarily somewhat
vague as it is a fairly gross generalization of typical
practices. Many existing systems will do better than is
suggested below, but the underlying mechanisms described should
be easily recognizable and familiar.
In traditionally implemented database systems:
The security implementation is entirely in the application
layer.
Since all access to the database is through the application
this is the obvious place to put all access controls.
Application servers provide functionally-rich environments
which would seem to make this the obviously correct, and
possibly the only viable approach.
Access controls are applied to functionality.
Most of the access limitations in a typical system are managed
by simply preventing access to certain functions. Often menu
entries will be greyed-out when you don’t have access rights.
Some access controls will be contextual:
there will be explicit checks to determine whether in the
context of this team/department/organization/customer/whatever
you have the right to perform a specific action.
This is typically still a functional rather than a relational
access control as there is the implied function
do-x-if-I-am-a-member-of-something, rather
than the more general do-x. Often the
general do-x function will be reserved for
administrator use only.
Sometimes such functions will do some moderately sophisticated
relational testing to see whether the user should be allowed
to continue, and this should be considered a relational access
control. That said, this is often an ad-hoc thing, and each
function may have its own rules and its own implementation.
Most access rights are assigned to users explicitly, through
the assignment of roles.
Roles are collections of low-level access rights
(privileges), and each role will typically allow a user to
perform a number of distinct tasks.
Users will typically be explicitly assigned roles, such as
Customer Service Rep (CSR), Product
Manager, Senior CSR, Administrator, etc.
Sometimes these are called rights or privileges but they are
essentially roles.
A user gains access to functionality by being assigned the
appropriate roles.
Implicit access rights are often managed by a lack of
implementation.
There may be some implicit access rights that
all users get, but this default
position is often achieved by simply
not implementing any controls at all in
certain parts of the application. For instance if every
user is expected to be able to see all lookup tables, then
the traditional system will simply not apply
any checks on lookup table access.
The Relational Security Approach
In our
traditional
system, almost all access is determined from explicit assignments
of roles. With a relational security approach we will still
use explicit role assignments, but these will only be part of
the story.
In a relational security model, access rights are managed in
multiple ways:
default role assignments;
Users can be given default roles. This is a little like the
default access rights in our traditional system, but:
they are implemented as explicit access controls, rather
than the more usual lack of access controls;
the set of rights given through default roles can be
changed with time and experience without having to modify
the application.
implicit role assignments;
It may be that we wish to record a user’s membership of a team
as part of our application. We can choose to make that
membership the source of a role assignment. This means that we
do not need to explicitly assign roles to a user: they can
instead be inferred from existing relationships in the data.
explicit role assignments;
This is similar to the traditional system,
but more sophisticated as assignments may be in specific
contexts. What this means is that you may be given the
CSR role in the context of one client, but
not in the context of others, or you may be given that role in
a department context which might give you
access to all clients managed by your department.
inherited role assignments;
If a hierarchy of scopes can be defined, roles assigned in a
given context can also apply in inferior contexts. For
example, if you have been assigned the
Administrator role in the context of a
division within your company, that role may be inherited to
apply at the department level of all departments within the
division.
These mechanisms can be as sophisticated/complex as you need them
to be, but from the user’s perspective they will be unsurprising
and they should therefore be simple to administer.
Where Are Access Controls Implemented In A Relational
Security System?
In our traditional system, all
access controls are managed by the application. Although this
may be a data-driven process, the decision to allow access or
not will often involve factors that are
external to the database: the application
will have to make decisions based upon rules, and those rules
may be, at least partly, hard-coded into the application.
With a relational security mechanism all of
the decision making is made within the database. There will be
no external factors such as hard-coded
access-control rules. There are two distinct types of access
controls that we implement:
on relations (tables and views);
on functions.
Access controls on functions are similar to the access controls
of the traditional system. The difference is that the database
directly provides a decision to the application, rather than
providing some of the base data for the application to make that
decision based on whatever rules were implemented for the
specific case in the specific application.
An application using a relational security system could
determine which menu entries should be greyed-out for a
user in the Project Management menu of
Project X, by executing a query something
like:
select i_have_priv_in_scope('exec pm-menu-item1', 'Project X'),
i_have_priv_in_scope('exec pm-menu-item2', 'Project X'),
i_have_priv_in_scope('exec pm-menu-item3', 'Project X'),
i_have_priv_in_scope('exec pm-menu-item4', 'Project X'),
i_have_priv_in_scope('exec pm-menu-item5', 'Project X'),
i_have_priv_in_scope('exec pm-menu-item6', 'Project X');
This would return true or
false for each menu entry that we are
interested in. Note that the permission tests are contextual:
whether you have permission to execute some project management
function depends on which project you want to apply it to. You
may be able to access different functions in different
projects.
Access controls on relations (tables and views) limit the data
that you may see or manipulate. Just as with access to
functions, this is contextual so that you may see data for some
projects and not for others. What this means is that even if
the application fails to properly limit your access, the
database will act as a backstop. If you have not been given
access to a record, then no matter how you try you will not be
able to see or manipulate it. The fact that different users
may see different data from the same query is why this is
sometimes called a Virtual
Private Database (VPD) implementation.
The application is not off the hook though. The application
should not allow the user to try to do things that will not be
allowed by the database. It should limit the records it tries
to retrieve for the user using well-crafted queries with
where-clauses that request only the data that the user should be
able to see. But if it gets it wrong, little harm will be done.
How Is Access Restricted In A Relational Security
System?
In our traditional system,
access controls are primarily managed by limiting the user’s
access to specific functions, and the restrictions are primarily
implemented in code that runs on the application server. Where
privileges are required for access to specific data,
where-clauses may be dynamically added to
queries based on those privileges or on flags whose values are
based on those privileges.
With a relational security model, access to data is limited
primarily by the database server itself. No application code is
required to limit a user's access to data, the database just
does it. Furthermore the application does not need the
smarts to determine what a user can do. It
can simply ask the database what is allowed. No complex
application code; no surprising access control rules; and no
external factors.
What this means is that all of the access
control rules are built from a common framework using a single
set of guiding principles. Although it is possible to implement
special cases there is rarely any need. This is because the
access control mechanisms are based on the highly flexible
mechanism of privileges within contexts.
Ease of Reasoning
Traditional access control systems are often built piecemeal, or
as an afterthought. Even when there are guiding principles
behind the implementation there are often corner cases that
require special treatment. This means that the security
mechanisms of traditional applications are often difficult to
completely describe. Furthermore since privileges in the
traditional system often imply conditionality, a simple
understanding of privileges is not enough.
By placing all of your access control definitions into a
relational security model, it becomes much easier to describe
and reason about your security implementation. And your
implementation, by virtue of its consistency, is much more
likely to match what your designer intended and your customer
wanted.
Comprehensiveness
Earlier we stated that implicit
access rights, in traditional applications, are often
managed by simply not implementing them. In a relational
security system, every piece of data is protected by the same
underlying mechanism of privilege and scope, which means is that
if something which once was viewed as public data subsequently
needs to be secured, it is simply a matter of changing some
privilege assignments. No code needs to be touched and once the
change has been tested we can be sure that it will apply
throughout the application: there will not be some obscure
screen somewhere that someone created by copy and paste that
gets forgotten and that does not get updated to implement the
new access control.
By having only one fundamental security mechanism, and by
linking it with the data that it is intended to protect, a
relational security system will be more complete and more
robust, and by building this into the database we can ensure
that the same security model applies to all applications
including reports.