Tuesday, August 6, 2013

[OBIEE 11g] Automatic Repository Deployment And Promotion Process






Automatic Repository Deployment and Promotion Process




A typical deployment process an OBIEE 11g repository will follow in most production environments resembles the following :





The development zone represents a series of developer machines modifying a repository either by:

  • Multi User Directory Environment Configuration (MUDE)
  • Local development machines where each developer migrates their changes to a centralized OBIEE 11g dev/unit test box via a patch-merge process


We're going to focus on the 'Production Deployment Path' that takes the repository from the Dev/Unit test machine and migrates it through the deployment path from Assembly Test through Production.

This production path is critical because it's at this point where the repository leaves the 'safe haven' of the developer environment and goes through various stages of testing, usually performed by another team. Each testing team will have their own BI Server and database that the repository must connect to for testing.

Usually, the repository remains the same through all environments except for:

  • Connection Pools
  • Environment specific server variables


 
We're going to perform the assembly test to production deployment process in a completely automated fashion by:


  • Generating an XUDML file that connections connection pool information
  • Generating a new system test repository by applying the System test XUDML to the assembly test repository
  • Using WLST to upload the RPD to the specif iced environment





 Step 1: Generate the XUDML file for the assembly, system, staging and production environments


We're going to create an eXtensible Universal Database Markup Language (XUDML for short) that contains connection pools specific for each environment. This file is generated by biserverxmlgen and is basically the repository exported to XML. The way to accomplish this in OBIEE 10g was using UDML which has seen been deprecated and is not supported by Oracle - see Oracle Note 1068266.1.



Step 1.1 - Set Variables via bi-init.sh


.
/export/obiee/11g/instances/instance1/bifoundation/OracleBIApplication/coreapplication/setup/bi-init.sh

Note the space between the '.' and the '/' . This is required for the i-init.sh script to propagate through all folders 

Step 1.2 - Generate XUDML file


Navigate to export/obiee/11g/Oracle_BI1/bifoundation/server/bin/ and run:

biserverxmlgen -R C:\testconnpool\base.rpd -P Admin123 -O c:\testconnpool\test.xml -8



  • Replace base.rpd with your source RPD - i.e. if you want to generate connection pool information for assembly test, base.rpd should represent your assembly test repository.
  • -O generates the output XML file
  • -8 represents the UTF-8 formatting for the XML file
  • -P represents the password of the base repository


If fail to set your session variables will you encounter the following error:

 "libnqsclusterapi64.so: open failed: No Such file or directory"


If you are successful, your output should be as follows:





Step 1.3 Remove inapplicable entries



For connection pool migrations, your script should only include:



<?xml version="1.0" encoding="UTF-8" ?>

<Repository xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<DECLARE>
<Connection Pool ......>
</ConnectionPool>
</DECLARE>
</Repository>



You will only need to re-generate this file if you change your connection pool information. This XUDML file will be used to update connection pools of your target environment.



Step 2: Apply XUDML file to base repository 



Let's say you have an assembly test repository and a system test XUDML file. The biserverxmlexec.sh script will take your assembly test repository, system test XUDML file and generate a 'system test repository' using the following command located in export/obiee/11g/Oracle_BI1/bifoundation/server/bin/



biserverxmlexec -I input_file_pathname [-B base_repository_pathname] [-P password] -O output_repository_pathname



Where:

  • input_file_pathname is the name and location of the XML input file you want to execute base_repository_pathname is the existing repository file you want to modify using the XML input file (optional). Do not specify this argument if you want to generate a new repository file from the XML input file.password is the repository password. 
  • If you specified a base repository, enter the repository password for the base repository. If you did not specify a base repository, enter the password you want to use for the new repository.
  • The password argument is optional. If you do not provide a password argument, you are prompted to enter a password when you run the command. To minimize the risk of security breaches, Oracle recommends that you do not provide a password argument either on the command line or in scripts. Note that the password argument is supported for backward compatibility only, and will be removed in a future release.
  • output_repository_pathname is the name and location of the RPD output file you want to generate


Example:

biserverxmlexec -I testxudml.txt -B rp1.rpd -O rp2.rpd
Give Password: my_rpd_password
 
You now have a system test repository that you can upload to your applicable environment.


Step 3: Upload Repository to BI Server via WLST


Many web sites show how to upload the repository via the FMW Enterprise Manager, but that is generally alot slower and not as efficient as scripting it.

The uploadRPD.py script below performs five tasks:

  • Connects to WLST
  • Locks the System
  • Uploads the RPD
  • Commits Changes
  • Restarts BI Services


Copy the code below and save it as a python script (.py)


connect('user','pass','server')
user = ''
password = ''
host = ''
port = ''
rpdpath = '/path/path2/repository.rpd'
rpdPassword = ''

# Be sure we are in the root
cd("..\..")

print(host + ": Connecting to Domain ...")
try:
domainCustom()
except:
print(host + ": Already in domainCustom")

print(host + ": Go to biee admin domain")
cd("oracle.biee.admin")



# go to the server configuration
print(host + ": Go to BIDomain.BIInstance.ServerConfiguration MBean")

cd ('oracle.biee.admin:type=BIDomain,group=Service')
biinstances = get('BIInstances')
biinstance = biinstances[0]


# Lock the System
print(host + ": Calling lock ...")
cd("..")
cd("oracle.biee.admin:type=BIDomain,group=Service")
objs = jarray.array([], java.lang.Object)
strs = jarray.array([], java.lang.String)
try:
invoke("lock", objs, strs)
except:
print(host + ": System already locked")

cd("..")

# Upload the RPD
cd (biinstance.toString())
print(host + ": Uploading RPD")
biserver = get('ServerConfiguration')
cd('..')
cd(biserver.toString())
ls()
argtypes = jarray.array(['java.lang.String','java.lang.String'],java.lang.String)
argvalues = jarray.array([rpdpath,rpdPassword],java.lang.Object)

invoke('uploadRepository',argvalues,argtypes)

# Commit the system
print(host + ": Commiting Changes")


cd('..')
cd('oracle.biee.admin:type=BIDomain,group=Service')
objs = jarray.array([],java.lang.Object)
strs = jarray.array([],java.lang.String)
invoke('commit',objs,strs)

# Restart the system
print(host + ": Restarting OBIEE processes")

cd("..\..")
cd("oracle.biee.admin")
cd("oracle.biee.admin:type=BIDomain.BIInstance,biInstance=coreapplication,group=Service")

print(host + ": Stopping the BI instance")
params = jarray.array([], java.lang.Object)
signs = jarray.array([], java.lang.String)
invoke("stop", params, signs)

BIServiceStatus = get("ServiceStatus")
print(host + ": BI ServiceStatus " + BIServiceStatus)

print(host + ": Starting the BI instance")
params = jarray.array([], java.lang.Object)
signs = jarray.array([], java.lang.String)
invoke("start", params, signs)

BIServerStatus = get("ServiceStatus")
print(host + ": BI ServerStatus " + BIServerStatus)


 
The aforementioned code works on scaled out (clustered) environments since there is only one active admin server. The code will connect to the active admin server located in your first node, and WLST will propagate changes to each node. You can validate this by navigating to the local repository folder of each node.

 
To run the script, load wlst located at :

/export/obiee/11g/oracle_common/common/bin/wlst.sh


and perform the execfile command as follows:


execfile
(‘/path/path1/path2/uploadRPD.py’)


In conclusion, the entire repository deployment process can be executed by the following two scripts:

biserverxmlexec (provided by Oracle)

uploadRpd.py






[OBIEE 11g] Enable Case Insensitive User Name Log-In With OBIEE 11g






Enable Case Insensitive User Name Log-in with OBIEE 11g

 

OBIEE 11g authenticates using an OID authenticator via OPSS (Oracle Platform Security Services), followed by a BISQLGroupAuthenticator - both configured in Weblogic Admin Console:





After configuring these authenticators (outlined here and here), you run a test by logging in a user who exists in your LDAP authenticator :
 

Example 1
:- Logging in with a valid username, valid password and correct username case sensitivity
  • username: cookjr (username is stored as 'cookjr' in external database table)
  • member of the following application roles: Authenticated User, BIConsumer, BIAuthor, BIAdministrator

 

From the above result, you can see the user cookjr has logged in and their application roles are correctly assigned.



Example 2 :- Logging in with a valid username, valid password and incorrect username case sensitivity

  • username: cOoKjR (username is stored as 'cookjr' in external database table)
  • member of the following application roles: Authenticated User, BIConsumer, BIAuthor, BIAdministrator 





 Application roles after login attempt:





Note how none of the custom application roles were applied to this login attempt even though it's the same user logging in.

 
WHY?

It is important to remember that the BISQLGroupAuthenticator used for group authentication is a driver that is used to generate Oracle SQL statements that you configure when setting up the authenticator in Weblogic Admin Console:




Keeping this in mind, also remember that Oracle SQL is case sensitive, meaning that:

Select * from table where name = 'john' does not equal select * from table where name = 'jOhn'.


To configure the BISQLGroupAuthenticator to be case insensitive for username logins, you'll need to modify your SQL statements in the BISQLGroupAuthenticator 'Provider Specific' tab to use the 'UPPER' function, which takes the username passed in from the Answers login screen, converts it to all caps, and compares it against the UPPER(G_MEMBER) field.


Example :-

  • SQL List Groups: SELECT G_NAME FROM GROUPS WHERE UPPER(G_NAME) LIKE UPPER(?)
  • SQL List Groups: SELECT G_NAME FROM GROUPS WHERE UPPER(G_NAME) LIKE UPPER(?)
  • SQL Is Member: SELECT G_MEMBER FROM GROUPMEMBERS WHERE UPPER(G_NAME) = UPPER(?) AND UPPER(G_MEMBER) = UPPER(?)
  • SQL List Member Groups SELECT G_NAME FROM GROUPMEMBERS WHERE UPPER(G_MEMBER) = UPPER(?)
  • SQL Get Group Description (if description supported enabled) SELECT G_DESCRIPTION FROM GROUPS WHERE UPPER(G_NAME) = UPPER(?)


Using this logic, the user will now be able to log in using any username case sensitivity. Note that you may still have an issue where the user is able to login with an invalid (or no) password.



This is most likely due to a legacy LDAP authenticator in your repository. 






Monday, August 5, 2013

[OBIEE 11g] User Able To Log-In Even With Invalid (Or No) Password In OBIEE 11g





User able to log-in even with Invalid (or no) password in OBIEE 11g




With the release of Oracle Business Intelligence (OBIEE) 11g, the 'old' (read: OBIEE 10g) way of authenticating users has been deprecated, mainly - authenticating a user's credentials via the repository which i've outlined in this post . At its core, 10g authentication was accomplished using init blocks that populated the :USERS and :GROUPS session variables in the repository.

OBIEE 11g, on the other hand, authenticates via authenticators in weblogic such as Oracle Internet Directory.


The OBIEE 10g method for authentication still exists in 11g, and unfortunately it is still possible to configure 11g init blocks so that the query does not check the password of the user.
For example:


SELECT USER_ID FROM USERS WHERE USER_ID = ':USER'


would just check the user id and not the password was correct but not check the password. In a scenario where such an INIT block exists and is set to act as an authentication block, this can lead to users being able to log in with any (or no) password. It can also lead to some apparently odd/inconsistent behavior. Consider the scenario where Users A and B both exist in OID which is set as the primary identity store. But User B also exists in a database which is referenced by an INIT block as described above. Both try to login using the wrong password. 


User A will simply fail. However, while User B will fail Authentication against OID, because the BI Server knows there is an Authentication INIT block set, it will then attempt to run that for each of them and in the case of User B, because their username is in the USER_ID column of the USERS table, they will be allowed in as the INIT block query apparently succeeds, even though it does not in fact correctly check the user’s password.

There is no 'fix' for this other than to force username validation for init blocks that use the :USER block or completely avoid using the :USER session variable.