Oracle9i Application Developer's Guide - Fundamentals Release 2 (9.2) Part Number A96590-01 |
|
This chapter explains how to implement application security policies. Topics in this chapter include:
Application context allows you to write applications which draw upon certain aspects of a user's session information. It provides a way to define, set, and access attributes that an application can use to enforce access control--specifically, fine-grained access control.
Most applications contain information about the basis on which access is to be limited. In an order entry application, for example, customers would be limited to access their own orders (ORDER_NUMBER
) and customer number (CUSTOMER_NUMBER
). These can be used as security attributes.
Consider a user running a Human Resource application. Part of the application's initialization process is to determine the kind of responsibility that the user can assume, based on the user's identity. This responsibility ID becomes part of the Human Resource application context; it will affect what data the user can access throughout the session.
This section explains the use of application context. It includes:
Application context provides important security features:
Each application can have its own context with its own attributes. Suppose, for example, you have three applications: General Ledger, Order Entry, and Human Resources. You can specify different attributes for each application. Thus,
SET_OF_BOOKS
and TITLE.
CUSTOMER_NUMBER.
ORGANIZATION_ID
, POSITION
, and COUNTRY
.In each case, you can adapt the application context to your precise security needs.
Suppose you have a General Ledger application, which has access control based upon the set of books being used. If a user accessing this application changes the set of books he is working on from 01 to 02, the application context can ensure that:
The validation function can check application metadata tables to make this determination and ensure that the attributes in combination are in line with the overall security policy. To prevent users from changing a context attribute without the above security validation, Oracle ensures that an attribute can be changed only by the designated package which implements the context.
Oracle9i provides a built-in application context namespace, USERENV
, which provides access to predefined attributes. These attributes are session primitives--information which the database captures regarding a user's session. For example, the IP address from which a user connected, the username, and a proxy username (in cases where a user connection is proxied through a middle tier), are all available as predefined attributes through the USERENV
application context.
Predefined attributes can be very useful for access control. For example, if you are using a three-tier application which creates lightweight user sessions through OCI or thick JDBC, you can access the PROXY_USER
attribute in the USERENV
application context to determine whether the user's session was created by a middle tier application. Your policy function could allow a user to access data only for connections where the user is proxied. If the user is not proxied (that is, when the user connects directly to the database), the user would not be able to access any data.
While you can use the PROXY_USER
attribute within VPD to ensure that users only access data through a particular middle-tier application, a different approach would be to develop a secure application role. Rather than have each policy ensure that the user accesses the database by being proxied through HRAPPSERVER
, you could have the secure application role enforce this.
Although predefined attributes can be accessed through the USERENV
application context, they cannot not be changed. They are listed in Table 12-1.
Use the following syntax to return information about the current session.
SYS_CONTEXT('userenv', 'attribute')
Note: The USERENV application context namespace is intended to replace the USERENV function provided in earlier database releases.
|
See Also:
|
Many applications store attributes used for fine-grained access control within a database metadata table that they use for access control. For example, an EMPLOYEES
table could include cost center, title, signing authority, and other information useful for fine-grained access control. However, many organizations centralize user information and user management in an LDAP-based directory such as Oracle Internet Directory. These organizations also wish to centralize the information about users that is used for access control. Application context attributes can be stored in Oracle Internet Directory and assigned to one or more enterprise users. They can be retrieved automatically upon login for an enterprise user, and used to initialize an application context.
To simplify the implementation of a security policy, you have the option of using application context within a fine-grained access control function.
Note: Using application context with fine-grained access control is called Virtual Private Database (VPD). |
Application context can be used in the following ways with fine-grained access control:
Accessing an application context inside your fine-grained access control policy function is like writing down an often-used phone number and posting it next to your phone, where you can find it easily--rather than looking it up every time you need it.
For example, suppose you base access to the ORDERS_TAB
table upon customer number. Rather than querying the customer number for a logged-in user each time you need it, you could store the number in the application context. In this way, the customer number is available when you need it.
Application context is especially helpful if your security policy is based upon multiple security attributes. For example, a policy function which bases a predicate on four attributes (such as employee number, cost center, position, spending limit) would have to execute multiple subqueries to retrieve this information. If all of this data is already available through application context, then performance will be much faster.
You can use application context to return the correct predicate--that is, the correct security policy.
Consider an order entry application which enforces the rules, "customers only see their own orders, and clerks see all orders for all customers." These are two different policies. You could define an application context with a position
attribute, and this attribute could be accessed within the policy function to return the correct predicate, depending on the value of the attribute. Thus, you can enable a user in the Clerk
position to retrieve all orders, but a user in the Customer
position to see his own records only.
To design a fine-grained access control policy to return a specific predicate for an attribute, access the application context within the function that implements the policy. For example, to limit customers to seeing their own records only, use fine-grained access control to dynamically modify the user's query from this:
SELECT * FROM Orders_tab
to this:
SELECT * FROM Orders_tab WHERE Custno = SYS_CONTEXT ('order_entry', 'cust_num');
Continuing with the example above, suppose you have 50,000 customers, and you do not want to have a different predicate returned for each customer. Customers all share the same policy. That is, they can only see their own orders. It is merely their customer numbers which are different.
Using application context, you can return one predicate within a policy function which applies to 50,000 customers. As a result, there is one shared cursor which nonetheless executes differently for each customer, because the customer number is evaluated at execution time. This value is, of course, different for every customer. Use of application context in this case provides optimum performance, as well as fine-grained security.
Note that the SYS_CONTEXT
function works much like a bind variable, but only if the SYS_CONTEXT
arguments are constants.
Applications may have differing user models, but you may want to use Virtual Private Database (VPD) to limit access by user. Whether the user is a database user or an application user unknown to the database, Oracle provides different ways in which applications can enforce per-user fine-grained access control.
For applications in which the application users are also database users, VPD enforcement is relatively simple; users connect to the database, and the application can set up per-session application contexts. Each session is initiated under a different username, so that it is simple to enforce different fine-grained access control conditions for users Jane and John. This is also possible with use of proxy authentication, since each "lightweight" session in OCI or thick JDBC is still a distinct database session, and can have its own application context.
Since proxy authentication can be integrated with Enterprise User Security, user roles can be retrieved from Oracle Internet Directory, as well as other attributes that can be used for VPD enforcement.
For applications in which a single user (for example, One Big Application User) connects to the database on behalf of all users, per-user fine-grained access control is still possible. An application developer can create a context attribute to represent the application user (for example, realuser). While all database sessions (and thus all audit records) are initiated as One Big Application User, each session can nonetheless have attributes that vary, depending on who the real user is. This model works best for applications with a limited number of users where there is no requirement for session reuse. Of course, each session, from the database standpoint, is created as the same database user, so that the ability to use roles, database auditing, and others is greatly diminished for reasons previously enumerated.
Web-based applications typically have hundreds if not thousands of users, and the web is stateless. There may be a persistent connection to the database (to support data retrieval for a number of user requests), but these connections are not specific to each web-based user. Web-based applications typically set up and reuse connections instead of having different sessions for each user, to provide scalability. For example, web user Jane and Ajit connect to a middle tier application, which establishes a session in the database used by the application on behalf of both users. Typically, neither Jane nor Ajit are known to the database. The application is responsible for switching the username on the connection, so that, at any given time, it's either Jane or Ajit using the session.
Oracle9i VPD capabilities facilitate connection pooling by allowing multiple connections to access one or more global application contexts, instead of setting up an application context for each distinct user session.
Applications use a CLIENT_IDENTIFIER (which could be an individual application username, or a group) to reference the global application context. Global application contexts provide additional flexibility for web-based applications to use Virtual Private Database, as well as enhanced performance through reuse of common application contexts among multiple sessions instead of setting up per-session application contexts. The CLIENT_IDENTIFIER is also viewable in the user session and accessible in the USERENV naming context.
The use of a CLIENT_IDENTIFIER thus functions as an application user proxy, since the CLIENT_IDENTIFIER can be used to capture the 'application username.' The ability to pass a CLIENT_IDENTIFIER to the database for use with global application context is supported in OCI, thick JDBC, and thin JDBC. For OCI-based connections, a change in CLIENT_IDENTIFIER is automatically piggybacked on the next OCI call, for additional performance benefits.
Application user proxy authentication can be used with global application context for additional flexibility and high performance in building applications. For example, suppose a web-based application that provides information to business partners has three types of users: gold partner, silver partner, and bronze partner, representing different levels of information available. Instead of each user having his own session -- with individual application contexts -- set up, the application could set up global application contexts for gold partner, silver partner, or bronze partner and use the client identifier to point the session at the correct context, in order to retrieve the appropriate type of data. The application need only initialize the three global contexts once, and use the client identifier to access the correct application context to limit data access. This provides performance improvements through session reuse, and through accessing global application contexts set up once, instead of having to initialize application contexts for each session individually.
Developers implementing Virtual Private Database (VPD) can use the DBMS_RLS
package to apply security policies to tables and views. Also, Developers can use the CREATE CONTEXT
command to create application contexts.
Alternatively, developers can use the Oracle Policy Manager graphical user interface, accessed from Oracle Enterprise Manager, to apply security policies to schema objects, such as tables and views, and to create application contexts. Oracle Policy Manager provides an easy-to-use interface to manage security policies and application contexts, and therefore makes VPD easier to develop.
Oracle Policy Manager is the administration tool for Oracle Label Security. Oracle Label Security provides a functional, out-of-the-box VPD policy which enhances your ability to implement row-level security. It supplies an infrastructure--a label-based access control framework--whereby you can specify labels for users and data. It also enables you to create one or more custom security policies to be used for label access decisions. You can implement these policies without any knowledge of a programming language. There is no need to write additional code; in a single step you can apply a security policy to a given table. In this way, Oracle Label Security provides a straightforward, efficient way to implement fine-grained security policies using data labeling technology. Finally, the structure of Oracle Label Security labels provides a degree of granularity and flexibility which cannot easily be derived from the application data alone. Oracle Label Security is thus a generic solution which can be used in many different circumstances.
To create VPD policies, users must provide the schema name, table (or view) name, policy name, the function name that generates the predicate, and the statement types to which the policy applies (that is, SELECT
, INSERT
, UPDATE
, DELETE
). Oracle Policy Manager then executes the function DBMS_RLS.ADD_POLICY
. You create an application context by providing the name of the context and the package that implements the context.
To use application context, you perform the following tasks:
Begin by creating a PL/SQL package with functions that set the context for your application. This section presents an example for creating the PL/SQL package, followed by a discussion of SYS_CONTEXT
syntax and behavior.
Note: A login trigger can be used because the user's context (information such as |
The following example creates the package app_security_context
.
CREATE OR REPLACE PACKAGE App_security_context IS PROCEDURE Set_empno; END; CREATE OR REPLACE PACKAGE BODY App_security_context IS PROCEDURE Set_empno IS Emp_id NUMBER; BEGIN SELECT Empno INTO Emp_id FROM Emp_tab WHERE Ename = SYS_CONTEXT('USERENV', 'SESSION_USER'); DBMS_SESSION.SET_CONTEXT('app_context', 'empno', Emp_id); END; END;
The syntax for this function is:
SYS_CONTEXT ('namespace', 'attribute', [length])
This function returns the value of attribute
as defined in the package currently associated with the context namespace. It is evaluated once for each statement execution, and is treated like a constant during type checking for optimization. You can use the pre-defined namespace USERENV
to access primitive contexts such as userid and NLS parameters.
Note: If you try to execute SYS_CONTEXT in a parallel query environment, you will receive a query error. See Using SYS_CONTEXT in a Parallel Query. |
See Also:
"Providing Access to Predefined Attributes Through the USERENV Namespace" Oracle9i SQL Reference for details about attributes |
During a session in which you expect a change in policy between executions of a given query, that query must use dynamic SQL. You must use dynamic SQL because static SQL and dynamic SQL parse statements differently.
Consider a situation in which policy A is in force when you compile a SQL statement--and then you switch to policy B and execute the statement. With static SQL, policy A remains in force: the statement is parsed at compile time and not reparsed upon execution. With dynamic SQL, however, the statement is parsed upon execution, and so the switch to policy B is carried through.
For example, consider the following policy:
EMPLOYEE_NAME = SYS_CONTEXT ('userenv', 'session_user')
The policy "Employee name matches database user name" is represented in the form of a SQL predicate: the predicate is basically a policy. If the predicate changes, the statement must be reparsed in order to produce the correct result.
If SYS_CONTEXT
is used inside a SQL function which is embedded in a parallel query, the function cannot pick up the application context. This is true because the application context exists only in the user session. To use these features in combination, you must call SYS_CONTEXT
directly from the query.
Consider a user-defined function within a SQL statement, which sets the user's ID to 5:
CREATE FUNC proc1 AS RETURN NUMBER; BEGIN IF SYS_CONTEXT ('hr', 'id') = 5 THEN RETURN 1; ELSE RETURN 2; END END;
Now consider the statement:
SELECT * FROM EMP WHERE proc1( ) = 1;
If this statement is run as a single query (that is, if one process is used to run the entire query), there will be no problem.
However, if this statement is run as a parallel query, the parallel execution servers (query slave processes) do not have access to the user session which contains the application context information. The query will not produce the expected results.
By contrast, if you use the SYS_CONTEXT
function within a query, there is no problem. For example,
SELECT * FROM EMP WHERE SYS_CONTEXT ('hr', 'id') = 5;
In this way, it works like a bind variable: the query coordinator can access the application context information and pass it on to the parallel execution servers.
When you execute a statement, Oracle9i takes a snapshot of the entire application context being set up by SYS_CONTEXT
. Within the duration of a query, the context remains the same for all fetches of the query.
If you (or a function) attempt to change the context within a query, the change will not take effect in the current query. In this way, SYS_CONTEXT
enables you to store variables in a session.
To perform this task, use the CREATE
CONTEXT
statement. Each context must have a unique attribute and belong to a namespace. That is, context names must be unique within the database, not just within a schema. Contexts are always owned by the schema SYS
.
For example:
CREATE CONTEXT order_entry USING oe_context;
where order_entry
is the context namespace, and oe_context
is the trusted package that can set attributes in the context namespace.
After you have created the context, you can set or reset the context attributes by using the DBMS_SESSION.SET_CONTEXT package. The values of the attributes you set remain either until you reset them, or until the user ends the session.
You can only set the context attributes inside the trusted procedure you named in the CREATE
CONTEXT
statement. This prevents a malicious user from changing context attributes without proper attribute validation.
Alternatively, you can use the Oracle Policy Manager graphical user interface to create a context and associate it with a PL/SQL package. Oracle Policy Manager, accessed from Oracle Enterprise Manager, enables you to apply policies to database objects and create application contexts. It also can be used to create and manage Oracle Label Security policies.
Always use an event trigger on login to pull session information into the context. This sets the user's security-limiting attributes for the database to evaluate, and thus enables it to make the appropriate security decisions.
Other considerations come into play if you have a changing set of books, or if positions change constantly. In these cases, the new attribute values may not be picked up right away, and you must force a cursor reparse to pick them up.
Now that you have set up the context and the PL/SQL package, you can go ahead and have your policy functions use the application context to make policy decisions based on different context values.
This section provides three examples that use application context within a fine-grained access control function.
This example uses application context to implement the policy, "Customers can see their own orders only."
This example guides you through the following steps in building the application:
The procedure in this example assumes a one-to-one relationship between users and customers. It finds the user's customer number (Cust_num
), and caches the customer number in the application context. You can later refer to the cust_num
attribute of your order entry context (order_entry_ctx
) inside the security policy function.
Note that you could use a login trigger to set the initial context.
Create the package as follows:
CREATE OR REPLACE PACKAGE apps.oe_ctx AS PROCEDURE set_cust_num ; END; CREATE OR REPLACE PACKAGE BODY apps.oe_ctx AS PROCEDURE set_cust_num IS custnum NUMBER; BEGIN SELECT cust_no INTO custnum FROM customers WHERE username = SYS_CONTEXT('USERENV', 'session_user'); /* SET cust_num attribute in 'order_entry' context */ DBMS_SESSION.SET_CONTEXT('order_entry', 'cust_num', custnum); DBMS_SESSION.SET_CONTEXT('order_entry', 'cust_num', custnum); END set_cust_num; END;
Note: This example does not treat error handling. You can access predefined attributes--such as session user--by using For more information, see Oracle9i SQL Reference |
Create an application context by entering:
CREATE CONTEXT Order_entry USING Apps.Oe_ctx;
Alternatively, you can use Oracle Policy Manager to create an application context.
Access the application context inside the package that implements the security policy on the database object.
Note: You may need to set up the following data structures for certain examples to work: CREATE PACKAGE Oe_security AS FUNCTION Custnum_sec (D1 VARCHAR2, D2 VARCHAR2) RETURN VARCHAR2; END; |
The package body appends a dynamic predicate to SELECT
statements on the ORDERS_TAB
table. This predicate limits the orders returned to those of the user's customer number by accessing the cust_num
context attribute, instead of a subquery to the customers table.
CREATE OR REPLACE PACKAGE BODY Oe_security AS /* limits select statements based on customer number: */ FUNCTION Custnum_sec (D1 VARCHAR2, D2 VARCHAR2) RETURN VARCHAR2 IS D_predicate VARCHAR2 (2000) BEGIN D_predicate = 'cust_no = SYS_CONTEXT("order_entry", "cust_num")'; RETURN D_predicate; END Custnum_sec; END Oe_security;
Create the policy as follows:
Note: You may need to set up the following data structures for certain examples to work: CONNECT sys/change_on_install AS sysdba; CREATE USER secusr IDENTIFIED BY secusr; |
DBMS_RLS.ADD_POLICY ('scott', 'orders_tab', 'oe_policy', 'secusr', 'oe_security.custnum_sec', 'select')
This statement adds a policy named OE_POLICY
to the ORDERS_TAB
table for viewing in schema SCOTT
. The SECUSR
.OE_SECURITY.CUSTNUM_SEC
function implements the policy, is stored in the SECUSR
schema, and applies to SELECT
statements only.
Now, any select statement by a customer on the ORDERS_TAB
table automatically returns only that customer's orders. In other words, the dynamic predicate modifies the user's statement from this:
SELECT * FROM Orders_tab;
to this:
SELECT * FROM Orders_tab WHERE Custno = SYS_CONTEXT('order_entry','cust_num');
Note the following with regard to this example:
custnum_sec
function to return different predicates based on the user's position context value.SELECT * FROM Orders_tab WHERE Custno = SYS_CONTEXT('order_entry', 'cust_num')
This is fully parsed and optimized, but the evaluation of the user's CUST_NUM
attribute value for the ORDER_ENTRY
context takes place at execution. This means that you get the benefit of an optimized statement which executes differently for each user who executes the statement.
See Also:
Compare and contrast this example, which uses an application context within the dynamically generated predicate, with "How Fine-Grained Access Control Works", which uses a subquery in the predicate |
This example uses application context to control user access by way of a Human Resources application. It guides you through the following three tasks, each of which is described more fully below.
In this example, assume that the application context for the Human Resources application is assigned to the HR_CTX
namespace.
Create a PL/SQL package with a number of functions that set the context for the application
APPS
is the schema owning the package.
CREATE OR REPLACE PACKAGE BODY apps.hr_sec_ctx IS /* function to set responsibility id */ PROCEDURE set_resp_id (respid NUMBER) IS BEGIN /* validate respid based on primitive and other context */ /* validate_respid (respid); */ /* set resp_id attribute under namespace 'hr_ctx'*/ DBMS_SESSION.SET_CONTEXT('hr_ctx', 'resp_id', respid); END set_resp_id; /* function to set organization id */ PROCEDURE set_org_id (orgid NUMBER) IS BEGIN /* validate organization ID */ /* validate_org_id(orgid); /* /* set org_id attribute under namespace 'hr_ctx' */ DBMS_SESSION.SET_CONTEXT('hr_ctx', 'org_id', orgid); END set_org_id; /* more functions to set other attributes for the HR application */ END hr_sec_ctx;
For example:
CREATE CONTEXT Hr_ctx USING Apps.Hr_sec_ctx;
Suppose that the execute privilege on the package HR_SEC_CTX
has been granted to the schema running the application. Part of the script will make calls to set various attributes of the HR_CTX
context. Here, we do not show how the context is determined. Normally, it is based on the primitive context or other derived context.
APPS.HR_SEC_CTX.SET_RESP_ID(1); APPS.HR_SEC_CTX.SET_ORG_ID(101);
The SYS_CONTEXT
function can be used for data access control based on this application context. For example, the base table HR_ORGANIZATION_UNIT
can be secured by a view that restricts access to rows based on attribute ORG_ID
:
Note: You may need to set up data structures for certain examples to work: CREATE TABLE hr_organization_unit (organization_id NUMBER); |
CREATE VIEW Hr_organization_secv AS SELECT * FROM hr_organization_unit WHERE Organization_id = SYS_CONTEXT('hr_ctx','org_id');
This example illustrates use of the following security features in Oracle9i:
In this example, we associate a security policy with the table called DIRECTORY
which has the following columns:
Column | Description |
---|---|
|
identification number for each employee |
|
employee identification number for the manager of each employee |
|
position of the employee in the corporate hierarchy |
The security policy associated with this table has two elements:
MGRID
for a specific EMPNO
. To implement this, we create a definer's right package in the Human Resources schema (HR
) to perform SELECT
on the table.EMPNO
and application context.EMPNO
by using a logon trigger.
Note: In this example, we grant |
CONNECT system/manager AS sysdba GRANT CONNECT,RESOURCE,UNLIMITED TABLESPACE,CREATE ANY CONTEXT, CREATE PROCEDURE, CREATE ANY TRIGGER TO HR IDENTIFIED BY HR; CONNECT hr/hr; CREATE TABLE Directory (Empno NUMBER(4) NOT NULL, Mgrno NUMBER(4) NOT NULL, Rank NUMBER(7,2) NOT NULL); CREATE TABLE Payroll (Empno NUMBER(4) NOT NULL, Name VARCHAR(30) NOT NULL ); /* seed the tables with a couple of managers: */ INSERT INTO Directory VALUES (1, 1, 1.0); INSERT INTO Payroll VALUES (1, 'KING'); INSERT INTO Directory VALUES (2, 1, 5); INSERT INTO Payroll VALUES (2, 'CLARK'); /* Create the sequence number for EMPNO: */ CREATE SEQUENCE Empno_seq START WITH 5; /* Create the sequence number for RANK: */ CREATE SEQUENCE Rank_seq START WITH 100; CREATE OR REPLACE CONTEXT Hr_app USING Hr.Hr0_pck; CREATE OR REPLACE CONTEXT Hr_sec USING Hr.Hr1_pck; CREATE or REPLACE PACKAGE Hr0_pck IS PROCEDURE adjustrankby1(Empno NUMBER); END; CREATE or REPLACE PACKAGE BODY Hr0_pck IS /* raise the rank of the empno by 1: */ PROCEDURE Adjustrankby1(Empno NUMBER) IS Stmt VARCHAR2(100); BEGIN /*Set context to indicate application state */ DBMS_SESSION.SET_CONTEXT('hr_app','adjstate',1); /* Now we can issue DML statement: */ Stmt := 'UPDATE SET Rank := Rank +1 FROM Directory d WHERE d.Empno = ' || Empno; EXECUTE IMMEDIATE STMT; /* Re-set application state: */ DBMS_SESSION.SET_CONTEXT('hr_app','adjstate',0); END; END; CREATE or REPLACE PACKAGE hr1_pck IS PROCEDURE setid; END; / /* Based on userid, find EMPNO, and set it in application context */ CREATE or REPLACE PACKAGE BODY Hr1_pck IS PROCEDURE setid IS id NUMBER; BEGIN SELECT Empno INTO id FROM Payroll WHERE Name = SYS_CONTEXT('userenv','session_user') ; DBMS_SESSION.SET_CONTEXT('hr_sec','empno',id); DBMS_SESSION.SET_CONTEXT('hr_sec','appid',id); EXCEPTION /* For purposes of demonstration insert into payroll table / so that user can continue on and run example. */ WHEN NO_DATA_FOUND THEN INSERT INTO Payroll (Empno, Name) VALUES (Empno_seq.NEXTVAL, SYS_CONTEXT('userenv','session_user')); INSERT INTO Directory (Empno, Mgrno, Rank) VALUES (Empno_seq.CURRVAL, 2, Rank_seq.NEXTVAL); SELECT Empno INTO id FROM Payroll WHERE Name = sys_context('userenv','session_user') ; DBMS_SESSION.SET_CONTEXT('hr_sec','empno',id); DBMS_SESSION.SET_CONTEXT('hr_sec','appid',id); WHEN OTHERS THEN NULL; /* If this is to be fired via a "logon" trigger, / you need to handle exceptions if you want the user to continue / logging into the database. */ END; END; GRANT EXECUTE ON Hr1_pck TO public; CONNECT system/manager AS sysdba CREATE OR REPLACE TRIGGER Databasetrigger AFTER LOGON ON DATABASE BEGIN hr.Hr1_pck.Setid; END; /* Creates the package for finding the MGRID for a particular EMPNO using definer's right (encapsulated privileges). Note that users are granted EXECUTE privileges only on this package, and not on the table (DIRECTORY) it is querying. */ CREATE or REPLACE PACKAGE hr2_pck IS FUNCTION Findmgr(Empno NUMBER) RETURN NUMBER; END; CREATE or REPLACE PACKAGE BODY hr2_pck IS /* insert a new employee record: */ FUNCTION findmgr(empno number) RETURN NUMBER IS Mgrid NUMBER; BEGIN SELECT mgrno INTO mgrid FROM directory WHERE mgrid = empno; RETURN mgrid; END; END; CREATE or REPLACE FUNCTION secure_updates(ns varchar2,na varchar2) RETURN VARCHAR2 IS Results VARCHAR2(100); BEGIN /* Only allow updates when designated application has set the session state to indicate we are inside it. */ IF (sys_context('hr_sec','adjstate') = 1) THEN results := 'mgr = SYS_CONTEXT("hr_sec","empno")'; ELSE results := '1=2'; END IF; RETURN Results; END; /* Attaches fine-grained access policy to all update operations on hr.directory */ CONNECT system/manager AS sysdba; BEGIN DBMS_RLS.ADD_POLICY('hr','directory_u','secure_update','hr', 'secure_updates','update',TRUE,TRUE); END;
In many application architectures, the middle tier application is responsible for managing session pooling for application users. That is, users authenticate themselves to the application, which uses a single identity to log into the database and maintains all the connections. In this environment, it is not possible to maintain application attributes using session-dependent secure application context because of the sessionless model of the application.
Another scenario is when a user is connected to the database through an application (such as Oracle Forms) which then spawns other applications (such as Oracle Reports) to connect to the database. These applications may need to share the session attributes such that they appear to be sharing the same database session.
Global application context is a type of secure application context that can be shared among trusted sessions. In addition to driving the enforcement of the fine-grained access control policies, applications (especially middle-tier products) can use this support to manage application attributes securely and globally.
Note: The public Java classes AppCtxManager and AppCtxMessages are exposed in package oracle.security.rdbms.appctx. This API provides a centralized location to store the user's application context. These classes are more fully described in Oracle9i Supplied Java Packages Reference. Related information can also be found in Oracle9i Supplied PL/SQL Packages and Types Reference. FA |
The DBMS_SESSION
interface for managing application context has a client identifier for each application context. In this way, application context can be managed globally, yet each client sees only his or her assigned application context. The following interfaces in DBMS_SESSION
enable the administrator to manage application context in client sessions:
The middle-tier application server can use SET_CONTEXT
to set application context for a specific client ID. Then, when assigning a database connection to process the client request, the application server needs to issue a SET_IDENTIFIER
to denote the ID of the application session. From then on, every time the client invokes SYS_CONTEXT
, only the context that was associated with the set identifier is returned. In other words, the application server uses SET_IDENTIFIER
to associate the database session with a particular user or a group. Then, the CLIENT_IDENTIFIER
is an attribute of the session and can be viewed in session information. Also, CLIENT_IDENTIFIER
is the key to accessing the global application context. For example, suppose a web-based application that provides information to business partners has three types of users: gold partner, silver partner, and bronze partner. These users represent different levels of available information. Instead of each user having their own setup session with application contexts, the application could set up global application contexts for gold partner, silver partner, and bronze partner. Afterwards, one can do the following:
SET_IDENTIFIER
to set a particular session to gold partner, silver partner, or bronze partner.The application need only initialize the three global contexts once, and use CLIENT_IDENTIFIER
to access the correct application context to limit data access. This provides performance improvements through session reuse, and through accessing global application contexts setup once, instead of having to initialize application contexts for each session.
For an application context accessed globally, the scenario is as follows:
12345
to client SCOTT
. It then issues the following statement to indicate that, for this client identifier, there is an application context RESPONSIBILITY
with a value of 13
in the HR
namespace.
DBMS_SESSION.SET_CONTEXT( 'HR', 'RESPONSIBILITY' , '13', 'SCOTT', '12345' );
Note that HR
must be a global context namespace created as follows:
CREATE CONTEXT hr USING hr.init ACCESSED GLOBALLY;
APPSMGR
to establish a connection to database, the following command should be issued when client SCOTT
is assigned to a new database session to indicate identity:
DBMS_SESSION.SET_IDENTIFIER('12345');
SYS_CONTEXT('HR','RESPONSIBILITY')
call, the database engine will match the client identifier 12345
to the global context, and return the value 13
.DBMS_SESSION.CLEAR_IDENTIFIER( );
After the client identifier in a session is clear, it takes on a NULL
value, implying that any subsequent SYS_CONTEXT
call will only retrieve application context with a NULL
client identifier, until the client identifier is set again using the SET_IDENTIFIER
interface.
For a proxy authentication application, the scenario is as follows:
CREATE CONTEXT hr USING hr.init ACCESSED GLOBALLY;
HR
application server (AS) starts up and establishes multiple connections to the HR
database as user APPSMGR
.SCOTT
logs on to the HR
application server.SCOTT
into the application.12345
, for this connection.SCOTT
's browser as part of a cookie or maintained by AS.
HR.INIT
package, which issues:
DBMS_SESSION.SET_CONTEXT( 'hr', 'id', 'scott', 'APPSMGR', 12345 ); DBMS_SESSION.SET_CONTEXT( 'hr', 'dept', 'sales', 'APPSMGR', 12345 );
DBMS_SESSION.SET_IDENTIFIER( 12345 );
SYS_CONTEXT
calls within this database session will return application context values belonging to the client session only. For example, SYS_CONTEXT('hr','id')
will return the value SCOTT
.DBMS_SESSION.CLEAR_IDENTIFIER ( );
Note that even if another database user (ADAMS
) had logged into the database, he cannot access the global context set by AS because AS has specified that only the application with logged in user APPSMGR
can see it. If AS has used the following, then any user session with client ID set to 12345
can see the global context.
DBMS_SESSION.SET_CONTEXT( 'hr', 'id', 'scott', NULL , 12345 ); DBMS_SESSION.SET_CONTEXT( 'hr', 'dept', 'sales', NULL , 12345 );
This approach enables different users to share the same context.
The users, however, should be aware of the security implication of different settings of the global context. Basically, NULL
in the username means that any user can access the global context. A NULL
client ID in the global context means that only a session with an uninitialized client ID can access the global context.
Users can query the client identifier set in the session as follows:
SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER')
The DBA can see which sessions have the client identifier set by querying the V$SESSION
view's CLIENT_IDENTIFIER
and USERNAME
.
When a user wants to see how much global context area (in bytes) is being used, she can use SYS_CONTEXT('USERENV','GLOBAL_CONTEXT_MEMORY')
See Also:
Oracle9i Supplied PL/SQL Packages and Types Reference Oracle9i JDBC Developer's Guide and Reference and Oracle Call Interface Programmer's Guide for client identifier information |
This feature lets you specify a special type of namespace that accepts initialization of attribute values from external resources. This enhances performance and enables the automatic propagation of attributes from one session to the other. For example, many organizations want to manage user information centrally, in an LDAP-based directory. Oracle9i Enterprise User Security feature supports centralized user and authorization management in Oracle Internet Directory. However, there may be additional attributes an application wishes to retrieve from LDAP to use for VPD enforcement:
The ability to initialize application context from external sources such as LDAP helps organizations leverage existing information they have for VPD enforcement, that is centrally managed, without requiring replication or duplication of this information in database tables.
This section contains these topics:
In some situations it is desirable to obtain default values from users. These default values may serve as hints or preferences initially, and may become trusted context after the values are validated. Similarly, clients may want a convenient way to initialize some default values, and then rely on a login event trigger or applications to validate the values.
For job queues, administrators may expect the job submission routine to record all the context being set at the time the job is submitted, and restore it when executing the batched job. To maintain the integrity of context, job queues cannot bypass the designated PLSQL package to set the context. Rather, externally initialized application context accepts initialization of context values from the job queue process.
Whereas automatic propagation of context to a remote session may create security problems, developers or administrators can effectively handle this new type of context that takes default values from resources other than the designated PLSQL procedure. In addition, performance is enhanced because this feature provides an extensible interface for the OCI client to bundle more information to the server in one OCISessionBegin()
call.
In addition to using the designated trusted package, externally initialized application context can also accept initialization of attributes and values through external resources such as an OCI interface, a job queue process, or a database link. It provides:
Although this new type of namespace can be initialized by any client program using OCI, there are login event triggers that can verify the values. It is up to the application to interpret and trust the values of the attributes.
Note that with this feature, the middle-tier server can actually initialize context values on behalf of database users. Context attributes are propagated for the remote session at initiation time, and the remote database accepts the values if the namespace is externally initialized.
Externally initialized application context is especially useful for cases in which users are not known to the database. In these situations, the application typically connects as a single database user, and all actions are taken as that user. Since all user sessions are created as the same user, this security model normally makes it very difficult, if not impossible, to use the Virtual Private Database capability to achieve per user or per customer data separation. However, these applications can use the client identifier as an application user proxy. In this way, the application uses the client identifier to proxy the "real" application user name to the database.
This approach has several advantages. With application user proxy, the sessions can be reused by multiple users merely by changing the client identifier (which here is employed to capture the name of the real application user). This avoids the overhead of setting up a separate session and separate attributes for the user, and enables reuse of sessions by the application merely by changing the client identifier (to represent the new application user name). When a client changes the client identifier, the change is piggybacked on the next OCI (or thick JDBC) call, for additional performance gains. Application user proxy (via client identifier) is available in available in OCI, thick JDBC, and thin JDBC.
Suppose, for example, that user Daniel connects to a Web Expense application. Daniel is not a database user, he is a typical Web Expense application user. The application sets up a global application context for a typical web user and sets DANIEL
as the client identifier. Daniel completes his Web Expense form and exits the application. Ajit now connects to the Web Expense application. Instead of setting up a new session for Ajit, the application reuses the session that currently exists for Daniel, merely by changing the client identifier to AJIT
. This avoids both the overhead of setting up a new connection to the database, and the overhead of initializing a new application context.
Note that the client identifier can be anything the application wishes to base access control upon; it need not be an application username.
Another way in which the client identifier can be used for applications whose users are not database users, is to use the client identifier as a type of group or role mechanism. For example, suppose a Marketing application has three types of users: standard partners, silver partners, and gold partners. The application could use the global application context feature to set up three types of contexts (standard, silver, and gold). The application then determines which type of partner a user is, and, passes the client identifier to the database for a session. The client identifier (standard, silver, or gold) here acts like a pointer to the correct application context. There may be multiple sessions that are silver, for example, and yet they all share the same application context.
This feature provides a centralized location to store the user's application context, enabling applications to set up the user's contexts during initialization based upon the user's identity. In particular, it supports Oracle Label Security labels and privileges. This feature makes it much easier for the administrator to manage contexts for large numbers of users and databases.
This section contains these topics:
Application context initialized globally utilizes the Lightweight Directory Access Protocol (LDAP). LDAP is a standard, extensible, and efficient directory access protocol. The LDAP directory stores a list of users to which this application is assigned. Oracle9i can use Oracle Internet Directory as the directory service for authentication and authorization of enterprise users. (Note that enterprise user security requires Oracle Advanced Security.)
The LDAP object orclDBApplicationContext
(a subclass of groupOfUniqueNames
) has been defined to store the application context values in the directory. The location of the application context object is described in Figure 12-1, which is based upon the Human Resources example.
Note that an internal C function is required to retrieve the orclDBApplicationContext
value. A list of application context values is returned to RDBMS.
Note: In this example, HR is the namespace, Title and Project are the attributes, and Manager and Promotion are the values. |
The administrator sets up the user's global application context values at the database and the directory.
When a global user connects to the database, the Oracle Advanced Security option performs authentication to verify the identity of the user connecting to the database. Once the identification is completed, the user's global roles are retrieved from LDAP. Then the user's global application context is retrieved from LDAP. Thus, when the user logs on to the database, her global roles and initial application context are already set up.
The initial application context for a user, such as department name, level (title) can be set up and stored in the LDAP directory. The values are retrieved during user login so that the context is set properly. In addition, any information related to the user is retrieved and stored in the application context namespace SYS_USER_DEFAULTS
. The following example shows how this is done.
CREATE CONTEXT HR USING hrapps.hr_manage_pkg INITIALIZED GLOBALLY;
An example of the entries added to the LDAP directory follows. These entries create an attribute name Title
with attribute value Manager
for the application (namespace) HR
, and assign usernames user1
and user2
.
dn: cn=OracleDBAppContext,cn=myDomain,cn=OracleDBSecurity,cn=Products,cn=OracleC ontext,ou=Americas,o=oracle,c=US changetype: add cn: OracleDBAppContext objectclass: top objectclass: orclContainer dn: cn=HR,cn=OracleDBAppContext,cn=myDomain,cn=OracleDBSecurity,cn=Products,cn=O OracleContext,ou=Americas,o=oracle,c=US changetype: add cn: HR objectclass: top objectclass: orclContainer dn: cn=Title,cn=HR,cn=OracleDBAppContext,cn=myDomain,cn=OracleDBSecurity,cn=Prod ucts,cn=OracleContext,ou=Americas,o=oracle,c=US changetype: add cn: Title objectclass: top objectclass: orclContainer dn: cn=Manager,cn=Title,cn=HR,cn=OracleDBAppContext,cn=myDomain,cn=OracleDBSecur ity,cn=Products,cn=OracleContext,ou=Americas,o=oracle,c=US cn: Manager objectclass: top objectclass: groupofuniquenames objectclass: orclDBApplicationContext uniquemember: CN=user1,OU=Americas,O=Oracle,L=Redwoodshores,ST=CA,C=US uniquemember: CN=user2,OU=Americas,O=Oracle,L=Redwoodshores,ST=CA,C=US
inetOrgPerson
object entry exists for the user, the connection will also retrieve all the attributes from inetOrgPerson
and assign them to the namespace SYS_LDAP_USER_DEFAULT
. The following is an example of an inetOrgPerson
entry:
dn: cn=user1,ou=Americas,O=oracle,L=redwoodshores,ST=CA,C=US
changetype: add
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
cn: user1
sn: One
givenName: User
initials: UO
title: manager, product development
uid: uone
mail: uone@us.oracle.com
telephoneNumber: +1 650 123 4567
employeeNumber: 00001
employeeType: full time
When user1
connects to a database that belongs to domain myDomain
, user1
will have his Title
set to Manager
. Any information related to user1
will be retrieved from the LDAP directory. The value can be obtained using the syntax
SYS_CONTEXT('namespace','attribute name')
For example:
DECLARE tmpstr1 VARCHAR2(30); tmpstr2 VARCHAR2(30); BEGIN tmpstr1 = SYS_CONTEXT('HR','TITLE); tmpstr2 = SYS_CONTEXT('SYS_LDAP_USER_DEFAULT','telephoneNumber'); DBMS_OUTPUT.PUT_LINE('Title is ' || tmpstr1); DBMS_OUTPUT.PUT_LINE('Telephone Number is ' || tmpstr2); END;
The output of the above example is:
Title is Manager Telephone Number is +1 650 123 4567
Fine-grained access control allows you to build applications that enforce security policies at a low level of granularity. You can use it, for example, to restrict a customer who is accessing an Oracle server to see only his own account, a physician to see only the records of her own patients, or a manager to see only the records of employees who work for him.
When you use fine-grained access control, you create security policy functions attached to the table, view, or synonym on which you have based your application. Then, when a user enters a DML statement (SELECT
, INSERT
, UPDATE
, or DELETE
) on that object, Oracle dynamically modifies the user's statement--transparently to the user--so that the statement implements the correct access control.
This section covers:
Fine-grained access control provides the following capabilities:
Attaching security policies to tables, views, or synonyms rather than to applications provides greater security, simplicity, and flexibility.
Attaching a policy to a table, view, or synonym overcomes a potentially serious application security problem. Suppose a user is authorized to use an application, and then, drawing on the privileges associated with that application, wrongfully modifies the database by using an ad hoc query tool, such as SQL*Plus. By attaching security policies to tables, views, or synonyms, fine-grained access control ensures that the same security is in force, no matter how a user accesses the data.
Adding the security policy to the table, view, or synonym means that you make the addition only once, rather than repeatedly adding it to each of your table-, view-, or synonym-based applications.
You can have one security policy for SELECT
statements, another for INSERT
statements, and still others for UPDATE
and DELETE
statements. For example, you might want to enable a Human Resources clerk to SELECT
all employee records in her division, but to UPDATE
only salaries for those employees in her division whose last names begin with "A" through "F".
Note: Although you can define a policy against a table, you cannot select that table from within the policy that was defined against the table. |
You can establish several policies for the same table, view, or synonym. Suppose, for example, you have a base application for Order Entry, and each division of your company has its own special rules for data access. You can add a division-specific policy function to a table without having to rewrite the policy function of the base application.
Note that all policies applied to a table are enforced with AND
syntax. Thus, if you have three policies applied to the CUSTOMERS
table, each policy is applied to any access of the table. You can use policy groups and a driving application context to partition fine-grained access control enforcement so that different policies apply, depending upon which application is accessing data. This eliminates the requirement for development groups to collude on policies and simplifies application development. You can also have a default policy group that always applies (for example, to enforce data separate by subscriber, in a hosting environment).
Since multiple applications, with multiple security policies, can share the same table, view, or synonym, it is important to identify those policies which should be in effect when the table, view, or synonym is accessed.
For example, in a hosting environment, Company A can host the BENEFIT
table for Company B and Company C. The table is accessed by two different applications, HUMAN RESOURCES and FINANCE, with two different security policies. The HUMAN RESOURCES application authorizes users based on ranking in the company, and the FINANCE application authorizes users based on department. To integrate these two policies into the BENEFIT table would require joint development of policies between the two companies, which is not a feasible option. By defining an application context to drive the enforcement of a particular set of policies to the base objects, each application can implement a private set of security policies.
To do this, you can organize security policies into groups. By referring to the application context, the Oracle server determines which group of policies should be in effect at runtime. The server enforces all the policies which belong to that policy group.
With fine-grained access control, each policy function for a given query is evaluated only once, at statement parse time. Also, the entire dynamically modified query is optimized and the parsed statement can be shared and reused. This means that rewritten queries can take advantage of Oracle's high performance features, such as dictionary caching and shared cursors.
While partitioning security policies by application is desirable, it is also useful to have security policies that are always in effect. In the previous example, a hosted application can always enforce data separation by subscriber_ID
, whether you are using the Human Resources application or the Finance application. Default security policies allow developers to have base security enforcement under all conditions, while partitioning of security policies by application (using security groups) enables layering of additional, application-specific security on top of default security policies. To implement default security policies, you add the policy to the SYS_DEFAULT
policy group.
Fine-grained access control is based on dynamically modified statements, similar to the example described in this section. Suppose you want to attach to the ORDERS_TAB
table the following security policy: "Customers can see only their own orders." The process is described in this section.
Note: A predicate is the |
In this case, you might create a function that adds the following predicate:
Cust_no = (SELECT Custno FROM Customers WHERE Custname = SYS_CONTEXT ('userenv','session_user'))
SELECT * FROM Orders_tab;
SELECT * FROM Orders_tab WHERE Custno = ( SELECT Custno FROM Customers WHERE Custname = SYS_CONTEXT('userenv', 'session_user'))
Upon execution, the function employs the username returned by SYS_CONTEXT ('userenv','session_user')
to look up the corresponding customer and to limit the data returned from the ORDERS_TAB
table to that customer's data only.
See Also:
For more information on using fine-grained access control, see "Introduction to Application Context Accessed Globally", as well as Oracle9i Supplied PL/SQL Packages and Types Reference. |
A policy group is a set of security policies which belong to an application. You can designate an application context (known as a driving context) to indicate the policy group in effect. Then, when the table, view, or synonym is accessed, the server looks up the driving context (which are also known as policy context) to determine the policy group in effect. It enforces all the associated policies which belong to that policy group.
This section contains the following topics:
In the Oracle Policy Manager tree structure, the Fine-Grained Access Control Policies folder contains the Policy Groups folder. The Policy Groups folder contains an icon for each policy group, as well as an icon for the SYS_DEFAULT policy group.
By default, all policies belong to the SYS_DEFAULT
policy group. Policies defined in this group for a particular table, view, or synonym will always be executed along with the policy group specified by the driving context. The SYS_DEFAULT policy group may or may not contain policies. If you attempt to drop the SYS_DEFAULT policy group, an error will be raised.
If, to the SYS_DEFAULT policy group, you add policies associated with two or more objects, then each such object will have a separate SYS_DEFAULT policy group associated with it. For example, the EMP table in the SCOTT schema has one SYS_DEFAULT policy group, and the DEPT table in the SCOTT schema has a different SYS_DEFAULT policy group associated with it. These are displayed in the tree structure as follows:
SYS_DEFAULT - policy1 (SCOTT/EMP) - policy3 (SCOTT/EMP) SYS_DEFAULT - policy2 (SCOTT/DEPT)
When adding the policy to a table, view, or synonym, you can use the DBMS_RLS.ADD_GROUPED_POLICY
interface to specify the group to which the policy belongs. To specify which policies will be effective, you add a driving context using the DBMS_RLS.ADD_POLICY_CONTEXT
interface. If the driving context returns an unknown policy group, an error is returned.
If the driving context is not defined, then all policies are executed. Likewise, if the driving context is NULL
, then policies from all policy groups are enforced. In this way, an application accessing the data cannot bypass the security setup module (which sets up application context) to avoid any applicable policies.
You can apply multiple driving contexts to the same table, view, or synonym, and each of them will be processed individually. In this way you can configure multiple active sets of policies to be enforced.
Consider, for example, a hosting company that hosts Benefits and Financial applications, which share some database objects. Both applications are striped for hosting using a SUBSCRIBER
policy in the SYS_DEFAULT
policy group. Data access is partioned first by subscriber ID, then by whether the user is accessing the Benefits or Financial applications (determined by a driving context). Suppose that Company A, which uses the hosting services, wants to apply a custom policy which relates only to its own data access. You could add an additional driving context (such as COMPANY A SPECIAL) to ensure that the additional, special policy group is applied for Company A's data access only. You would not apply this under the SUBSCRIBER
policy, since the policy relates only to Company A, and it is cleaner to segregate the basic hosting policy from other policies.
Alternatively, with the Oracle Policy Manager graphical user interface, accessed from Oracle Enterprise Manager, you can create a policy group by using the DBMS_RLS.CREATE_POLICY_GROUP
command line procedure.
To create policy groups, the administrator must do two things:
The following example shows how to perform these tasks.
Begin by creating a namespace for the driving context. For example:
CREATE CONTEXT appsctx USING apps.apps_security_init;
Create the package that administers the driving context. For example:
CREATE OR REPLACE PACKAGE BODY apps.apps_security_init PROCEDURE setctx ( policy_group varchar2 ) BEGIN REM Do some checking to determine the current application. REM You can check the proxy if using the proxy authentication feature. REM Then set the context to indicate the current application. . . . DBMS_SESSION.SET_CONTEXT('APPSCTX','ACTIVE_APPS', policy_group); END; END;
Define the driving context for the table APPS.BENEFIT
.
DBMS_RLS.ADD_POLICY_CONTEXT('apps','benefit','APPSCTX','ACTIVE_APPS')
Create a security function to return a predicate to divide the data by company.
CREATE OR REPLACE FUNCTION by_company (schema varchar2, table varchar2) RETURN VARCHAR2; BEGIN RETURN 'COMPANY = SYS_CONTEXT(''ID'',''MY_COMPANY'')'; END;
Since policies in SYS_DEFAULT
are always executed (except for SYS
, or users with the EXEMPT ACCESS POLICY
system privilege), this security policy (named SECURITY_BY_COMPANY
), will always be enforced regardless of the application running. This achieves the universal security requirement on the table: namely, that each company should see its own data, regardless of the application running. The function APPS.APPS_SECURITY_INIT.BY_COMPANY
returns the predicate to make sure that you can only see your company's data.
DBMS_RLS.ADD_GROUPED_POLICY('apps','benefit','SYS_DEFAULT', 'security_by_company', 'apps','by_company');
First, create the HR
group:
CREATE OR REPLACE FUNCTION hr.security_policy RETURN VARCHAR2; AS BEGIN RETURN 'SYS_CONTEXT(''ID'',''TITLE'') = ''MANAGER'' '; END; DBMS_RLS.CREATE_POLICY_GROUP('apps','benefit','HR');
The following adds a policy named HR_SECURITY
to the HR
policy group. The function HR.SECURITY_POLICY
returns the predicate to enforce HR's security on the table APPS.BENEFIT
:
DBMS_RLS.ADD_GROUPED_POLICYS('apps','benefit','HR', 'hr_security','hr','security_policy');
Create the FINANCE
policy:
CREATE OR REPLACE FUNCTION finance.security_policy RETURN VARCHAR2; AS BEGIN RETURN 'SYS_CONTEXT(''ID'',''DEPT'') = ''FINANCE'' '; END;
Create a policy group named FINANCE
:
DBMS_RLS.CREATE_POLICY_GROUP('apps','benefit','FINANCE');
Add the FINANCE
policy to the FINANCE
group:
DBMS_RLS.ADD_GROUPED_POLICY('apps','benefit','FINANCE', 'finance_security','finance', 'security_policy');
As a result, when the database is accessed, the application initializes the driving context after authentication. For example, with the HR
application:
execute apps.security_init.setctx('HR');
In this regard, one factor is extremely important: The package implementing the driving context must correctly validate the application which is being used. Although the database always ensures that the package implementing the driving context sets context attributes (by checking the call stack), this fact cannot protect against poor or inadequate validation within the package.
For example, in applications where database users or enterprise users are known to the database, the user needs EXECUTE
privilege on the package which sets the driving context. Consider a user who knows that:
BENEFITS
application allows more liberal access than its HR
application, andsetctx
procedure (which sets the correct policy group within the driving context) does not perform any validation to determine which application is actually connecting. That is, the procedure does not check the IP address of the incoming connection (for a three-tier system), or, even better, the proxy_user
attribute of the user session.In this situation, the user could pass to the driving context package an argument (BENEFITS
) which would set the context to the more liberal BENEFITS
policy group--even though this user will, in fact, access the HR
application. In this way the user can bypass the intended, more restrictive security policy simply because the package does inadequate validation.
If, by contrast, you implement proxy authentication with VPD, you can determine the identity of the middle tier (and thus, the application) which is actually connecting to the database on a user's behalf. In this way, the correct, per-application policy will be applied to mediate data access. For example, a developer using the proxy authentication feature could determine that the application (that is, the middle tier) connecting to the database is HRAPPSERVER
. The package which implements the driving context can thus verify that the proxy_user
in the user session is HRAPPSERVER
before setting the driving context to use the HR
policy group, or can disallow access if proxy_user
is not HRAPPSERVER
.
In this case, when the following query is executed
SELECT * FROM APPS.BENEFIT;
Oracle picks up policies from the default policy group (SYS_DEFAULT
) and active namespace HR
. The query is internally rewritten as follows:
SELECT * FROM APPS.BENEFIT WHERE COMPANY = SYS_CONTEXT('ID','MY_COMPANY') and SYS_CONTEXT('ID','TITLE') = 'MANAGER';
The DBMS_RLS
package enables you to administer security policies. The procedures inside this package allow you to specify the table, view, or synonym to which you are adding a policy and various data pertinent to that policy. These data include the names of the policy and the policy group, the function implementing the policy, and the type of statement the policy controls (that is, SELECT
, INSERT
, UPDATE
, or DELETE
), and additional information. The package includes the following procedures:
Alternatively, you can use Oracle Policy Manager to administer security policies.
V$VPD_POLICY
allows one to perform a dynamic view in order to check what policies are being applied to a SQL statement. When debugging, in your attempt to find which policy corresponds to a particular SQL statement, you should use the following table.
The system privilege EXEMPT ACCESS POLICY
allows a user to be exempted from all fine-grained access control policies on any DML operation (SELECT
, INSERT
, UPDATE
, and DELETE
). This provides ease of use for such administrative activities as installation, and import and export of the database through a non-SYS
schema.
Also, regardless of the utility or application that is being used, if a user is granted the EXEMPT ACCESS POLICY
privilege, then the user is exempt from VPD and Oracle Label Security policy enforcement. That is, the user will not have any VPD or Oracle Label Security policies applied to their data access.
Since EXEMPT ACCESS POLICY
negates the effect of fine-grained access control, this privilege should only be granted to users who have legitimate reasons for bypassing fine-grained security enforcement. This privilege should not be granted WITH ADMIN OPTION
, so that users cannot pass on the EXEMPT ACCESS POLICY
privilege to other users, and thus propagate the ability to bypass fine-grained access control.
Starting from 9i, queries against Fine Grained Access enabled objects always execute the policy function to make sure most up to date predicate is used for each policy. For example, in case of the time based policy function, in which queries are only allowed between 8am-5pm, an execute of a cursor that is parsed at noon would result in an execution of the policy function at the execution time to make sure policy function is consulted again for the query.
There are only two exceptions to this rule. One is to specify STATIC_POLICY=TRUE when adding the policy to indicate that the policy function always returns the same predicate. Another one is for users whose security policies do not return different predicate within a database session, the init.ora parameter _dynamic_rls_policies can be set to FALSE to reduce the execution overhead.
For deployment environments where latest application context value is always the desired value, init.ora parameter _app_ctx_vers can be set to FALSE to reduce overhead of application context scoping. By default, it is TRUE, and changes of value within a SQL is not visible. This default may change in the future, thus developers should be careful not to allow changes of application context values within a SQL statement using a user defined function, just like other Write No Database State requirements of user defined function executed within a SQL. In general, users should not depend on order of execution in a SQL statement as this could yield inconsistent result depending on query plans.
Note that these two parameters may be deprecated in coming releases when there is new functionality to replace them.
This section describes fine-grained auditing in the context of Oracle9i auditing capabilities. It contains the following sections:
Standard Oracle9i auditing monitors privileges and objects, and provides triggers to monitor DML operations such as INSERT
, UPDATE
, and DELETE
. By contrast, monitoring SELECT
statements is facilitated by fine-grained auditing, which allows the monitoring of data access based on content. In this way, you can specify auditing conditions, and obtain more specific information about the environment and query result. This additional information helps you reconstruct audited events, and determine whether access rights have been violated.
For example, a drug enforcement agency needs detailed tracking of access to its informants database. Likewise, a central tax authority needs to track access to tax returns in order to guard against employee snooping. Such agencies need enough detail to determine what data was accessed, not simply that the SELECT
privilege was used by SCOTT
on the INFORMANTS
table. Fine-grained auditing can provide that level of detail.
Oracle provides over 170 configurable auditing options for accountability of users and servers. The Oracle9i audit facility allows you to audit database activity by statement, by use of system privilege, by object, or by user, including system administrators. For example, you can audit activity as general as all user connections to the database, and as specific as a particular user creating a table. You can audit only successful operations, or only unsuccessful operations. Auditing unsuccessful SELECT
statements may find users attempting to access data that they are not privileged to see.
Although auditing is highly configurable, standard audit options do not include a lot of detail about the audited events. Typically, an audit record identifies the user, the object accessed, the privilege used, whether the access was successful or unsuccessful, and a timestamp.
You can use triggers to record customized information that is not automatically included in audit records. In this way, you can further design your own audit auditing conditions and audit record contents. For example, you could define a trigger on the EMP
table to generate an audit record whenever an employee's salary is increased by more than 10 percent. This can include selected information, such as before and after values of SALARY
:
CREATE TRIGGER audit_emp_salaries AFTER INSERT OR DELETE OR UPDATE ON employee_salaries for each row begin if (:new.salary> :old.salary * 1.10) then insert into emp_salary_audit values ( :employee_no, :old.salary, :new.salary, user, sysdate); endif; end;
Furthermore, you can use event triggers to enable auditing options for specific users on login, and disable them upon logoff.
In some cases, businesses may actually need to capture the statement executed as well as the result set from a query. Fine-grained auditing provides an extensible auditing mechanism that supports definition of key conditions for granular audit, as well as an event handler to actively alert administrators to misuse of data access rights.
Oracle9i also gives you the option of sending audit records to the database audit trail or your operating system's audit trail, when the operating system is capable of receiving them. The audit trail for database administrators, for example, is typically written to a secure location in the operating system. Writing audit trails to the OS provides a way for a separate auditor who is root on the OS to hold all DBAs (who don't have root access) accountable for their actions. These options, added to the broad selection of audit options and customizable triggers or stored procedures, give you the flexibility to implement an auditing scheme that suits your specific business needs.
A more granular level of auditing can be achieved with a fine-grained auditing mechanism. This employs simple, user-defined SQL predicates on table objects as conditions for selective auditing. During fetching, whenever policy conditions are met for returning a row from a query block, the query is audited.
Fine-grained auditing allows organizations to define audit policies, which specify the data access conditions that trigger the audit event, and use a flexible event handler to notify administrators that the triggering event has occurred. For example, an organization may allow HR clerks to access employee salary information, but trigger an audit event when salaries are greater than $500K are accessed. The audit policy (where SALARY > 500000) is applied to the EMPLOYEES table through an audit policy interface (a PL/SQL package).
For additional flexibility in implementation, organizations can employ a user-defined function to determine the policy condition, and identify an audit column to further refine the audit policy. For example, the function could allow unaudited access to any salary as long as the user is accessing data within the intranet, but audit access to executive-level salaries when they are accessed from the internet. A relevant column helps reduce the instances of false or unnecessary audit records, because the audit need only be triggered when a particular column is referenced in the query. For example, an organization may only wish to audit executive salary access when an employee name is accessed, because accessing salary information alone is not meaningful unless an HR clerk also selects the corresponding employee name.
You can use the PLSQL package DBMS_FGA
to administer these fine-grained audit policies. If any rows returned from a query block match the audit condition, these rows are identified as interested rows. An audit event entry, including username, SQL text, policy name, session id, timestamp, and other attributes, is inserted into the audit trail. You can optionally define an audit event handler to process the event. For example, the event handler could send an alert page to the administrator.
The following example shows how you can audit SELECT
statements on table hr.emp to monitor any query that accesses the salary column of the employee records which belong to sales department:
DBMS_FGA.ADD_POLICY( object_schema => 'hr', object_name => 'emp', policy_name => 'chk_hr_emp', audit_condition => 'dept = ''SALES'' ', audit_column => 'salary');
Then, either of the following SQL statements will cause the database to log an audit event record.
SELECT count(*) FROM hr.emp WHERE dept = 'SALES' and salary > 10000000;
or
SELECT salary FROM hr.emp WHERE dept = 'SALES';
With all the relevant information available, and a trigger-like mechanism to use, the administrator can define what to record and how to process the audit event.
Consider what happens when the following commands are issued. After the fetch of the first interested row, the event is recorded, and the audit function SEC.LOG_ID
is executed. The audit event record generated is stored in DBA_FGA_AUDIT_TRAIL
, which has reserved columns for recording SQL text, policy name, and other information.
/* create audit event handler */ CREATE PROCEDURE sec.log_id (schema varchar2, table varchar2, policy varchar2) AS BEGIN UTIL_ALERT_PAGER(schema, table, policy); -- send an alert note to my pager END; /* add the policy */ DBMS_FGA.ADD_POLICY( object_schema => 'hr', object_name => 'emp', policy_name => 'chk_hr_emp', audit_condition => 'dept = ''SALES'' ', audit_column => 'salary', handler_schema => 'sec', handler_module => 'log_id', enable => TRUE);
This section contains information about enforcing application security. This section consists of the following topics:
Prebuilt database applications explicitly control the potential actions of a user, including the enabling and disabling of the user's roles while using the application. By contrast, ad hoc query tools, such as SQL*Plus, allow a user to submit any SQL statement (which may or may not succeed), including the enabling and disabling of any granted role.
An application user can potentially exercise the privileges attached to that application to issue destructive SQL statements against database tables by using an ad hoc tool.
For example, consider the following scenario:
VACATION
role.VACATION
role includes the privileges to issue SELECT
, INSERT
, UPDATE
, and DELETE
statements against the EMP_TAB
table.VACATION
role.Now, consider a user who has been granted the VACATION
role. Suppose that, instead of using the Vacation application, the user executes SQL*Plus. At this point, the user is restricted only by the privileges granted to him explicitly or through roles, including the VACATION
role. Because SQL*Plus is an ad hoc query tool, the user is not restricted to a set of predefined actions, as with designed database applications. The user can query or modify data in the EMP_TAB
table as he or she chooses.
This section presents features that you may use in order to restrict database roles from SQL*Plus users and thus, prevent serious security problems. These features include the following:
Oracle9i offers some capability to limit what roles a user accesses through an application, through the PRODUCT_USER_PROFILE
table.
DBAs can use PRODUCT_USER_PROFILE
to disable certain SQL and SQL*Plus commands in the SQL*Plus environment on a per-user basis. SQL*Plus, not Oracle, enforces this security. DBAs can even restrict access to the GRANT
, REVOKE
, and SET ROLE
commands in order to control users' ability to change their database privileges.
The PRODUCT_USER_PROFILE
table enables you to list roles which you do not want users to activate with an application. You can also explicitly disable use of various commands, such as SET ROLE
. For example, you could create an entry in the PRODUCT_USER_PROFILE
table to:
Suppose user Jane connects to the database using SQL*Plus. Jane has the CLERK
, MANAGER
, and ANALYST
roles. As a result of the above entry in PRODUCT_USER_PROFILE
, Jane is only able to exercise her ANALYST
role with SQL*Plus. Also, when Jane attempts to issue a SET ROLE
statement, she is explicitly prevented from doing so because of the entry in the PRODUCT_USER_PROFILE
table prohibiting use of SET ROLE
.
Use of the PRODUCT_USER_PROFILE
table does not completely guarantee security, for multiple reasons. In the above example, while SET ROLE
is disallowed with SQL*Plus, if Jane had other privileges granted to her directly, she could exercise these using SQL*Plus.
.
See Also:
SQL*Plus User's Guide and Reference for more information about the |
Stored procedures encapsulate use of privileges with business logic so that privileges are only exercised in the context of a well-formed business transaction. For example, an application developer might create a procedure to update employee name and address in EMPLOYEES
table, which enforces that the data can only be updated in normal business hours. Also, rather than grant an human resources clerk the UPDATE
privilege on the EMPLOYEES
table, a developer (or application administrator) may grant the privilege on the procedure only. Then, the human resources clerk can exercise the privilege only in the context of the procedures, and cannot update the EMPLOYEES
table directly.
Oracle9i enables you to enforce security, to a fine level of granularity, directly on tables, views, or synonyms by implementing Virtual Private Database (VPD). Because security policies are attached directly to tables, views, or synonyms and automatically applied whenever a user accesses data, there is no way to bypass security.
Strong security policies, centrally managed and applied directly to data, can enforce security no matter how a user gets to the data: whether through an application, through a query, or by using a report-writing tool.
When a user directly or indirectly accesses a table, view, or synonym associated with a VPD security policy, the server dynamically modifies the user's SQL statement. The modification is based on a WHERE
condition (known as a predicate) returned by a function which implements the security policy. The statement is modified dynamically, transparently to the user, using any condition which can be expressed in, or returned by a function.
Functions which return predicates can also include callouts to other functions. Within your PL/SQL package, you can embed a C or Java callout that can either access operating system information, or return WHERE
clauses from an operating system file or central policy store. A policy function can return different predicates for each user, for each group of users, or for each application. Using policy functions over synonyms can substitute for maintaining a separate view for each user or class of users, saving substantial overhead in memory and processing resources.
Application context enables you to securely access the attributes on which you base your security policies. For example, users with the position attribute of manager
would have a different security policy than users with the position attribute of employee
.
Consider an HR clerk who is only allowed to see employee records in the Aircraft Division. When the user initiates the query
SELECT * FROM emp;
the function implementing the security policy returns the predicate division = `AIRCRAFT'
, and the database transparently rewrites the query. The query actually executed becomes:
SELECT * FROM emp WHERE division = `AIRCRAFT';
The security policy is applied within the database itself, rather than within an application. This means that use of a different application will not bypass the security policy. Security can thus be built once, in the database, instead of being reimplemented in multiple applications. Virtual Private Database therefore provides far stronger security than application-based security, at a lower cost of ownership.
It may be desirable to enforce different security policies depending on which application is accessing data. Consider a situation in which two applications, Order Entry and Inventory, both access the ORDERS
table. You may want to have the Inventory application apply to the table a policy which limits access based on type of product. At the same time, you may want to have the Order Entry application apply to the same table a policy which limits access based on customer number.
In this case, you must partition the use of fine-grained access by application. Otherwise, both policies would be automatically AND
ed together--which is not the desired result. You can specify one or more policy groups, and a driving application context that determines which policy group is in effect for a given transaction. You can also designate default policies which always apply to data access. In a hosted application, for example, data access should always be limited by subscriber ID.
Virtual Private Database and Oracle Label Security are not enforced during DIRECT path export. Also, Virtual Private Database policies and Oracle Label Security policies cannot be applied to objects in schema SYS. As a consequence, the SYS
user and users making a DBA-privileged connection to the database (for example, CONNECT/AS SYSDBA
) do not have VPD or Oracle Label Security policies applied to their actions. Database administrators need to be able to administer the database. It would not be acceptable to export part of a table due to a VPD policy being applied. SYSDBA actions are auditable, however, by enabling such auditing upon installation and specifying that this audit trail be stored in a secure location in the operating system.
Database users who are granted the Oracle9i EXEMPT ACCESS POLICY privilege, directly or through a database role, are exempt from Virtual Private Database and Oracle Label Security enforcement. The users are exempt from Virtual Private Database and Oracle Label Security enforcement regardless of the export mode, application, or utility used to extract data from the database. EXEMPT ACCESS POLICY privilege is a powerful privilege and should be carefully managed. It is usually inadvisable to grant this privilege WITH ADMIN OPTION because very few users should have this exemption.
|
Copyright © 1996, 2002 Oracle Corporation. All Rights Reserved. |
|