Friday, February 28, 2014

Delete UDFs using OIM API

Version: Oracle Identity Manager 11g
Description: Oracle Identity Manager has an API service, namely ConfigManager, that allows developers to perform various operations on User Defined Field (UDF).

** WARNING USE AT YOUR OWN RISK **
This post will show you how to use ConfigManager API service to delete a UDF. The "deleteAttribute" method only deletes the attribute in the backend (USR, SDC, MV_USER_COLS, and User.xml metadata) and all the UI customizations are untouched. Once in a while the "deleteAttribute" method does not remove the backend data fully, and hence you would have to manually clear the data.

package oracleidentitymanagerclient;

import java.util.Hashtable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.security.auth.login.LoginException;
import oracle.iam.configservice.api.ConfigManager;
import oracle.iam.configservice.api.Constants;
import oracle.iam.configservice.exception.*;
import oracle.iam.platform.OIMClient;

/*
 * Uses the OIMClient to access the ConfigManager services.
 * This class shows how to delete a User Defined Field in the backend.
 * The attribute is removed from SDC and USR. 
 * Also it is removed from MDS, to be specific "/file/User.xml".
 * Restart the oim server or purge the cache after executing code. 
 *
 * WARNING: USE AT YOUR OWN RISK. MAKE SURE NOTHING ELSE IS RUNNING IN OIM.
 * The method call to delete an attribute may fail to remove from the USR, SDC, or User.xml.
 */
public class OracleIdentityManagerClient 
{
    public static final String OIM_HOSTNAME = "localhost";
    public static final String OIM_PORT = "14000";
    public static final String OIM_PROVIDER_URL = "t3://"+ OIM_HOSTNAME + ":" + OIM_PORT;
    public static final String OIM_USERNAME = "xelsysadm";
    public static final String OIM_PASSWORD = "Password1";
    public static final String OIM_CLIENT_HOME = "/home/oracle/Desktop/oimclient";
    public static final String AUTHWL_PATH = OIM_CLIENT_HOME + "/conf/authwl.conf";

    public static void main(String[] args) 
    {
        OIMClient oimClient = null;
      
        try
        {
            //Set system properties required for OIMClient
            System.setProperty("java.security.auth.login.config", AUTHWL_PATH);
            System.setProperty("APPSERVER_TYPE", "wls"); 
           
            // Create an instance of OIMClient with OIM environment information 
            Hashtable<String,String> env = new Hashtable<String,String>();
            env.put(OIMClient.JAVA_NAMING_FACTORY_INITIAL, "weblogic.jndi.WLInitialContextFactory");
            env.put(OIMClient.JAVA_NAMING_PROVIDER_URL, OIM_PROVIDER_URL);
            oimClient = new OIMClient(env);

            // Login to OIM with the approriate credentials
            oimClient.login(OIM_USERNAME, OIM_PASSWORD.toCharArray());
            
            // Access ConfigManager services
            ConfigManager configMgrOps = oimClient.getService(ConfigManager.class);
            
            // Change this value to the attribute you want to delete
            String attributeName = "CustomAttribute"; //Use attribute unique name
            
            // Deletes the SDC and USR attribute records. Removes attribute from User.xml
            configMgrOps.deleteAttribute(Constants.Entity.USER, attributeName);
        }
        
        catch (LoginException ex) {
            Logger.getLogger(OracleIdentityManagerClient.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoSuchEntityException ex) {
            Logger.getLogger(OracleIdentityManagerClient.class.getName()).log(Level.SEVERE, null, ex);
        } catch (AccessDeniedException ex) {
            Logger.getLogger(OracleIdentityManagerClient.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoSuchAttributeException ex) {
            Logger.getLogger(OracleIdentityManagerClient.class.getName()).log(Level.SEVERE, null, ex);
        } catch (DeleteSystemAttributeException ex) {
            Logger.getLogger(OracleIdentityManagerClient.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ConfigManagerException ex) {
            Logger.getLogger(OracleIdentityManagerClient.class.getName()).log(Level.SEVERE, null, ex);
        }

        finally
        {
            // Logout user from OIMClient
            if(oimClient != null)
                oimClient.logout();
        }
    }
}

Troubleshooting
If the attribute is not properly cleared in the backend, the UI consoles will not render properly. Look at the logs to see what is causing the problem.

<Error> <oracle.iam.oimdataproviders.impl> <BEA-000000> <ORA-00904: "USR"."USR_UDF_TEST": invalid identifier
java.sql.SQLSyntaxErrorException: ORA-00904: "USR"."USR_UDF_TEST": invalid identifier

        at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:462)
        at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:405)
        at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:931)
        at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:481)
        at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:205)
        at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:548)
Issue:   There are references for the UDF in MDS. The sysadmin console will display a blank page after logging in. Also when you try to view user details through the console or APIs you will get errors.

Fix:
1. Export the User.xml file and remove the attribute. Given below is an example of four sections to remove with the attribute named "test".

<attribute name="test">
<type>string</type>
<required>false</required>
<searchable>true</searchable>
<multi-valued>false</multi-valued>
<MLS>false</MLS>
<multi-represented>false</multi-represented>
<attribute-group>Extended</attribute-group>
<description/>
<metadata-attachment>
<metadata>
<name>certifiable</name>
<value>false</value>
<category>properties</category>
</metadata>
<metadata>
<name>user-searchable</name>
<value>false</value>
<category>properties</category>
</metadata>
<metadata>
<name>read-only</name>
<value>false</value>
<category>properties</category>
</metadata>
<metadata>
<name>visible</name>
<value>true</value>
<category>properties</category>
</metadata>
<metadata>
<name>display-type</name>
<value>TEXT</value>
<category>properties</category>
</metadata>
<metadata>
<name>entity-type</name>
<value/>
<category>properties</category>
</metadata>
<metadata>
<name>bulk-updatable</name>
<value>false</value>
<category>properties</category>
</metadata>
<metadata>
<name>category</name>
<value>Basic User Information</value>
<category>properties</category>
</metadata>
<metadata>
<name>entity-type-attributes</name>
<value/>
<category>properties</category>
</metadata>
<metadata>
<name>encryption</name>
<value>CLEAR</value>
<category>properties</category>
</metadata>
<metadata>
<name>possible-values-code</name>
<value>null</value>
<category>properties</category>
</metadata>
<metadata>
<name>max-size</name>
<value>64</value>
<category>properties</category>
</metadata>
<metadata>
<name>system-controlled</name>
<value>false</value>
<category>properties</category>
</metadata>
<metadata>
<name>custom</name>
<value>true</value>
<category>properties</category>
</metadata>
</metadata-attachment>
</attribute>

<field name="usr_udf_test">
<type>string</type>
<required>false</required>
</field>

<attribute-map>
<entity-attribute>test</entity-attribute>
<target-field>usr_udf_test</target-field>
</attribute-map>
<attribute-map>

<metadata>
<name>12</name>
<value>test</value>
<category>categories.Basic User Information</category>
</metadata>

2. Import the metadata back into MDS.
3. Run PurgeCache utility or restart the servers.

1 comment:

  1. Hello,

    Is the UDF column deleted even when there is data in it. Do we need to perform some pre-requisites for cleaning the column and then invoking the ConfigService API?

    ReplyDelete