Saturday, January 7, 2012

OIM10G: Administrative Queues


Hello,
My Name is Thiago L Guimaraes. I am a Security Consultant and I work with Marco. I will publish some articles to help developers with different OIM topics.
The objective of Administrative Queues is: Improve the manageability of requests using users that are part of group queues authorized to manage those requests.
The idea is very simple. You only need to assign a group of users to manage a provisioning request using an entity called a queue.
In this queue you can have one or more group definitions. So, here we will use Administrative queue form to create and manage administrative queues. You assign queues to requests from form the Queues tab on the Request form(Data Object Manager–Object Definition tab).
A request can specify some Admin privileges for each group in the queue. In this example I’ve assigned two different groups and each have different administrative privileges for the request. The ‘DeleteAccess’ group is able to delete a request. And ‘WriteAccess’ group is able to modify a request.
Steps:
1. Create and configure an admin queue.
2. Raise a new request in order to provision a test resource which is following an approval flow
3. The request is assigned to the manager of the requester – who is able to approve the request
4. The members of the group associated with the administrative queue are able to approve the request
First go to User Management à Administrative Queue, create your ‘Queue Name’ and assign your Group Members as showing below:
Go to Adapter Factory –> Create your Entity Adapter .
Don’t forget to upload your Java code (.jar file) to JavaTasks directory in OIM_HOME/xellerate.
The Java code for the entity adapter is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package adminqueuespjr;
/**
 *
 * @author Thiago Leoncio
 *  The wrapper class for Administrative Queue implementation on OIM 9.1.0.2 BP17
 *  Created On : 01/17/2012
 */
import Thor.API.Operations.tcQueueOperationsIntf;
import Thor.API.Operations.tcRequestOperationsIntf;
import Thor.API.tcResultSet;
import Thor.API.tcUtilityFactory;
import java.util.HashMap;
import org.apache.log4j.Logger;
public class AdministrativeQueueUtility {
    private static Logger logger = Logger.getLogger("ADMINQUEUE test");
    public static void assignRequestToQueue(long requestKey, String queueName) {
        try {
            tcUtilityFactory apiFactory = OIMUtil.getUtilityFactory();
            tcRequestOperationsIntf reqOpsIntf = null;
            long queueKey = 0;
            queueKey = getQueueKey(queueName);
            if (queueKey != 0) {
                reqOpsIntf = (tcRequestOperationsIntf) apiFactory
                        .getUtility("Thor.API.Operations.tcRequestOperationsIntf");
                reqOpsIntf.assignQueue(queueKey, requestKey);
                logger.info("Request " + requestKey + " assigned to "
                        + queueName);
            } else {
                logger.info("Request " + requestKey + " not assigned to "
                        + queueName + " as the queue does not exist.");
            }
        } catch (Exception e) {
            logger.error("Error assigning request " + requestKey + " to queue "
                    + queueName, e);
        }
    }
    public static long getQueueKey(String queueName) {
        tcQueueOperationsIntf queueOpsIntf = null;
        HashMap<String, String> queueFilter;
        tcResultSet queues = null;
        long queueKey = 0;
        try {
            tcUtilityFactory apiFactory = OIMUtil.getUtilityFactory();
            queueOpsIntf = (tcQueueOperationsIntf) apiFactory
                    .getUtility("Thor.API.Operations.tcQueueOperationsIntf");
            queueFilter = new HashMap<String, String>();
            queueFilter.put("Queues.Queue Name", queueName);
            queues = queueOpsIntf.findQueues(queueFilter);
            if ((queues != null) && (queues.getRowCount() == 1)) {
                queues.goToRow(0);
                queueKey = queues.getLongValue("Queues.Key");
            }
        } catch (Exception e) {
            logger.error(
                    "Error occurred in method AdministrativeQueueUtility.getQueueKey.",
                    e);
        }
        return queueKey;
    }
}
Mapping variables:
Data Object Manager –>Search for Request.
–UGP_KEY OF MY USER IS 42 WriteAccess group
Select * from UGP
Now when you raise a request that need approval from this type of groups, OIM behavior will be:
Logs:
DEBUG,07 Oct 2011 19:23:12,031,[XELLERATE.ACCOUNTMANAGEMENT],Class/Method: tcUtilityFactory/getRemoteUtility – Data: moUtil – Value: Thor.API.Operations.tcQueueOperationsClient
DEBUG,07 Oct 2011 19:23:12,032,[XELLERATE.APIS],Class/Method: tcQueueOperationsBean/findQueues entered.
DEBUG,07 Oct 2011 19:23:12,035,[XELLERATE.APIS],Class/Method: tcQueueOperationsBean/findQueues left.
DEBUG,07 Oct 2011 19:23:12,038,[XELLERATE.ACCOUNTMANAGEMENT],Class/Method: tcUtilityFactory/getRemoteUtility – Data: moUtil – Value: Thor.API.Operations.tcRequestOperationsClient
DEBUG,07 Oct 2011 19:23:12,058,[XELLERATE.ADAPTERS],Class/Method: tcAdpEvent/finalizeEntityAdapter entered.
DEBUG,07 Oct 2011 19:23:12,062,[XELLERATE.ADAPTERS],Class/Method: tcAdpEvent/finalizeEntityAdapter – Data: No Return Value mapping defined – Value:
DEBUG,07 Oct 2011 19:23:12,062,[XELLERATE.ADAPTERS],Class/Method: tcAdpEvent/finalizeEntityAdapter left.
 INFO,07 Oct 2011 19:23:12,062,[XELLERATE.ADAPTERS],Event: adpTHIAGOADMINQUEUE has completed.
DEBUG,07 Oct 2011 19:23:12,683,[XELLERATE.APIS],Class/Method: tcFormDefinitionOperationsBean/findForms entered.
DEBUG,07 Oct 2011 19:23:12,691,[XELLERATE.APIS],Class/Method: tcFormDefinitionOperationsBean/findForms left.
DEBUG,07 Oct 2011 19:23:12,715,[XELLERATE.APIS],Class/Method: tcFormDefinitionOperationsBean/getFormFieldsData entered.
 INFO,07 Oct 2011 19:23:12,722,[XELLERATE.APIS],Class/Method: tcFormDefinitionOperationsBean/getFormFieldsData: Form with key 4does not have any fields defined.
DEBUG,07 Oct 2011 19:23:13,604,[XELLERATE.ADAPTERS],Class/Method: tcRuleEvaluator/findApprovalProcessDeterminationRule entered.
1) –WITH QUM Administrative queue members
select * from qum
–WITH RQE table you can see request that were included into QUEUE TABLE
select * from rqe
Finally,
I hope this helps,
Thiago L Guimaraes

Tuesday, January 3, 2012

OIM10G: How to audit OIM tables from database perspective and OIM create user API curiosity


Hi, This is Thiago Leoncio again and I want to publish a curiosity of the OIM APIs discovered using a security tool from Oracle Database.
OIM Curiosity:
Do you know how many tables are involved during the process to create a user using OIM API in OIM 9.1.0.2 Schema?
================================================================================
SQLS AND STEPS to Enable Oracle Database Audit using OIM Schema (eg: oimuser)
================================================================================
1) Before start, just to make sure AUDIT is not set
show parameter audit_trail;
This need to show NONE or FALSE
2) Run this command to create sequences, triggers, procedures and functions for AUDIT purpose:
DATABASE_HOME/rdbms/admin/cataudit.sql
3) ALTER SYSTEM SET AUDIT_TRAIL=TRUE SCOPE=SPFILE;
4) Shutdown database and startup:
5) Connect into database again , usign SYSADM user and type: show parameter audit_trail;
this need to show TRUE
6) Requering to AUDIT process starts to collect something, by your desire:
audit all by OIMUSER by access;
or
AUDIT SELECT TABLE, UPDATE TABLE, INSERT TABLE, DELETE TABLE BY OIMUSER BY ACCESS;
or
audit delete,insert,update on sys.aud$ by access;
7) Statements that you can find more details about the Auditory:
7.1) select * from SYS.AUD$
7.2) select * from DBA_AUDIT_TRAIL
7.3) select * from DBA_AUDIT_EXISTS
7.4) select * from DBA_AUDIT_OBJECT
7.5) select * from DBA_AUDIT_SESSION (show OS Process Number)
Helpful SQLS using DBA_AUDIT_SESSION:
7.5.1) SQL to get OIM SCHEMA Connections Made Out Of Working Hours -
SELECT checkOIM.username,
TO_CHAR(checkOIM.timestamp,’DD Mon YYYY HH24:MI:SS’)   logontime,
TO_CHAR(checkOIM.logoff_time,’DD Mon YYYY HH24:MI:SS’) logofftime
FROM sys.dba_audit_session checkOIM
WHERE checkOIM.timeStamp > SYSDATE-7
AND checkOIM.returnCode = 0
AND NOT (    TO_NUMBER(TO_CHAR(checkOIM.timestamp,’D’)) < 6
AND TO_NUMBER(TO_CHAR(checkOIM.timestamp,’HH24MI’)) BETWEEN  800 AND 1800 )
ORDER BY checkOIM.username;
7.5.2) Unsuccessful Logon Attempts in the Last Month
SELECT checkOIM.username,
checkOIM.os_username,
checkOIM.terminal,
TO_CHAR(checkOIM.timeStamp,’DD Mon YYYY HH24:MI’) timestamp,
checkOIM.returnCode
FROM sys.dba_audit_session checkOIM
WHERE checkOIM.timeStamp > SYSDATE-30
AND checkOIM.returnCode != 0;
7.6) select * from DBA_AUDIT_STATEMENT
7.7) select * from DBA_AUDIT_TRAIL
–WHAT OPTIONS I AM AUDITING
7.8) select * from DBA_OBJ_AUDIT_OPTS
–TIP Merge this views below
7.9) select * from DBA_PRIV_AUDIT_OPTS
7.10) select * from DBA_STMT_AUDIT_OPTS
like this:
select user_name, audit_option, success, failure  from dba_stmt_audit_opts
union
select  user_name, privilege, success, failure from  dba_priv_audit_opts;
Results:
Answer|||Example:
So, according to AUDIT_TRAIL, when I click on button, just to create a simple user, OIM generates ‘INSERT’ Statements with 11 different tables, as you can see into results of the SQL below:
SQL to Check just INSERT statement:
++++++++++++
select   to_char(timestamp,’DD/MM/YYYY HH24:MI:SS’) STARTTIME,obj_name,DBA_AUDIT_TRAIL.* from DBA_AUDIT_TRAIL where obj_name is not null and ACTION_NAME =‘INSERT’
++++++++++++
As you can see (picture above) some of these more than one per table.
OIM table names:
USG | OTI | OSI | OSH | SCH | ORC | USR | OBI | OIO | ADMINSERVER_WLSTORE | AUD_JMS
by the way,
STEPS TO CLEAN AUDIT TABLE:
DELETE FROM SYS.AUD$;
commit;
Bye, I hope this helps,
Thiago L Guimaraes