FOR r IN SELECT TO_CHARchannel_id channel_id FROM bi_tables.channel_managers WHERE upperuser_name = upperv_channel_manager ORDER BY 1 LOOP v_return := v_return || r.channel_id ||
Trang 1are returned The other important thing to notice in this package is the VPD tagging function
called VPD_TAG:
CREATE OR REPLACE
PACKAGE bi_select.channel_policy
AS
FUNCTION vpd_whereclause
(
schema_name IN VARCHAR2,
object_name IN VARCHAR2)
RETURN VARCHAR2;
FUNCTION vpd_tag
(
v_channel_manager IN VARCHAR2)
RETURN VARCHAR2;
END;
/
CREATE OR REPLACE
PACKAGE body bi_select.channel_policy
AS
FUNCTION vpd_whereclause
(
schema_name IN VARCHAR2,
object_name IN VARCHAR2)
RETURN VARCHAR2
AS
v_whereclause VARCHAR2(2000):='';
v_client_id VARCHAR2(30) :='';
BEGIN
SELECT sys_context('USERENV','CLIENT_IDENTIFIER')
INTO v_client_id
FROM dual;
IF v_client_id IS NOT NULL THEN
v_whereclause := 'channel_id in
(select channel_id from bi_tables.channel_managers where upper(bi_tables.channel_managers.user_name) = upper('''|| v_client_id||'''))';
ELSE
v_whereclause := '1=0';
END IF;
RETURN v_whereclause;
END;
FUNCTION vpd_tag
(
v_channel_manager IN VARCHAR2)
RETURN VARCHAR2
AS
v_return VARCHAR2(2000) := NULL;
Trang 2FOR r IN
(SELECT TO_CHAR(channel_id) channel_id
FROM bi_tables.channel_managers
WHERE upper(user_name) = upper(v_channel_manager)
ORDER BY 1
)
LOOP
v_return := v_return || r.channel_id || ';';
END LOOP;
IF v_return IS NOT NULL THEN
v_return := SUBSTR(v_return,1,LENGTH(v_return)-1);
END IF;
RETURN v_return;
END;
END;
/
The tag on the Oracle BI cache entry will consist of the values of the security sensitive session variables for the user that issued the query Figure 14-15 shows the definition of the session variable
VPD_TAG—notice that Security Sensitive is selected The code to populate this session variable,
in the initialization block GET_VPD_TAG, makes use of the VPD tagging function:
select channel_policy.vpd_tag(':USER')
from dual
FIGURE 14-15 The security session variable VPD_TAG that will be used to tag cache entries
Trang 3For the user BICHANNEL1, the VPD_TAG session variable is set to 9, and for users
BICHANNEL2 and BICHANNEL3, the value is set to 4 When we test this, we should see
that out of these three users, only BICHANNEL2 and BICHANNEL3 can share cache entries The mechanism for tagging the cache entries is the key to ensuring the Oracle BI cache does not violate VPD policies If the effect of the VPD policy will yield different results for two different users, then the VPD tag should use different values for these two users Because the logic that defines the VPD tag is tied so closely to the VPD policy itself, I decided to build this logic directly into my VPD policy PL/SQL package The BI_SELECT.CHANNEL_POLICY PL/SQL package
contains the logic to generate both the VPD predicate and the VPD tag The function called VPD_ WHERECLAUSE is used by the VPD policy to generate the predicate that will be appended to all queries against the SH.SALES_FACTS table The function called VPD_TAG generates the value
that should be used to tag cache entries
Testing the VPD Example Testing this feature is worthwhile, because it helps you understand
how it works The goal of this test is to show that the BI server uses the cache only when it will not violate the VPD policy This test requires three users: BICHANNEL1, BICHANNEL 2, and BICHANNEL 3 (see the appendix for more details on these users) If you take a quick look at the BI_SELECT.CHANNEL_MANAGERS table shown in Figure 14-14 and the SH.CHANNELS table, you will see that BICHANNEL1 manages the TeleSales channel, while BICHANNEL 2 and BICHANNEL 3 manage the Internet channel We will run an Oracle BI Answers request for each user This will be a very simple report that returns the sales for each channel Figure 14-16 shows the definition of this report in Oracle Answers
Figure 14-17 shows the results of this query when executed by BICHANNEL1
Figure 14-18 shows the results of this query when executed by BICHANNEL2 or
BICHANNEL3
FIGURE 14-16 The request that will be executed by all three users
Trang 4These results are the exact results that we would expect to see with the VPD policy The user BICHANNEL1 can see only the sales for the TeleSales division The users BICHANNEL2 and BICHANNEL3 can see only one the sales for the Internet division This tells us that the database
is appropriately applying the VPD policy It also tells us that BICHANNEL1 is not sharing a cache entry with BICHANNEL2 and BICHANNEL3 Had the BI server used the cache to satisfy the request, we would have seen the same results for all three users
The last thing we need to check is that BICHANNEL2 and BICHANNEL3 are able to share cache entries, because the VPD policy limits both users to the same set of data Here are the steps required to verify this:
1 Clear all cache entries.
2 Run the query as BICHANNEL1.
3 Check the logs and verify the BI server sends a query to the database (no cache entries
are available)
4 Run the query as BICHANNEL2.
FIGURE 14-17 The results when executed by BICHANNEL1
FIGURE 14-18 The results when executed by BICHANNEL2 or BICHANNEL3
Trang 55 Check the logs and verify the BI server sends a query to the database BICHANNEL2’s VPD_TAG session variable does not match the VPD_TAG attached to BICHANNEL1’s
cache entry
6 Run the query as BICHANNEL3.
7 Check the logs and verify that BICHANNEL3 was able to use the cache entry generated
by BICHANNEL2 BICHANNEL3’s VPD_TAG session variable matches the VPD_TAG
attached to BICHANNEL2’s cache entry
Now we’ll clear all cache entries using the Manage Cache utility in the Administrator tool Then, the log level needs to be raised for the three users we will use for our test: BICHANNEL1, BICHANNEL2, and BICHANNEL3 Log levels range from 0 to 7 Productions systems should run with a log level of 0 to avoid unnecessary overhead and should be raised for testing only for troubleshooting The log level needs to be set to a value of at least 2 to see the physical queries that are issued to the database If you are using the RPD with internal security, the log level for each user can be adjusted on the user property page in the RPD
If we use any of the RPDs with externalized security, we need to set a session variable called
LOGLEVEL equal to a value of 2 or higher for each user, to raise the log level for a user We can temporarily turn on logging for a user easily by issuing the command set variable LOGLEVEL=2;
in the Prefix box on the Advanced tab of an Answers request You can see this in Figure 14-19
To see the logs generated by each user, you will need to open a browser window and log
in as an administrator (BIADMIN in the example RPDs) This allows you to get to the Manage Sessions screen from the Administration window For each session, you can see the log files that are generated Here is a snippet of the log file that BICHANNEL1 generated:
+++bichannel1:720000:720003: 2008/10/10 16:15:09
- Sending query to database named orcl (id: <<268155>>): select T3192.CHANNEL_DESC as c1,
sum(T3276.AMOUNT_SOLD) as c2,
T3192.CHANNEL_ID as c3
from
SH.CHANNELS T3192,
SH.SALES T3276
where ( T3192.CHANNEL_ID = T3276.CHANNEL_ID )
group by T3192.CHANNEL_DESC, T3192.CHANNEL_ID
order by c1
FIGURE 14-19 Raise the user’s log level by setting the LOGLEVEL variable on the Advanced tab
in Answers.
Trang 6Next, here’s BICHANNEL2’s log file entry:
+++bichannel2:700000:700003: 2008/10/10 16:17:34
- Sending query to database named orcl (id: <<267859>>): select T3192.CHANNEL_DESC as c1,
sum(T3276.AMOUNT_SOLD) as c2,
T3192.CHANNEL_ID as c3
from
SH.CHANNELS T3192,
SH.SALES T3276
where ( T3192.CHANNEL_ID = T3276.CHANNEL_ID )
group by T3192.CHANNEL_DESC, T3192.CHANNEL_ID
order by c1
Finally, here’s the log file for BICHANNEL3:
+++bichannel3:710000:710005: 2008/10/10 16:19:57
- Cache Hit on query:
Matching Query: SET VARIABLE QUERY_SRC_CD='Report',LOGLEVEL=2; SELECT
Channels."Channel Desc" saw_0, "Sales Facts"."Amount Sold" saw_1 FROM SH ORDER
BY saw_0
Created by: bichannel2
To summarize, all three of these users ran the same report or logical query User BICHANNEL2 was not able to use the BI server cache entry created by BICHANNEL1, because the two users’ VPD tags do not match However, user BICHANNEL3 is able to use the cache generated by BICHANNEL2 because they have the same VPD tags
Deciding When to Use VPD or Oracle BI Row-level Security
At first glance, VPD and Oracle BI row-level security may seem a bit redundant However, you might want to use both of these types of data security for several reasons Following a basic good security practice, using both VPD and the BI filters, provides defense-in-depth for multiple layers
of protection, as shown next:
Trang 7Applying security at the database (VPD) puts the security as close to the data as possible This method’s biggest advantage is that security is enforced no matter how the database is accessed: Oracle BI, SQL*Plus, a web application, or any other access method
NOTE
VPD policies are applied to all applications that access the database
Oracle BI security filters are applied only to queries issued via
Oracle BI.
Applying security at the BI layer provides its own benefits as well For example, a business model filter might be applied to data that actually comes from multiple physical sources In this case, the filters need to be defined only once: at the business model layer of the BI metadata In addition, business model filters in Oracle BI allow VPD-like security to be added to any backend data source that Oracle BI supports (multidimensional data sources, relational database—both Oracle and non-Oracle, Access database, spreadsheets, and XML data files)
At this point, you may be wondering which of these two row-level security mechanisms you should implement As we implied, they are not mutually exclusive If, however, you find that one mechanism meets all your needs, it is unlikely that you would replicate the work in another layer
So which should you implement? Here are a number of things you might consider:
Will the data be accessed by something other than the BI server applications? It is
absolutely critical that the data is secure at all times by all access mechanisms Putting the security as close to the data as possible ensures that the security is not intentionally
or inadvertently bypassed
Will the backend database support row-level security? Oracle BI allows for a number of
backend databases Using Oracle BI, you can apply row-level security no matter what the backend data source is (XML, Excel, Access, and so on)
How much work will be required to implement these features? I’ve worked with some
clients that already have the VPD policies in place and just needed to make sure that Oracle BI could respect those policies Other clients are adding BI on top of existing systems where it would require a lot of work to add VPD They tend to find Oracle BI business model filters easier to implement
Who is responsible for the security? If the DBA is responsible for the security, VPD would
be the logical choice If the BI application administrator is responsible for the database, it might be easier to implement security as part of the BI deployment
What are the audit requirements? Applying the security policy in the database using
VPD allows all the security to be centralized This not only makes it easier for auditors
to inspect the security policies, but it also makes it easier to ensure that the policies are not bypassed or altered
Does the data need to be protected from the administrators? Oracle BI business
model filters do not apply to administrators If it is important to secure your data from administrators, database security options should be employed In fact, this is the perfect situation for integrating Oracle BI with Database Vault
■
■
■
■
■
■
Trang 8In addition to these considerations is one more implementation consideration Oracle BI business model filters and VPD polices are applied at different levels VPD policies are applied
at the object level Every query issued by every user will be affected by the policy If you want to exclude the policy from being applied to a user, that must be designed into the policy itself or you have to make use of the EXEMPT ACCESS POLICY privilege
An Oracle BI business model filter is applied to an object at the group level Business model filters will affect only members of the group where the filter is defined Users that are not members
of this group are completely unaffected by the business model filters attached to the group You can, of course, make this group as large or as small as you want You could design the group so that everyone is a member In summary, VPD policies affect every user by default, whereas Oracle
BI business model filters only affect the member of the group where the filter is defined
In conclusion, Oracle VPD and Oracle BI business model filters are mechanisms used to enforce row-level security Oracle BI is designed to work with VPD and even has a VPD-aware caching architecture Oracle BI business model filters provide a quick and easy way to add row-level security to your BI environment, but the are applied only to data accessed through Oracle
BI In addition, they can be used with any supported Oracle BI data source Oracle VPD has the distinct advantage of being closer to the data VPD policies will be applied no matter how the data is being accessed
NOTE
Oracle BI has been optimized to work with VPD.
Oracle BI and Database Vault
This section explains how the concepts introduced in Chapters 4 through 7 can be applied to the concepts discussed in this and the previous chapter Chapter 6 focused on creating a security policy around a Sales Management application This included transactional, batch, and reporting use cases In this section, we focus primarily on the reporting use case, as Oracle BI is a reporting tool However, as Oracle BI can be placed on top of transactional or warehouse data models, the other use cases in Chapter 6 can also be useful for someone attempting to integrate Oracle BI and Database Vault (DBV)
Factors and Oracle BI
Recall from Chapter 4 that factors are discrete security-related attributes that resolve to a specific value In Oracle BI, factors can be used in number of ways They might be used directly as part of the Oracle BI authentication and authorization process or to simplify the definition of Oracle BI session variables
In Chapter 13, we used initialization blocks to authenticate and authorize users Factor functions are ideal for initialization blocks Using factor functions greatly simplifies the
development of initialization blocks by allowing the Oracle BI administrator to reuse existing security code This also allows you to put your security policies in a central place (the DBV), making it easier for auditors to verify compliance with security requirements Finally, the
definition of the factor function is protected by DBV When the code used to retrieve security-related information is stored in an initialization block, any authorized BI server metadata
developer can modify that code Moving the code into a DBV-protected factor means that
only authorized realm users will be able to modify the factor definition
Trang 9When using factors to establish Oracle BI session variables, remember that Oracle BI uses shared connection pools to retrieve database information For example, if we wanted to use the factor User_Department_Name, as defined in Chapter 5, the initialization block query would
simply be select DVF.F$USER_DEPARTMENT_NAME FROM DUAL This factor function uses
the database session to return the value of the factor This will work only if we have properly conveyed the end user’s identity to the database
One way for Oracle BI to convey the end user’s identity would be to use the technique discussed earlier in this chapter to set a client identifier Another way to convey the end user’s identity would be to use the technique discussed in Chapter 5 to set the CLIENT_IDENTIFIER factor This technique discussed how to use the concepts of factor assignment and factor validation
to set the client identifier in a more trusted manner The example presented in Chapter 5
demonstrated how the factor could be assigned only from an application server that used a specific certificate as part of the database authentication process In this case, the application server would be the BI server
Before using the factor User_Department_Name with Oracle BI, we need to make one
modification The code that defined the factor called hr.employee_utility.get_user_department_ name without any parameters By default, this function uses SYS_CONTEXT('USERENV',
'SESSION_USER') ) as input But this will not work with the way Oracle BI uses connection pools,
so the factor should call the get_user_department_name function passing the client identifier as
input In this case the factor definition would look like this:
dbms_macadm.create_factor(
factor_name => 'User_Department_Name' ,
factor_type_name => 'User',
description =>
'The name of the department the current user works in.',
rule_set_name => NULL ,
get_expr =>
'hr.employee_utility.get_user_department_name(
sys_context(''USERENV'',''CLIENT_IDENTIFIER''))',
validate_expr => null,
identify_by => dbms_macutl.g_identify_by_method,
labeled_by => dbms_macutl.g_labeled_by_self,
eval_options => dbms_macutl.g_eval_on_access,
audit_options => dbms_macutl.g_audit_on_get_error,
fail_options => dbms_macutl.g_fail_with_message);
To set the DEPARTMENT_NAME session variable, we would use an initialization block to issue the query select DVF.F$USER_DEPARTMENT_NAME FROM DUAL via a connection pool This connection pool would have a logon script that calls dvsys.set_factor(‘Client_Identifier’, ‘:USER’) Actually, to use the procedure dvsys.set_factor as part of a logon script, it would need to be wrapped in a function just as we did with dbms_session.set_identifier earlier in the chapter
The logon script would ensure that the end user’s identity is properly conveyed to the database before attempting to retrieve the department name factor Once the Oracle BI session variable
DEPARTMENT_NAME is set, it could be used as a part of a business model filter to appropriately
limit the data the end user can see
Trang 10Realms and Oracle BI
In designing the examples included at www.OraclePressBooks.com, we took care to follow the principles discussed in Chapter 1 In particular, if you examine the setup scripts, you will find objects owner accounts and user access accounts
Let’s quickly review the database accounts used in the examples For the application data, the object owner accounts used are SH and BI_TABLES, while the user access account is BI_SELECT Earlier in the chapter we saw how every end user connected via a shared connection pool (BI_ SELECT) to retrieve information from the database We also examined how to convey the end user’s identity to the database for the purposes of identification and auditing A similar setup was used for the security-related information used in the examples The object owner accounts are BI_ SECURITY_TABLES and BI_USAGE_TRACKING and the user access account is BI_SECURITY_ SELECT
The next thing you will notice is that in just the first two setup scripts, it took 25 grant
commands to set up the user access accounts properly, even for such a simple example This is where the concept of DBV realms becomes very useful In the security setup for these examples,
we have effectively described two realms All the application-related objects, all objects owned
by SH and BI_TABLES, could be placed in one realm All security-related objects, all objects owned by BI_SECURITY_TABLES and BI_USAGE_TRACKING, could be placed in another realm The user access accounts would be added as realm participants Chapter 5 gives examples of how
to set up these realms and add objects and participants to the realm
Without DBV protections, it is actually quite easy to circumvent our previous BI security setup All it takes is a database user with the SELECT ANY privilege to bypass all the work we put into designing our architecture Putting these objects in a realm fixes this problem by immediately controlling access via ANY privileges In addition, the management of access to objects can be eased by granting the appropriate realm participant SELECT ANY TABLE without worrying about granting too many privileges to the participants Once DBV is installed and configured, accounts with system ANY privileges can no longer access or manipulate objects protected by the realm
TIP
The benefit of placing the objects in realms is that it immediately and
transparently protects all the BI data and security-related BI objects
from other privileged database users.
Recall that more than just tables and views can be added to the realm This is an important point Another object to add to the realm would be the VPD policy; this ensures that the security policy protecting the data is also secured The BI_ACCESS role used in the example could also
be added to the realm; this would ensure that this role could be granted only by the accounts or roles authorized as owners of the realm
Auditing
The caching capabilities of Oracle BI introduce some interesting security questions, and the same
is true with auditing It might seem like the hardest part of auditing when using Oracle BI would
be capturing the end user’s identity from within the database as the user has connected via a