OBIEE 11G Row Level Security
OBIEE 11G Row Level Security
OBIEE 11G Row Level Security
In the two analysis screenshots below, for example, one user sees one set of stores when they view a particular
report, whereas another user viewing the same report gets to see a completely different set of stores, but no filters
have been explicitly added to the analysis instead, some other process is applying row-level security to the
analysis data in the background, automatically.
The advantage of row-level security, particularly if its applied automatically by the BI Server in the background, is that
you can roll-out generic reports across all of your users, but each one will provide a customised view showing just the
data, or rows, that apply to that user, even if the report designer forgets to add filters to the analysis themselves to
restrict users views of data to the correct region, in this case.
So where can you set up row-level security in OBIEE, so that this background row-level filtering takes place? In
general, you would set up row-level filtering like this using two repository features, together:
First, you would define whats called a session variable to hold the region name that the user is allow to see,
and then
2. You would define a filter, using the Identity Manager dialog, to filter rows against this region setting.
You can also apply row-level filtering at the database level, by using whats called Virtual Private Databases, and
1.
then enabling this in the physical database settings, but thats a topic for another day. In addition, of course the
developers of individual analyses and reports can add filters to the report definition, which again can make reference
to session or other variables. But for now, lets look at the most common way to set up background row-level filtering
and security.
Assuming that weve got two tables stored in a database somewhere, that list out users and the region they are
assigned to, like this:
The steps to set up security to restrict users to a single regions worth of data would look like this:
1.
Before we do anything, well need to create a new, dedicated connection pool definition within the physical
database settings that connects us to the database schema that holds these tables. This is because, as from
2.
3.
4.
5.
6.
OBIEE 11g, by default connection pools that are used for general database queries cant be used for
initialisation blocks, and youll get a validation warning if you try and do this. Instead, using the Oracle BI
Administrator tool and with the repository open online, create a new connection pool within the database that
holds these tables, enter the connection details, and give it a name such as init_blocks_cp.
Now, well start by defining the session variable that will hold the region name that the user is allowed to see.
Still using the Oracle BI Administrator tool and with the repository open online, select Manage > Variables to
open the Variable Manager dialog.
Within the navigation tree on the left-hand side of the Variable Manager dialog, click on the Session > Variables
node, then right-click in the area on the right and select New Session Variable
With the Session Variable dialog open, type in REGION as the Name, and then press the New button next
to theInitialization Block: area, which currently has not assigned as its setting.
The Session Variable Initialization Block dialog will then be displayed. Enter GET_REGION_SESS_VAR as the
name, and then press the Edit Data Source button to bring up the Session Variable Initialization Block Data
Source dialog.
Using this dialog, select Database as the Data Source Type, select the connection pool that you defined
earlier, and then select the Default initialisation string radio button. Then, type in the SQL that returns the
region for a given user, using the :USER substitution variable, like this:
select r.region from gcbc_hr.staff_logins l, gcbc_hr.staff_regions rwhere l.login_name = r.login_nameand
l.login_name = :USER
Press OK to close the dialog, and the Session Variable Initialization Block dialog should look as in the
screenshot below:
Using the Oracle BI Administrator tool and with the repository open online, select Manage > Identity from the
application menu.
8. The Identity Manager dialog will then be displayed. Click on the Application Roles tab on the right-hand side,
and then then double-click on the role you wish to assign the row-level security settings to; in this
case, BIConsumer, to apply the rule to all users of the system.
9. The Application Role dialog will then display. Press the Permissions button to open the User/Application
Role Permissions dialog.
10. With the User/Application Role Permissions dialog open, press the Add button to bring up
the Browse dialog. Using the Browse dialog, select the table you wish to apply the filter to.
In this instance, there are two ways we can set up the filter. The Region column that corresponds to the filter is
found in the Dim Stores table, which means that if we want to apply the filter when any column from this table
7.
is included in an analysis, wed double-click on this particular table to select it for the filter condition. If, however,
we wanted the filter to be applied even if no column from the Dim Stores table was selected, wed double-click
on the associated fact table Fact Sales instead, which would apply the filter regardless of what attribute
columns were selected for the analysis criteria.
Note also that you can place the filter on either a presentation table, or a business model table. If you choose
the former, and youve got several subject areas based off of the same business model, only the table from that
particular presentation layer subject area will be subject to the filter. If, however, you click on the Business
Model tab instead and then select a business model table, every subject area that contains presentation tables
derived from that business model table will have the filter applied.
11. After double-clicking on a table, youre returned back to the User/Application Role Permissions dialog, to
define the actual filter expression.
Click in the Data Filter area and then press the Edit Expression button to bring up the Expression Builder
Data Filterdialog.
12. Using this dialog, set the following filter, which references the session variable you defined earlier using the
VALUEOF(NQ_SESSION.variablename) syntax:
Sales.Dim Stores.Region Name = VALUEOF(NQ_SESSION.REGION)
Press OK to close the dialog, then keep pressing OK with the other dialogs to eventually return back to
the Identity Manager dialog. To close that final dialog, select Action > Close.
Now, when users log in that have entries in this table, you should see that queries that reference either the Dim
Stores table (in this case), or if youve set it up like this, any query against the fact table, will have the required
restriction applied to the rows of data returned. If you dont see this restriction happening, check the nqserver.log file
for an error message like:
But the SQL in the variable definition that we defined earlier is expecting a single value, not a set of values. The way
that you in fact deal with this is to create whats called a row-wise initialization variable that can contain multiple
values internally, it still holds a single value, but this consists of all the values you load in, separated by semicolons.
To define a row-wize initialised variable, follow these steps:
1.
2.
Using the Oracle BI Administration tool and the repository online, select Manage > Variables as before. This
time though, do not create the variable first; instead, click on the Session > Initialization Blocks entry in
the Variable Manager navigation tree, then right-cick on the right-hand panel and select New Initialization
Block
With row-wise variables, you define the SQL query, and the variable, at the same time. Using the Session
Variable Initialization Block dialog, type in a name for the initialisation block, for example
GET_REGIONS_ROWWISE_SESS_VAR, and then press the Edit Data Source button to bring up
the Session Variable Initialization Block Data Source dialog.
As before, select Database as the Data Source Type, select the Default initialization string radio button and
select the connection pool as before, but then when you come to type in the SQL you define the variable at the
same time, like this:
select REGIONS, r.region
from gcbc_hr.staff_logins l, gcbc_hr.staff_regions r
where l.login_name = r.login_name
and l.login_name = :USER
with the literal values REGIONS, in this case, defining the row-wise variables as part of the initialisation block
definition.
3.
Press OK to close this dialog and return to the Session Variable Initialization Block dialog.
In the previous example, youd see the variable name listed in the Variable Target area. To assign this
initialisation block to the row-wise variable weve just defined in the SQL statement, press the Edit Data
Target button, and then when the Session Variable Initialization Block Variable Target dialog is shown,
check the Row-wise initialisationcheckbox. Your final Session Variable Initialization Block dialog should
now look like this:
4.
Now, to reference the row-wise session variable in a filter, for example in the mandatory filter we applied to
theBIConsumer role, youd reference it in the same way as with a regular variable:
Sales.Dim Stores.Region Name = VALUEOF(NQ_SESSION.REGIONS)
Then, you should see any users that have more than one region assigned, getting the correct values in their
analyses:
So thats the basics of how row-level security works in OBIEE you define a session variable using an initialisation
block, which then gets used to create a data filter behind the scenes using the Identity Manager. Theres a few
variants around this you might use Virtual Private Database, for example, to enforce the row-level security at the
database level but this is the most common approach.
One other row-level filtering approach that you might sometimes come across though is where the filter is applied at
the logical table source level. If you open up the repository and double-click on a logical table source within the
Business Model and Mapping layer, then click on the Content tab, youll that one of the sections lets you type in an
SQL WHERE clause to limit the rows returned, like this:
By default, and in most cases, this section is usually empty for most logical table sources, but you could use it to
enforce row-level security for all users, without reference to a particular user or role, like this:
I personally dont tend to use this type of approach to row-level security, as its applied across all users regardless of
roles etc, and also its not so obvious to find, hidden away in a logical table source definition. But you ought to be
aware of how its done, as its used extensively, for example, by Oracle with the BI Applications repository model.
So thats an overview of row-level security. Tomorrow, well look at subject area (and table and column-level)
security, and also how we restrict users to only be allowed to use certain front-end functions, so that for example they
can view dashboards, but not use the analysis, scorecard or alerts editors.