Technical Note

Using Virtual Private Database in an Oracle HTML DB Application
Authors: Scott Spendolini (product manager), Sergio Leunissen (senior product manager), and David Knox (chief engineer)
Publication Date: October 2004

Securing an application begins with applying proper access control rules at the database level. One of the ways the Oracle Database helps you implement access control rules is through Fine Grained Access (FGA) control or Virtual Private Database (VPD). In this article, we will look at how an application developed in Oracle HTML DB can take advantage of this feature.

VPD allows you to restrict access to records based on a security policy that you implement in a PL/SQLfunction. The PL/SQL function contructs a WHERE clause based on conditions defined by the security administrator. The function is then registered with the tables or views you want to protect using the built in DBMS_RLS  package. When a query is issued on a protected table or view, VPD effectively appends the string returned from the policy function to the original SQL statement.

This technical note explains an example of using a VPD policy in an HTML DB application.  The instructions assume you have SQL*Plus access to your own database.

Software Requirements

Setting up the Security Administration Schema

To begin, we'll create two schemas; one schema will be our security schema, and the other will be our data schema. The first schema will be used by the security administrator, whose job is to apply the security to our application and data schemas. Note that the SYS user has to grant execute privileges to this schema  on the DBMS_RLS package.

To create the security adminstrator's schema:

  • Connect as SYSTEM
  • Execute the following:
  • CREATE USER vpd_admin IDENTIFIED BY
    akf7d98s2 DEFAULT
    TABLESPACE users TEMPORARY TABLESPACE temp
  • Grant the necessary privileges to perform the steps in this technical note by executing the following:
  • GRANT CREATE SESSION TO vpd_admin;
    GRANT CREATE PROCEDURE TO vpd_admin<>;
    
  • Connect as SYS and grant the security adminstrator necessary privileges needed for registering VPD policies:
  • GRANT EXECUTE ON DBMS_RLS TO vpd_admin;
    

Setting Up the Data Schema

Next, we'll create the schema to store our data.  It is not necessary to separate the PL/SQL and privileges needed to implement the VPD policies into a different schema than the schema that holds the data. It is, however, a good practice. We'll create a copy of the SCOTT.EMP table inside the DATA_SCHEMA.  For testing purposes, SELECT privilege on the newly created emp table will be granted to SCOTT.

To create the data schema:

  • connect as SYSTEM and execute the following:
  • CREATE USER data_schema
    IDENTIFIED BY laskjdf098ksdaf09
    DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp;
    
  • Grant necessary privileges for DATA_SCHEMA to be allowed to create a table by executing the following:
  • GRANT CREATE TABLE TO
    data_schema;
    ALTER USER data_schema QUOTA 1
    m ON "USERS";
    
  • Create a table based on a copy of SCOTT.EMP:
  • CREATE TABLE data_schema.emp AS SELECT * FROM scott.emp;
    
  • Grant SELECT privilge to the SCOTT schema for testing:
  • GRANT SELECT ON data_schema.emp TO scott;
    

Creating the Policy Function

Next, we'll define the access policy as the security administrator.  The policy function will limit the records returned to those owned by the user running a query. The invoking user may either be a database user or an Oracle HTML DB application user. The function does this by matching the user's name to the value in the ENAME column. We'll see later how this code satisfies our security requirements within an Oracle HTML DB application.

To create the policy function:

  • Connect as the security adminstrator user, VPD_ADMIN:
  • connect vpd_admin/akf7d98s2
    
  • Execute the following:
  • CREATE OR REPLACE FUNCTION user_only (
                                   p_schema IN VARCHAR2 DEFAULT NULL,
                                   p_object IN VARCHAR2 DEFAULT NULL)
                           RETURN VARCHAR2
    AS
    BEGIN
    RETURN 'ename = nvl(v(''APP_USER''),USER)';
    END;
    /
    

Registering the Policy Function

Note that the EXECUTE privileges on the policy function were intentionally not granted to anyone. The database will execute this function on behalf of the user.  Now, we need to register this function such that it is applied every time a query is run on the EMP table. The registration is done by invoking the DBMS_RLS package as our security administrator.

  • To register the policy function, execute the following as VPD_ADMIN:
  • BEGIN
    DBMS_RLS.add_policy
             (object_schema => 'data_schema',
              object_name => 'EMP',
              policy_name => 'EMP_SEL_POL',
              function_schema => 'vpd_admin',
              policy_function => 'USER_ONLY',
              statement_types => 'SELECT');
    END;
    /
    

The policy created above states than any SELECT statements on EMP table in the DATA_SCHEMA schema will cause the database to execute the USER_ONLY function located in the VPD_ADMIN schema.  The string returned by the USER_ONLY function will be appended to the query that was originally run.

Testing the Policy Function in SQL*Plus

We can test our VPD policy by logging in via SQL*Plus to the SCOTT schema. A query on the table is transparently re-written and the results are constrained to contain only SCOTT's record.

To test the policy function:

  • connect as the SCOTT user
  • connect scott/tiger
    
  • Run the following query:
  • SELECT empno, ename, job, sal
       FROM data_schema.emp;
    

You should see the following results:

EMPNO        ENAME       JOB          SAL
----------   ----------  ---------    ----------
7788         SCOTT       ANALYST      3000

Only one row was returned because the query executed by the database after applying the VPD policy was:

SELECT empno, ename, job, sal
FROM data_schema.emp
WHERE ename = nvl(v('APP_USER'),USER)

We'll get to the meaning of v('APP_USER') later . Suffice it to say here that, when this query was run outside of the context of Oracle HTML DB, the function v('APP_USER') returned NULL and that therefore ename was matched to the value of USER for each row.

Testing the Policy Function in an Oracle HTML DB Application

To test our newly created policy function in an Oracle HTML DB application, we'll quickly create a report based on the DATA_SCHEMA.emp table.   First, we'll need to create workspace with access to the DATA_SCHEMA schema.

To create a workspace:

  • Log in as the Oracle HTML DB  Service Administrator, using a URL that looks like this:
  • http://your_server.com/pls/some_dad/htmldb_admin
    
  • Under Manage Workspaces, click Create New Workspace.
  • Enter a Workspace Name and click on Next .
  • Choose to Re-use an existing schema, and enter DATA_SCHEMA for the Schema Name.
  • Click on Next.
  • In the Administrator Username field, enter admin.
  • In the Password field, enter a password.
  • In the Email field, enter an email address.
  • Click on Next.
  • Review your selections, and then click on Provision.
Now, we can log in as a developer into the newly created workspace.

To log in to the workspace:

  • Click on the Logout icon in the upper right corner of the page.
  • Click on the Login link.
  • Enter the Workspace Name, Username , and Password you just created and click on Login.

You should now see the "Welcome to HTML DB" screen, with icons for the Application Builder, SQL Workshop, Data Workshop, and Administration.The quickest way to test the VPD policy in an Oracle HTML DB application is to create one on the existing EMP table.

To quickly create an application:

  • Click on Create Application.
  • Select Based on Existing Tables.
  • Click on Next >.
  • Select DATA_SCHEMA as the Table/View Owner.
  • Click on Next >
  • In the first field under Table/View Names, enter EMP.
  • Click on Next >.
  • Click on Finish to create your application.
  • Click on Run Application to run your application.
  • Log in with the username admin and the password you chose when you created the Workspace.
  • Click on the Emp link under Report and Edit; you should get a "No Data Found" message.

The Policy was again applied to the SELECT statement on the EMP table, and as you logged in as the application user admin, no rows were returned according to the VPD policy in effect.

To see the same data returned in the report as we saw in SQL*Plus, we'll have to create an application user SCOTT. The application we created using the application wizard by default uses Oracle HTML DB authentication, based on a repository of users associated with the workspace the application is part of. We can use the workspace administration facilities to create a new user.

Note that we'll be creating an application user here, not a database schema. Oracle HTML DB gives you the flexibility to maintain application users wherever you need, including an LDAP repository or Single Sign-On. For this demonstration, we'll stick with the Oracle HTML DB supplied authentication mechanism.

To create a new application user in the workspace:

  • While the application is running, click on Edit Application at the bottom of the page.
  • Under the Tasks region, click on Manage Developers, and then click on Create >.
  • Create a user called SCOTT, specify a password and a valid e-mail address, and then click on Create User.
  • Click on the Build icon in the navigation bar, and then click on Run.
  • Click on the Logout link, and then log back in as the SCOTT user you just created.
  • Click on the Emp link under Report and Edit; you should now see one row.

Note how the same policy is applied whether the data is accessed directly from SQL*PLUS or through a report in an Oracle HTML DB application.

A bit more on the function call v('APP_USER') in the VPD function. APP_USER is a built-in session state variable that always contains the username of the user currently running an Oracle HTML DB application, regardless of how this user was authenticated. To make sure the VPD policy works as desired in both SQL*Plus and inside an Oracle HTML DB application, we used the NVL around the v('APP_USER') function.

You have just implemented a VPD policy in your HTML DB application.

E-mail this page
Printer View Printer View
Oracle Is The Information Company About Oracle | Oracle RSS Feeds | Careers | Contact Us | Site Maps | Legal Notices | Terms of Use | Privacy