In this chapter, we will cover the following tasks:
Creating different policy functions Creating Oracle Virtual Private Database row-level policies Creating column-level policies Creating a driving context Creating policy groups Setting context as a driving context Adding a policy to a group Exempting users from VPD policies Introduction Oracle Virtual Private Database (VPD) is a security feature, introduced in Oracle Database 8i. It is available only in Enterprise Edition of Oracle Database. Discretionary access control (DAC) grants/restricts access to data at an object level (for example, table level). This means that a user can access either the entire data in a table or no data. VPD enables you more granular control over security of your data. Using VPD, you can restrict access to data at row level or column level. VPD doesn't replace DAC, but it is complimentary to DAC. VPD can further restrict access to users who have been given access to data by DAC.Virtual Private Database [ 90 ] There are five types of policies based on how often a policy function is evaluated: DBMS_RLS.DYNAMIC DMBS_RLS.STATIC DBMS_RLS.SHARED_STATIC DBMS_RLS.CONTEXT_SENSITIVE DBMS_RLS.SHARED_CONTEXT_SENSITIVE DBMS_RLS.DYNAMIC is default. Although it is not necessary to use application contexts when implementing VPD policies, it is a common practice. Figure 1 shows usual steps that you will need to complete to implement the VPD policy on protected objects, such as table or view: Figure 1 � Steps to implement the VPD policy A driving context is an application context that has at least one attribute and its purpose is to determine which group of policies will be applied. The driving context is set by an application that is trying to access the data.Virtual Private Database [ 91 ] The default VPD behavior is that all policies defined on a table or a view are enforced for all SQL statements regardless of the application that executes them. If multiple applications share a table or a view, it is highly likely that you will either need to establish more complex logic to handle security requirements (to determine in which case, which predicate should be returned) or change the default VPD behavior by creating and using policy groups. If policies are already defined, you should identify which policies should be in effect when each application accesses the table or view. Each object has a predefined default policy group (SYS_DEFAULT), and the policies defined in this group are always applied for that particular object. A driving context determines which other policy group will also be applied at that time. Suppose that there are two applications (A and B) that access data in table HR.EMP_VPD_TEST. Their specific policies are defined in two policy groups (HR_GRP_A and HR_GRP_B), and policies that should be enforced in any case are defined in the default group (SYS_DEFAULT). When application A accesses the data, policies that belong to HR_GRP_A and SYS_DEFAULT groups are applied, and when application B accesses the data, polices that belong to HR_GRP_B and SYS_DEFAULT groups are applied (it is assumed that the driving context is properly set). Steps to implement policy groups are shown in Figure 2: Figure 2 � Steps to implement policy groupsVirtual Private Database [ 92 ] Creating different policy functions The purpose of a policy function is to return a predicate that will be applied in WHERE clause of the statement (except for INSERT operation). In this recipe, you'll create several simple policy functions, based on different business and security requirements. Getting ready To complete this recipe, you'll need to create the table hr.emp_vpd_test, insert several values into that table, and create several users (in our case, susan, joel, emma, maja, and zoran already exist). Figure 3 � A test tableVirtual Private Database [ 93 ] If you won't use the same data as shown in Figure 4, then keep in mind to accordingly make changes in the How to do it section and the rest of the recipes in this chapter. Figure 4 � Test data in the table hr.emp_vpd_test How to do it� 1. Connect to the database as a user who has appropriate privileges (for example, user maja): $ sqlplus majaVirtual Private Database [ 94 ] 2. Create a policy function that satisfies this condition: The user susan can't access data in a table (for example, hr.emp_vpd_test) and other users can access entire data in the table. Figure 5 3. Create an application context that has the emp_id attribute and the value is emp_id (from the hr.emp_vpd_test) of the connected user or if the connected user is not employee. See Chapter 12, Appendix � Application Contexts for detailed explanation (recipes: Creating an application context and Setting application context attributes) and make appropriate changes. Create an application contextVirtual Private Database [ 95 ] Create a PL/SQL package Create a logon triggerVirtual Private Database [ 96 ] 4. Create a policy function (for example, emp_access) that satisfies this condition: a �regular� employee can access only his or her data in a table (for example, hr.emp_vpd_test) and manager users can access his or her data in the table and data for employees he or she directly manages. Figure 9 � The emp_access policy function 5. Create a role (for example, HREMP_TEST).Virtual Private Database [ 97 ] 6. Create a policy function that satisfies this condition: Only users who have the HREMP_TEST role can view data in a table (for example, hr.emp_vpd_test). Figure 11 � The role_access policy function How it works� In step 4, you created a policy function that uses the application context you created, where as other policy functions you created use built-in application contexts. A policy function can be part of a package or is standalone.Virtual Private Database [ 98 ] There's more� To test whether the function defined in step 2 works properly, perform the following tasks: 1. Connect to the database as the user maja and execute the following statement: Figure 12 � Maja can access data 2. Grant the user susan execute on no_access function and connect to the database as the user susan. Figure 13 � Temporary grant the susan privilege 3. Execute the following statement: select maja.no_access('a','b') from dual; Figure 14 � Susan can't access dataVirtual Private Database [ 99 ] 4. Connect to the database as the user maja and revoke execute on no_access function from the user susan. Figure 15 � Clean up environment (revoke privilege) See also All recipes of Chapter 12, Appendix � Application Contexts Creating Oracle Virtual Private Database row-level policies Oracle VPD row-level policies restrict users' access per row for a protected object. This means that two users who execute the same query against, for example, a table may, as a result, receive different number of rows. Getting ready See the Getting ready section of the recipe Creating different policy functions.Virtual Private Database [ 100 ] How to do it� 1. Connect to the database as a user who has appropriate privileges (for example, the user maja): $ sqlplus maja 2. Create a VPD policy (for example, test_pol1) that protects the hr.emp_vpd_test table in the following way: it restricts SELECT operation based on a policy function (for example, no_access). 3. To test VPD policy created in the previous step, connect as the user susan to the database (keep in mind that she has the SELECT ANY TABLE privilege) and try to access data in the table hr.emp_vpd_test. Figure 17 � Susan can't access dataVirtual Private Database [ 101 ] 4. Connect to the database as a user who can create a VPD policy (for example, user maja). Create a VPD policy (for example, test_pol2) that additionally protects the hr.emp_vpd_test table in the following way: it restricts the SELECT and DELETE operations based on a policy function (for example, emp_access). SQL> connect maja Figure 18 � The VPD policy TEST_POL2 5. Connect to the database as the user joel and execute the following query: SELECT * FROM HR.EMP_VPD_TEST; The result will show 3 rows, because joel can view his data and data for his direct employees (policy function emp_access). Figure 19 � Joel can view his data and data for his direct employeesVirtual Private Database [ 102 ] 6. Connect to the database as the user emma and execute the following query: SELECT * FROM HR.EMP_VPD_TEST; The result will show only 1 row, because emma is a �regular� employee, so she can view only her own data (policy function emp_access). Figure 20 � Emma can only view her own data There's more� You defined two VPD policies on the same table, and they are both enabled. The first one only restricts the user susan from accessing the table, whereas the other one affects all users connected to the database (with some exceptions, see the recipe Exempting users from VPD policies). If susan connects to the database, both policies will determine whether she can access the data and if yes, which data. The way the policies are defined, she won't be able to view data in the table. See also The recipe Exempting users from VPD policiesVirtual Private Database [ 103 ] Creating column-level policies When you create a column-level VPD policy, you define sensitive columns, and if those columns are referenced in a query, statement will be rewritten. To create a column- level VPD policy, you also use the DBMS_RLS.ADD_POLICY procedure. Getting ready See the Getting ready section for the first recipe in this chapter. Results shown in this recipe assume that you completed previous recipes in this chapter. How to do it� 1. Connect to the database as a user who has appropriate privileges (for example, the user maja): $ sqlplus maja 2. Create a VPD policy (for example, test_col) that protects the hr.emp_vpd_test table in the following way: it defines that salary and comm_pct are sensitive columns and a user can access them only if he or she has the HREMP_TEST role (the role_access policy function).Virtual Private Database [ 104 ] 3. Grant the role HREMP_TEST to user zoran: SQL> grant HREMP_TEST to zoran; 4. Connect to the database as the user zoran and view data in the table hr.emp_vpd_test. 5. Connect to the database as the user maja and disable the VPD policy TEST_POL2.Virtual Private Database [ 105 ] 6. Repeat step 4. 7. Connect to the database as the user joel and execute the same statement as in the previous step.