Prev  Up  Next
Chapter 4. Veil2 Concepts  Home  Chapter 6. How Difficult Is This?

Veil2 is a collection of database objects, written in C and SQL, that provides an implementation of roles, privileges, contexts, scopes and session management that can be used to secure your database with relatively little custom implementation work.

It links to your database through functions, triggers and foreign keys, and provides fast, tested mechanisms to identify, load and test a user's privileges in various scopes.

It is important to realize at this point that Veil2 is not a complete application or a product: it cannot be used stand-alone and can only be integrated into your database by careful work on your part. You will need to define the links between Veil2 and your database schema, and you will need to provide Veil2 with customized functions and views to make this integration work.

To aid in this, Veil2 allows user-provided views and functions to take precedence over the built-in system-provided ones. This mechanism aims to provide maximum flexibility while still allowing Veil2 to be distributed as a PostgreSQL extension. This means that future Veil2 bug-fixes and upgrades can be easily applied to your database without breaking your customizations.

There is various documentation to help you with this:

You should familiarize yourself with at least this document and the demos before starting out on your implementation.

Veil2 works by:

  • ensuring the database knows which user is connected;
  • providing a set of contextual privileges to each user;
  • providing a fast means of testing a user's privileges;
  • individually securing each accessible relation using privilege tests.

What this means is that when Alice tries to select the user record for Bob, Alice will only see that record if she has been assigned the necessary privilege to view Bob's user record in an appropriate scope. As each user's privilege assignments will be different, each user will see a different subset of data.

The following sections provide more detail on each of the above list items.

Veil2 provides session management functions for both dedicated and shared database connections. It is up to you or your application to ensure that the session protocols are followed. If they are not, the user will have access to no data at all, or access to data based on another user's access rights.

By calling the appropriate session management functions with appropriate authentication tokens, a Veil2 session will be created. This causes session parameters to be set up in secure temporary tables from which they can be quickly retrieved. These session parameters include session privileges with one record for each scope in which the user has privileges.

The set of privileges in each scope is stored in a single bitmap. This is a space-efficient array of numbered bits, with each bit indicating the presence or absence of a privilege. Tests for the presence of a privilege in a bitmap are very fast.

As stated above, the set of privileges in each scope is stored in a bitmap, and tests for the presence of a privilege in the bitmap are very fast. The security rules for a relation will typically be defined something like this (from the veil2_demo extension):

alter table demo.projects enable row level security;

create policy projects__select
    on demo.projects
   for select
 using (   veil2.i_have_global_priv(25)
        or veil2.i_have_priv_in_scope(25, 3, corp_id)
        or veil2.i_have_priv_in_scope(25, 4, org_id)
        or veil2.i_have_priv_in_scope(25, 5, project_id));

Each of the test functions is checking whether the user has the privilege, select projects (privilege 25), to view the current record. Tests are made in global scope, then corp scope (scope type 3) of the owning corp, then org scope (scope type 4) of the owning org, and finally in project scope (scope type 5) of the project itself. Each of these tests causes a different bitmap in the users session privileges to be checked.

Although having so many tests performed for each record returned might seem like a significant overhead, in fact it is very small compared with the cost of retrieving the record in the first place and will often be effectively unmeasurable.

Note that you should not rely solely on your VPD (Virtual Private Database) implementation to limit the number of records returned from queries to your users. Your application should be constructing where-clauses that only return records that your user is entitled to see. That is, your Veil2 implementation should act as a final back-stop safety check and not as a (hidden) part of your system's functionality.

There are 2 reasons for this:

  1. performance;

    Relying on Veil2 to filter unsuitable records means that your where-clauses are essentially incomplete, which in turn means that the RDBMS has not been given all of the information that it needs in order to best optimize your queries.

    Furthermore, if Veil2 is filtering-out records from the result-set then we are unnecessarily retrieving those records, and are having to process them in order to determine their unsuitability. This would be a large and unnecessary overhead.

  2. security.

    If our queries are running slower than they should because Veil2 is having to filter-out unsuitable records, it may be possible for an attacker to use a timing attack to determine the existence of records they are not entitled to see.

    For the truly security conscious, you may want to modify the privilege testing functions so that attempts to view records to which you have no access, result in logs being recorded. Note though, that such logs would be essentially unusable and would become a significant overhead if significant numbers of queries required results to be filtered.

Every table and view is given its own individual security definition. For tables, they will be much as shown above but will include definitions for insert, update and delete as well as select.

Views are secured in a similar way, but with the privilege testing functions defined in the view itself. Sometimes using views can improve the performance of the privilege tests as they can be incorporated more deeply within the view, meaning that the tests do not have to be executed for every row used by the view's query.

Integrating your systems with Veil2 is not a trivial task, but it is straightforward. Once you have understood at least the core concepts, you can simply follow the steps described in the Setting Up A Veil2 Virtual Private Database - Overview section.

The following sections describe the major areas that you will need to address in order to protect an existing system with Veil2. This is intended as an introduction to the process solely in order to give you a feel for what is required.

Prev  Up  Next
Chapter 4. Veil2 Concepts  Home  Chapter 6. How Difficult Is This?