Virtual Private Database
• Virtual Private Database (VPD) is a database security feature that is
built into an Oracle database server, as opposed to being part of an
application that is accessing the data. The user is only allowed to
see the data they have been given permission to see.
• A Virtual Private Database (VPD) makes the database tables seem
like they belong to one user when multiple users may actually be
using that table.
• The VPD uses a filtering mechanism to filter out rows that do not
match the required authorization of the user.
• VPD is used when the standard object privileges and associated
database roles are insufficient to meet application security
requirements.
• Virtual Private Database is also known as fine graind access
control (FGAC). It allows to define which rows users may have
access to.
• VPD was first introduced in Oracle8i.
Overview of VPD
• A VPD deals with data access
• VPD controls data access at the row or column
level
• Oracle10/11g:
– Fine-grained access control: associate security
policies to database objects
– Application Context: define and access application
or session attributes
– Combining these two features, VPD enables
administrators to define and enforce row-level
access control policies based on session attributes.
Why VPD?
• Security
– Server-enforced security (as opposed to application-enforced).
• Purposes/benefits
– Security requirements necessitate data access be restricted at row or column
level (FGA)
– One database schema serves multiple unrelated groups or entities
• Scalability
– Table Customers contains 1,000 customer records.
– Suppose we want customers to access their own records only.
– Using views, we need to create 1,000 views. Using VPD, it can be done with a
single policy function.
• Simplicity
–
–
–
–
Say, we have a table T and many views are based on T.
Suppose we want to restrict access to some information in T.
Without VPD, all view definitions have to be changed.
Using VPD, it can be done by attaching a policy function to T; as the policy is
enforced in T, the policy is also enforced for all the views that are based on T.
Implementing a VPD Using Views
• View object limits what users can see and do with
existing data: hides columns or rows from users
• CREATE VIEW statement: creates data views
• How does it work?
– When a user accesses a table (or view or synonym)
which is protected by a VPD policy (function),
• The Oracle server invokes the policy function whenever a
logged on user tries to execute a query.
• The policy function returns a predicate, based on session
attributes or database contents.
• The server dynamically rewrites the submitted query by
appending the returned predicate to the WHERE clause.
– The modified SQL query is executed.
Policy Types
• To implement Oracle Virtual Private Database, you must create a
function to generate the dynamic WHERE clause, and a policy to
attach this function to the objects that you want to protect.
• The POLICY_TYPE parameter of the DBMS_RLS.ADD_POLICY
procedure is used to set one of the five policy types:
– STATIC - The return value of the policy function is cached and reused
repeatedly for an individual object. By definition the return value of
the policy function must be static.
– SHARED_STATIC - The same as STATIC but the resulting predicate can
be applied to several objects.
– CONTEXT_SENSITIVE - Used when policy is based around local
application context. The result of the policy function is cached and
reused. The policy function is only executed again when the value of
the application context changes.
– SHARED_CONTEXT_SENSITIVE - The same as CONTEXT_SENSITIVE but
the resulting predicate can be applied to several objects.
– DYNAMIC - The policy function is executed for every SQL statement.
•
•
•
•
Column-Level VPD Policy
In conventional Virtual Private Database the VPD Policy is applied to the whole row. By
default a Column-Level VPD Policy allows you to restrict the rows displayed only if specified
columns are accessed.
GRANT EXECUTE ON dbms_rls TO user;
Create the policy function to restrict access to SAL and COMM columns
if the employee is not part of the department 20.
CREATE OR REPLACE FUNCTION pf_job (oowner IN VARCHAR2, ojname IN VARCHAR2)
RETURN VARCHAR2 AS
con VARCHAR2 (200);
BEGIN
con := 'deptno = 20';
RETURN (con);
END pf_job;
/
-- Apply the policy function to the table.
BEGIN
DBMS_RLS.ADD_POLICY (object_schema => 'scott',
object_name
=> 'emp',
policy_name
=> 'sp_job',
function_schema => 'scott',
policy_function => 'pf_job',
sec_relevant_cols => 'sal,comm');
END;
/
• We see all records if SAL and COMM are not
referenced
SELECT empno, ename, job FROM emp;
• Rows are restricted if SAL or COMM are referenced.
SELECT empno, ename, job, sal, comm FROM emp;
• Remove the policy function from the table.
BEGIN
DBMS_RLS.DROP_POLICY (object_schema
object_name
=> 'emp',
policy_name
=> 'sp_job');
END;
/
=> 'scott',
Column Masking
• Column masking is a simple way to hide you valuable data
from certain users without having to apply encrypt/decrypt
techniques and increase the column width to accommodate
the new string like the old times.
• Column masking behaviour is implemented by using the
"sec_relevant_cols_opt => DBMS_RLS.ALL_ROWS"
parameter. This allows you to display all rows but mask the
values of the specified columns for the restricted rows.
• There are 3 steps for accomplish column masking:
1.
2.
3.
A function to be used by the policy (function policy) created in
next step.
Use dbms_rls package to create the policy.
Assign “exempt access policy” to users to be excluded from
the policy. These users can see all data with no masking.
• Step 1: Create Function Policy
CREATE OR REPLACE
FUNCTION vpd_function (obj_owner IN VARCHAR2, obj_name IN VARCHAR2)
RETURN VARCHAR2
AS
BEGIN
RETURN 'rowid = ''0''';
END vpd_function;
/
• Step 2: Create Policy
BEGIN
DBMS_RLS.ADD_POLICY(object_schema=> 'SCOTT',
object_name=> 'EMP',
policy_name=> 'scott_emp_policy',
function_schema=> 'SYSTEM',
policy_function=> 'vpd_function',
sec_relevant_cols=> 'JOB',
policy_type => DBMS_RLS.SHARED_STATIC,
sec_relevant_cols_opt=> dbms_rls.ALL_ROWS);
END;
/
• Step 3: Exclude Some Users from Policy
– Users who need to see all the data without any masking need to
be granted “exempt access policy”
– Notes:
– Dropping a table that has a policy will drop the policy but not
the function policy.
– Renaming the table will NOT drop the policy or disable it. The
policy will remain active.
– Export/Import will also export/import the policy along with the
table, but will not export/import the function policy.
– When exporting a table under a policy, make sure the user
exporting the table has “exempt access policy” grant, otherwise,
the column under the policy will always be null and column data
will be lost.
• Some Important Views
– dba_policies
– v$vpd_policy
• Using the same policy function as before.
BEGIN
DBMS_RLS.ADD_POLICY (object_schema
=> 'scott',
object_name
=> 'emp',
policy_name
=> 'sp_job',
function_schema
=> 'scott',
policy_function
=> 'pf_job',
sec_relevant_cols => 'sal,comm',
sec_relevant_cols_opt => DBMS_RLS.ALL_ROWS);
END;
/
• All rows are returned but the SAL and COMM values are only
• shown for employees in department 20.
– SELECT empno, ename, job, sal, comm FROM emp;
• Remove the policy function from the table.
BEGIN
DBMS_RLS.DROP_POLICY (object_schema
object_name
=> 'emp',
policy_name
=> 'sp_job');
END;
/
=> 'scott',