3 Using the ArisID API

The ArisID API provides enterprise developers and system architects a library for building identity-enabled applications using multiple identity protocols. The ArisID API enables developers to specify requirements for identity attributes, roles, and search filters by using Client Attribute Requirements Markup Language (CARML).

Note:

This chapter and all its subsections have been deprecated in 12c (12.2.1.3.0) release. By deprecate, we mean that the feature is no longer being enhanced but is still supported for the full life of the 12c (12.2.1.3.0) release. Where indicated, a deprecated feature may be desupported in a future major release.

The following topics describe the architecture and key functionality of the Identity Governance Framework ArisID API:

3.1 About the ArisID API

The Identity Governance Framework ArisID API represents a common core service through which all identity information exchanged should be passed. While not an official name, the ArisID API is often referred to as Identity Beans by developers.

If you have installed Oracle WebLogic Server and Oracle Identity Management, all the necessary jar files for developing applications with this API are already installed on your computer.

The Identity Governance Framework open source API jar files are as follows:

The ArisID API jar files are as follows:

  • idxuserrole.jar — Provides the Standard User and Role identity read-only operations. This jar is generated from the standard idxuserrole.xml CARML file. See Java API Reference for Identity Governance Framework IDXUserRole.

  • userrole.jar — Provides the User and Role identity read/write operations for updating identity information. See Java API Reference for Identity Governance Framework UserRole.

  • arisId-stack-ovd.jar — This jar file is an implementation of the IAttrSvcStack interface with the Oracle Virtualization library to connect to different backends and provide an abstract view of the identity store entities.

The ArisID beans provide the Java APIs required for initialization and accessing CARML interactions. The bean generator generates a set of java files for each entity in the CARML file using Apache Velociy. The CARML file is a declarative document that describes the attribute usage requirements of your application. The ArisID beans are in the jar files idxuserrole.jar and userrole.jar.

The following figure provides a high-level view of the ArisID API architecture.

Figure 3-1 IGF ArisID API Architecture

Description of Figure 3-1 follows
Description of "Figure 3-1 IGF ArisID API Architecture"

3.2 Configuring the ArisID API

ArisID API supports several configuration options which allow for easier and flexible deployment in Web Server environments.

The Identity Governance Framework ArisID supports the basic development process, which is Create > Modify > Test > Deploy. Creation requires CARML XML files and modifying them to suit your environment. Testing the application can be done in Oracle WebLogic Server embedded LDAP directory server.

This section contains the following topics:

3.2.1 Examining CARML Files

CARML is an XML-based declarative format to define the attribute usage requirements of an application. Administrators examine the CARML file to connect to the appropriate back-end resources.

To determine whether the existing ArisID beans meet your application's needs, you need to examine idxuserrole.xml (read-only operations) and userrole.xml (read-only and read/write operations) CARML files. These CARML files are located in DOMAIN_HOME/config/fmwconfig/carml.

3.2.2 Configuring the Identity Repository

An identity repository is a data store where information about users and groups in a company is stored. You can configure the identity repository to be used by the ArisID beans.

The identity repository to be used by the ArisID beans must be available. You can use the Oracle WebLogic Server embedded LDAP-based directory server or any LDAP directory supported by 11g Oracle Virtual Directory. The ArisID API is integrated with Oracle Platform Security Services. It automatically connects to the LDAP-based identity store configured in Oracle Platform Security Services. For more information about the identity stores supported by Oracle Platform Security Services, see System Requirements and Certification for Identity Governance Framework.

If you must use a different identity store from the Oracle Platform Security Services identity store, then set the following system property:

igf.ovd.config.dir=DOMAIN_HOME/config/fmwconfig/arisidprovider/conf 

Next, edit the adapters.os_xml file to include the host, port and credentials of the directory to be connected to. The igf.ovd.config.dir property can be set to any other directory containing adapaters.os_xml and other configuration files with the right settings.

Directory Limitations

The following LDAP directory limitations apply:

  • When using OpenLDAP 2.2 or Novell eDirectory, there is no paging support. Paging APIs, for example, searchUsersbyPage(), searchRolesbyPage(), etc., do not work. There is no Multiple Language Support (MLS).

  • When using Oracle WebLogic Server embedded LDAP-based directory server, there is no Multiple Language Support (MLS).

3.2.3 Configuring the Mapping File

The mapping file allows you to map CARML attributes to LDAP attributes, objectclasses, and search parameters. You can customize your mapping file for the LDAP-based directory server at your site.

When a CARML file is created a corresponding mapping file is created in the same location. The default mapping file has attribute details specific to Oracle WebLogic Server embedded directory server, which is the Oracle Platform Security Services default identity store. If you are using a default CARML file and the Oracle Platform Security Services identity store, you do not need to configure mapping. The configuration parameters in Oracle Platform Security Services override the parameters in the mapping file.

3.3 Design Recommendations for the ArisID API

The default CARML and mapping files make certain assumptions about the deployment scenario. You may need to modify these details depending on your deployment requirements.

The following topics describe the configuration parameters that can be modified:

3.3.1 About Unique Identifier Configuration

It is imperative to ensure that all users are uniquely identifiable. The default configuration, email, is used as a unique identifier for identifying user entries.

When you are searching for a user, the default attribute expected for search is email. For example:

SearchUser( String uniqueid,  Map<String, Object>)

For performance reasons, the attribute used as a unique identifier must be a searchable attribute in the backend. The mapping between the application's choice of uniquekey and the backend attribute is handled at configuration time. This is a configuration in Oracle Virtual Directory mapping. The HashMap is used to provide the optional context information to be used while performing the operation. In the current release it supports the following options:

  • The Principal user that performs the search - (ArisIdConstants.APP_CTX_AUTHUSER, (Principal)user)

  • The language constraint if any - (ArisIdConstants.APP_CTX_LOCALE, "fr")

  • Pagination support if any - (ArisIdConstants.APP_CTX_PAGESIZE, 10)

3.3.2 About Unique Key Attribute Specification

Attribute uniqueness is enforced by defining constraints on attributes.

An application occasionally stores the entries accessed from the identity repository's backend in their own application-specific repository. In such cases, you must carefully consider which attribute should be persisted. For instance, if the backend is an LDAP-based repository, you should use the GUID attribute as the persisting attribute because this is the only unique key on the LDAP-based backend. All other LDAP attributes are modifiable.

If the backend is a relational database, choose an attribute on which uniqueness constraint is enforced as the unique key. You can specify this in the ArisID mapping property file. The method to search for a user based on the unique key is:

searchUserOnUniqueKey(String UniqueKey, Map<String,Object>)

The HashMap is used to provide the optional context information to be used while performing the operation. In the current release it supports the following options:

  • The Principal user that performs the search - (ArisIdConstants.APP_CTX_AUTHUSER, (Principal)user)

  • The language constraint if any - (ArisIdConstants.APP_CTX_LOCALE, "fr")

  • Pagination support if any - (ArisIdConstants.APP_CTX_PAGESIZE, "10")

3.3.3 About Multiple Language Support

Multiple Language Support (MLS) is provided for applications that need locale-specific results.

The attributes and the appropriate MLS code are stored in the ArisID properties file in the multiLanguageAttributes element.

<multiLanguageAttributes>…</multiLanguageAttribute>

The displayname is the most commonly used multiple language attribute, therefore it is configured by default as a multi-language attribute. Other attributes can be added as needed in the ArisID mapping file.

Restrictions

Any API to which locale is specified as an argument will return the locale-specific values for all the attributes listed in the ArisID properties file as <multiLanguageAttributes> that have locale-specific values. For all other attributes it returns the default values stored.

In the backend system, the data is returned in a form conforming to ISO-3166. For example, if there is a French locale (in addition to English), it is stored as cn,:fr for the cn attribute. The locale for the client applications should be specified in the properties HashMap as ArisIdConstants.APP_CTX_LOCALE, "fr" and the ArisID properties file should contain cn as multiLanguageAttribute and map this attribute.

3.3.4 Handling Large Results

There are situations when you retrieve large result sets. This could cause a performance and resource problem. Use the sample code to manage large result sets.

When applications access identity data, the result set for a search is frequently too large to be handled by the application. In such cases you have the option of dividing the result into manageable sized pages. You do this by defining the number of objects to be returned in the page.

The following example shows a typical usage pattern:

RoleManager rm = new RoleManager(env); 
  List<PropertyFilterValue> attrFilters = new  ArrayList<PropertyFilterValue>(); 
  attrFilters.add(new PropertyFilterValue(Role.NAME, "admin", AttributeFilter.OP_CONTAINS)); 

  HashMap<String,Object> map = new HashMap<String,Object>(); 
  map.put("ArisIdConstants.APP_CTX_PAGESIZE","2"); 
  SearchResults<Role> sr = rm.searchRolesbyPage(attrFilters, map); 

  while(sr.hasMore()) 
  { 
     List<Role> roles = sr.getNextSet(); 

     for (int i=0; i<roles.size(); i++) 
       //do the operations with roles.get(i)
}

3.3.5 Securing the Application

There are two common security scenarios for executing create, read, update, and delete (CRUD) operations on the target system. You must review these scenarios for a better understanding.

They are as follows:

Proxy authentication is not supported in this release.

3.3.5.1 Applying Domain Level Credentials

In this scenario, all applications in a domain use common credentials to connect to the target system and perform operations with those credentials. The application does not maintain a footprint in the target system.

The LDAP Adapter's configuration file, adapters.os_xml, contains credentials to connect to the backend directory, along with the host and port details. If you do not provide any other credentials during initialization, the application connects to the target system using the credentials in the LDAP Adapter's configuration file.

If proxy user (logged in user id) is not specified in the API's application context, ArisID operation will be executed with the credentials that are in LDAP Adapter's configuration file.

If your application connects using common credentials, you must build security into the application itself so that it displays or modifies data only for an authorized user.

Consider the following example where the LDAP adapter's configuration file adapters.os_xml is configured with domain level userid and encrypted password to connect to backend directory. The following is a snippet of adapters.os_xml.

    <binddn>cn=admin</binddn>
    <bindpass>{OMASK}C2QXW1Nmf+s=</bindpass>

While initializing the ArisID API do not provide any credentials.

Map env = new HashMap();
// Do not set UserManager.SECURITY_PRINCIPAL & SECURITY_CREDENTIALS
UserManager uMgr  = new UserManager(env);
…
…
// Search Operation (with no proxy user in app context)
List<PropertyFilterValue> attrFilters = new ArrayList<PropertyFilterValue>();
attrFilters.add(new PropertyFilterValue("User.FIRSTNAME", "app1", AttributeFilter.OP_CONTAINS));
attrFilters.add(new PropertyFilterValue("User.LASTNAME", "user1", AttributeFilter.OP_BGNSWITH));
Map<String, Object> appCtx = null;
users = um.searchUsers(attrFilters, appCtx);
3.3.5.2 Applying Application Level Credentials

In this scenario, each application uses application level credentials to connect to the target system and performs CRUD operations with those credentials.

In this case you provide the application's user id and password while initializing the ArisID API. When you do that, the application connects to the target system using those credentials.

If no proxy user is specified in the API's application context then ArisID operation will be executed with the application's credentials.

This scenario has the following features:

  • Each application has different privileges to view and update the data in the target system

  • You can audit the modifications performed by each application in the target system

Consider the scenario where the LDAP adapter's configuration file adapters.os_xml is configured with domain level userid and encrypted password to connect to backend directory. The following is a snippet of adapters.os_xml.

<binddn>cn=admin</binddn>
    <bindpass>{OMASK}C2QXW1Nmf+s=</bindpass>

While initializing the ArisID API, provide the application user credentials.

Map env = new HashMap();
env.put(UserManager.SECURITY_PRINCIPAL, "cn=app1_user,cn=users,dc=example,dc=com");
env.put(UserManager.SECURITY_CREDENTIALS, "mypassword");
UserManager uMgr  = new UserManager(env);
…
// Search Operation (with no proxy user in app context)
List<PropertyFilterValue> attrFilters = new ArrayList<PropertyFilterValue>();
attrFilters.add(new PropertyFilterValue("User.FIRSTNAME", "app1", AttributeFilter.OP_CONTAINS));
attrFilters.add(new PropertyFilterValue("User.LASTNAME", "user1", AttributeFilter.OP_BGNSWITH));Map<String, Object> appCtx = null;
users = um.searchUsers(attrFilters, appCtx);

3.3.6 Configuring the Timeout Interval

You can configure the timeout intervals for LDAP operations. These intervals specify the amount of time after which the LDAP operation times out.

The default connect/read timout is configured to be 15 seconds. For example, if the LDAP operation on IdentityStore is taking more than 15 seconds, the operation will timeout and throw the following IGF exception:

org.openliberty.arisid.stack.ConnectionException

If the IdentityStore has a many entries and the applications are using filters with "contains" and search with paging/sorting, those queries may timeout.

The recommendation is to set the timeout value to 0 (no timeout) and increase the pool size to 20. If the application has a timeout interval, set the value to greater than 0.

To configure the timeout interval:

  1. Run the following WLST command to list all adapters.

    listAdapters() 
    
  2. Run the following command for each adapter to set timeout and maxpoolsize.

    1. modifyLDAPAdapter('<ADAPTER NAME>', 'OperationTimeout', 0)

    2. modifyLDAPAdapter('<ADAPTER NAME>', 'MaxPoolSize', 20)

  3. Restart WebLogic Server.

3.3.7 Specifying Wildcard Characters in Search Filters

Oracle Internet Directory supports wildcard search for DN attributes.

Directories other than Oracle directories might not support wildcard search. Therefore, if you perform a seachUsers operation through Identity Governance Framework API with say Microsoft Active Directory as the backend and using a DN in a search filter, then you must provide the AttributeFilter.OP_EQUALS operator to successfully execute the operation.

3.4 Generating ArisID Beans

When you have finished editing your CARML file, you can generate the ArisID Beans to use in your application. The ArisID Beans provide Java APIs as a layer on top of the ArisID API that have various action methods associated with them.

To generate the ArisID Beans run the following command:

java BeanGenerator [-genmap] <package name> <output dir> [<relationship file>] <carml file>

where:

  • -genmap: Generates the CARML-ArisIDStack map file in the same location where the CARML file is.

  • package name: Is the package name for the generated bean classes.

  • output dir: Location to write the generated bean classes.

  • relationship file: File containing the relationship definitions between entities.

  • carml file: The CARML declaration file.

To build ORG beans from a CARML file:

  1. Create a CARML file name org.xml with the appropriate attributes/interactions for ORG entity.

  2. Generate org beans (OrgManager.java and Org.java) using the Bean Generator. The build.xml file should resemble the following sample:

    <path id="ArisIDBeans.classpath">
                <pathelement location="MW_HOME/oracle_common/modules/velocity-dep-1.4.jar" />
                <pathelement location="MW_HOME/oracle_common/modules/oracle.jrf_11.1.1/jrf.jar" />
        </path>
        <property name="BeanGeneratorClassPath" refid="ArisIDBeans.classpath"/>
        <target name="generatebeans" description="generate arisid beans">
            <java classname="org.openliberty.arisidbeans.BeanGenerator" dir="${generatedsource.dir}" fork="true">
                <arg value="${generatedbean.userrole.packagename}"/>
                <arg value="."/>
                <arg value="${carml.dir}/org.xml"/>
                <classpath>
                    <pathelement path="${BeanGeneratorClassPath}"/>
                </classpath>
                <sysproperty key="org.openliberty.arisid.policy.wspolicy.class"
                             value="org.openliberty.arisid.policy.neethi.PolicyImpl" />
            </java>
        </target>
    
  3. Compile the generated java files Org.java and OrgManager.java.

  4. Edit the generated mapping file (igf-map-config-.xml) to update basesearch, objectclass, OVD attribute names with their values.

  5. An application can use the generated ORG APIs for the interactions defined in the CARML file (org.xml). After the application is deployed in application server:

    1. Copy the mapping file under DOMAIN_HOME/config/fmwconfig/arisidprovider/conf, and

    2. Copy the CARML file under DOMAIN_HOME/config/fmwconfig/carml

3.5 Examples of Using IDX User and Role Beans

It is imperative to understanding the use of IDX User and Role Beans. Use the sample applications to understand how to integrate IDX User/Role Beans into your application.

The following topics describe the use of IDX User/Role Beans:

3.5.1 Searching Users Using IDX User and Role Beans: SearchUsers.jsp

Use IDX User/Role Beans Java version to search users.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@page import="org.openliberty.arisid.*"%>
<%@page import="org.openliberty.arisidbeans.*"%>
<%@page import="oracle.igf.userrole.*"%>
<%@page import="java.util.*"%>
<%@page import="java.net.URI"%>
<%!public static UserManager uMgr = null;
{
        try {
                uMgr = new UserManager(null);
        } catch (Exception e) {
                e.printStackTrace();
        }
 
}
%>
<html>
<head>
<title>Search Users</title>
<%
 
 
String firstname = request.getParameter("firstname");
String lastname = request.getParameter("lastname");
String telephone = request.getParameter("telephone");
 
 
List<PropertyFilterValue> attrFilters = new ArrayList<PropertyFilterValue>();
attrFilters.add(new PropertyFilterValue("firstname", firstname, AttributeFilter.OP_BGNSWITH));
attrFilters.add(new PropertyFilterValue("lastname", lastname, AttributeFilter.OP_BGNSWITH));
attrFilters.add(new PropertyFilterValue("telephone", telephone, AttributeFilter.OP_CONTAINS));
 
List<User> subjs = uMgr.searchUsers(attrFilters);
 
%>
</head>
<body>
 
<a href="SearchUsers.html">Home</a>
<center>List of Users with FirstName starting with "<%=firstname%>", LastName
starting with "<%=lastname%>" and TelephoneNumber containing
"<%=telephone%>"</center>
 
<%
Iterator<User> sIter = subjs.iterator();
while (sIter.hasNext()) {
        User subj = sIter.next();
 
        Map<String, IAttributeValue> vals = subj.getAllAttributes();
        Iterator<IAttributeValue> iter = vals.values().iterator();
%>
<table border="0">
        <tr>
                <th>Item</th>
                <th>Value</th>
        </tr>
        <%
                while (iter.hasNext()) {
                        IAttributeValue val = iter.next();
                        String name = val.getNameIdRef();
                        String value = null;
                        if (val.size() > 0)
                                value = val.get(0);
if (value != null)
{
        %>
        <tr>
                <td><%=name%></td>
                <td><%=value%></td>
        </tr>
        <%
}
                }
        %>
</table>
<%
        }
%>
<br>
<br>
<br>
<a href="SearchUsers.html">Home</a>
</body>
</html>

3.5.2 Searching Users Using IDX User and Role Beans: SearchUsers.html

Use the IDX User/Role Beans code to search users.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD><TITLE>Search Users</TITLE></HEAD>
<BODY>
<FORM METHOD=POST ACTION="SearchUsers.jsp">
 
First Name Starting with <INPUT TYPE=TEXT NAME=firstname SIZE=30><BR><BR>
Last Name Starting with <INPUT TYPE=TEXT NAME=lastname SIZE=30><BR><BR>
Telephone Number containing <INPUT TYPE=TEXT NAME=telephone SIZE=15><BR><BR>
<P><INPUT TYPE=SUBMIT>
</FORM>
</BODY>
</HTML>

3.6 Understanding OpenLDAP Considerations

OpenLDAP specifies some mandatory attributes for implementing the APIs. You must keep in mind these attributes while implementing your applications.

For OpenLDAP, Role.MEMBER is a mandatory attribute for the following APIs:

  • createRole(List<PropertyValue> attrVals, Map<String,Object> appCtxMap)

  • createRole(List<PropertyValue> attrVals)

If the Role.MEMBER is not included in the input attrVals list, role creation will fail.