Monday, 7 March 2016

Migrating application roles in OBIEE 11g

My last article talked about a maintenance and hassle free mechanism to implement security. The article moved the security architecture to roles created in EM. The next logical step is to move the roles from one environment to another because lets face it, manually creating roles is a lot of effort.

Oracle has a process to migrate the policy store from one environment to another and is described @

This process migrates all of the roles. I wanted to just migrate the roles that I created for data security so that I don't disturb anything that is working.

I wrote the following python script to make it happen.

The concept:

The heart of this code is WLST functions such as listAppRolesdeleteAppRole and createAppRole. If we were to use just these functions without any checks then the execution of a deleteAppRole on a role that does not exist would cause the script to error out and the statements after such a deleteAppRole will not execute. I wanted my script to be smart enough to be able to deal with this situation so I did the following.

I used listAppRoles WLST function to list all the existing roles. I then used this output to find out whether a role exists in the system or not. If it does not exist, then I don't fire a deleteAppRole on such a role. The problem is that the output of listAppRoles is sent to the monitor. For this output to be usable, we have to store it in a string variable. We will soon see the process of doing this.

The script shared below works as follows.
I delete all the data security roles using the script. I then recreate each of them with the updated members. If a role does not have an update, it is still deleted and recreated.

Now, we can make this script better by using listAppRoleMembers. This script finds out the members of a certain role. So instead of deleting and recreating all the application roles, we can use the output of listAppRoleMembers to find whether the roles needs an update or not. If it does not need an update then we leave it alone, if it needs an update we do the needful. So this takes away the need to delete and recreate the roles. Using listAppRoleMembers would have meant a few more case statements and a little more work so I am skipping all of that for the purpose of this discussion.

The syntax is listAppRoleMembers("obi","OBIEE_AMERICAS_ROLE")
Here, obi is the application stripe. You can see this application stripe when you login to EM.

Alright lets see the code. Note that indentation is very important in Python. Hence, I have put a comment after each line of code about its indentation.

import sys #indentation no space
#indentation no space
global mystr #indentation no space
myStr = "" #indentation no space
#indentation no space
#This is a class that redirects the standard output to its local variable.
class stringPrint: #indentation no space
 def __init__(self): #indentation one space
  self.old_stdout=sys.stdout #indentation two space
#indentation no space
 def write(self, text): #indentation one space
  global myStr #indentation two space
  myStr = myStr + text #indentation two space
#indentation no space
#Class definition ends above. myPrint (defined below) is an object of this class.
myPrint = stringPrint() #indentation no space
#We redirect standard output to myPrint
sys.stdout = myPrint #indentation no space
#indentation no space
#the connect command connects to weblogic in the online mode. It prompts for weblogic user id, its password and t3://<hostname>:<admin_server_port>
connect() #indentation no space
listAppRoles("obi") #indentation no space
# Because of the redirection of the standard output to myPrint object, the output of the above listAppRoles is stored into myStr global string variable. Since our job is done so we redirect the output to standard output device below.
sys.stdout = myPrint.old_stdout #indentation no space
#indentation no space
# We find if OBIEE_AMERICAS_ROLE exists in myStr or not.
if myStr.find("OBIEE_AMERICAS_ROLE") > -1: #indentation no space
# If it does, we delete it 
 deleteAppRole("obi","OBIEE_AMERICAS_ROLE") #indentation one space
 print ("Deleting OBIEE_AMERICAS_ROLE") #indentation one space
else: #indentation no space
# If it doesnot, we do nothing 
 print ("OBIEE_AMERICAS_ROLE does not exist") #indentation one space
#indentation no space
if myStr.find("OBIEE_APAC_ROLE") > -1: #indentation no space
 deleteAppRole("obi","OBIEE_APAC_ROLE") #indentation one space
 print ("Deleting OBIEE_APAC_ROLE") #indentation one space
else: #indentation no space
 print ("OBIEE_APAC_ROLE does not exist") #indentation one space
#indentation no space
if myStr.find("OBIEE_EMEA_ROLE") > -1: #indentation no space
 deleteAppRole("obi","OBIEE_EMEA_ROLE") #indentation one space
 print ("Deleting OBIEE_EMEA_ROLE") #indentation one space
else: #indentation no space
 print ("OBIEE_EMEA_ROLE does not exist") #indentation one space
#indentation no space
if myStr.find("OBIEE_DATA_SECURITY") > -1: #indentation no space
 deleteAppRole("obi","OBIEE_DATA_SECURITY") #indentation one space
 print ("Deleting OBIEE_DATA_SECURITY") #indentation one space
else: #indentation no space
 print ("OBIEE_DATA_SECURITY does not exist") #indentation one space
#indentation no space
# Now we start with creating the roles and assigning members to them.
createAppRole("obi","OBIEE_AMERICAS_ROLE") #indentation no space
grantAppRole("obi","OBIEE_AMERICAS_ROLE","","OBIEE_AMERICAS_GROUP") #indentation no space
print ("OBIEE_AMERICAS_ROLE has been created and roles/groups/users have been assigned") #indentation no space
#indentation no space
createAppRole("obi","OBIEE_APAC_ROLE") #indentation no space
grantAppRole("obi","OBIEE_APAC_ROLE","","OBIEE_APAC_GROUP") #indentation no space
print ("OBIEE_APAC_ROLE has been created and roles/groups/users have been assigned") #indentation no space
#indentation no space
createAppRole("obi","OBIEE_EMEA_ROLE") #indentation no space
grantAppRole("obi","OBIEE_EMEA_ROLE","","OBIEE_EMEA_GROUP") #indentation no space
print ("OBIEE_EMEA_ROLE has been created and roles/groups/users have been assigned") #indentation no space
#indentation no space
createAppRole("obi","OBIEE_DATA_SECURITY") #indentation no space
grantAppRole("obi","OBIEE_DATA_SECURITY","","OBIEE_AMERICAS_ROLE") #indentation no space
grantAppRole("obi","OBIEE_DATA_SECURITY","","OBIEE_APAC_ROLE") #indentation no space
grantAppRole("obi","OBIEE_DATA_SECURITY","","OBIEE_EMEA_ROLE") #indentation no space
print ("OBIEE_DATA_SECURITY has been created and roles/groups/users have been assigned") #indentation no space
#indentation no space
disconnect() #indentation no space
exit() #indentation no space

This script can be executed using the following command.

sh <BI_Home>/oracle_common/common/bin/ <full file path of the py file that has the above code.>

For example:
sh /app/oracle/biee/oracle_common/common/bin/ /app/oracle/

Make sure that you have execute permission on the py file.

Till next time ..


Thu Hoang said...

i like your post, I try to do something, copy your code to file
and then execute py file by java command following.
my code:
WLSTInterpreter interpreter = WLST.getWLSTInterpreter();

but i have a error:

Exception_111:Traceback (innermost last):
File "/app/bi/JavaTestWLST/", line 35, in ?
NameError: listAppRoles

please help me.


Thu Hoang said...

How are you,
please tell me the way check user belong to application role after i run a grantAppRole command for 2 times.


Vishal Pathak said...

listAppRoleMembers can be used for this purpose.