Identity API
The Identity API is used by Web Center to access the service layer implementing the DirX Identity business logic and to access the LDAP layer for searching and modifying the objects in the data store.
The Identity API hides the details of the service layer implementation. It references the business objects by identifiers (being usually the object’s distinguished name) and uses standard data types whenever this is possible.
The API methods are available in the JSPs to implement own or modify existing actions in Web Center. Furthermore, the API may be used in a standalone Java application for DirX Identity.
The API methods are grouped into several interfaces. All interfaces and their implementation are available from the jar files that come with the Web Center installation.
Interface Summary
The Identity API offers the following interfaces:
| Name | Description |
|---|---|
Approval |
Defines methods providing DirX Identity approval functionality. |
Assignment |
Defines methods providing DirX Identity privilege assignment functionality. |
AuthenticatedUser |
Defines the methods that have to be implemented by external authentication mechanisms. |
Certification |
Provides access to certification campaigns. |
Delegation |
Defines methods providing the old DirX Identity delegation functionality. |
Delegations |
Defines methods providing the new DirX Identity delegation functionality. |
Objects |
Defines general object management methods. |
RequestWorkflow |
Defines request workflow management and access methods. |
Session |
Defines methods providing session-related functionality. |
Users |
Extends the Objects interface and defines special user management methods. |
For details, refer to the javadoc provided with Web Center in the docs-api folder.
The use of the interfaces Session, Assignment, Objects and Users is demonstrated in a sample program.See the section “Sample application UserSample.java” in this chapter.
Basic Concepts
This section provides information about basic concepts.
Technical Users and Effective Users
The API distinguishes between a technical and an effective user.The technical user provides the LDAP bind to the directory (should be the DomainAdmin of the particular domain).The effective user must exist in the directory, too.In the Web Center login process, the effective user’s credentials are verified, and the user object is loaded from the directory.The technical user, however, always owns the bind to the directory.
Access Control
The access rights are controlled by DirX Identity Access Policies that are checked in the service layer which is part of the Identity API.These access policies are evaluated with respect to the logged-in (effective) user.Since each user accesses the directory with the technical bind, the DirX Identity algorithms are not affected by the LDAP ACLs of the effective user.
Session Handling
Each user working with the API must be provided with his own API session. In Web Center, a new session is created each time a new user logs in. The API session object is held as an attribute of the HTTP-session, thus each HTTP session has its own unique API session. The session manages the LDAP connection, access control, and access to the business logic. It is implicitly contained in the implementation of each interface.
Business Logic
Since Web Center uses the DirX Identity API to access the Data Store, all aspects of DirX Identity Business Logic available in Web Center are covered by the use of the API, too. Note, that among others, the following features are available via the API:
| Feature | Interface.method |
|---|---|
Triggering an offline role resolution |
Objects.saveObject |
Check for SoD violation |
Objects.saveObject |
Start approval workflows in case a new privilege is assigned that must be approved |
Objects.saveObject |
Evaluate Object Description during modification of a property |
Objects.setObjectProperty |
Evaluate Object Description during save of the object. |
Objects.saveObject |
Create default property values by evaluating the object descriptions when a new object is created. |
Objects.createObject |
Evaluation of ObjectDescriptions is performed with full functionality as in WebCenter/Identity Manager, since the same algorithms of the underlying layers are used.This includes the evaluation of naming rules and JavaScripts.
Special Aspects
Some special aspects of the API methods are discussed here in more detail.
Data Conversion
The Objects interface offers the methods getObjectProperty and setObjectProperty to read and modify an object’s data.
Both methods load the object from the data store to the storage layer cache, in case the object is not already cached.Note that the data type returned by getObjectProperty and accepted by setObjectProperty is related to the object description assigned to the considered object.Some types defined in the object descriptions are converted to more general, simpler types, when getObjectProperty is called.The following table shows the mapping of object description types to simple types:
| Simple type | Object description type |
|---|---|
java.util.Date |
siemens.dxm.util.GeneralizedTime |
java.util.String |
com.siemens.idm.server.config. nodes.IDMTimeintervalImpl |
java.util.String |
siemens.dxm.storage.StorageObject |
java.util.String[] |
siemens.dxm.storage.StorageObject[] |
java.util.String |
siemens.dxr.service.nodes.SvcNode |
com.siemens.webMgr. identityAPI.Parameter |
siemens.dxr.service.types. AssignmentRPValue[] |
java.util.String[] |
siemens.dxr.service.types.RoleMatchRule[] |
java.util.String[] |
siemens.dxr.service.nodes.SvcRoleParam[] |
Examples:
The date attributes dxrStartDate, dxrEndDate are defined as GeneralizedTime in the user’s object description User.xml. A call to Objects.getObjectProperty(dn, “dxrStartDate”) returns a Java Date object. Note that in the forms-config.xml file, the type java.util.Date must be used for such date attributes. If a date must be provided in Objects.setObjectProperty, a Java Date object must be be passed as value.
A user’s manager is defined as StorageObject in the User.xml object description. A call to Objects.getObjectProperty(dn, “manager”) returns a String containing the manager’s dn rather than a StorageObject.
Vice versa, Objects.setObjectProperty expects a String containing the manager’s dn as value.
Filtering Assigned Privileges
The identity API contains the method listObjects in the Objects interface.
If assigned objects are requested (assignedRoles, assignedPermissions, assignedGroups, or assignedAccounts) the filter and base parameters are evaluated.This is intended to speed up displaying assignments to selected privileges in situations where users possess many privileges.
The following hints have to be considered:
-
Set filter = null or base = null to get all assigned privileges.
-
If you want to read a certain assigned privilege, use filter=”(objectClass=*)” and the privilege’s DN as base.The filter “(objectClass=*)” is evaluated with best performance (always match).It is preferable over “(objectClass=dxrRole)” etc.
-
Be aware that the assignments returned by the search may be only used for read/display.If you want to select an assignment and to update it later, you have to search the assignments for the given type using filter = null or base = null and identify the assignments to be modified on this basis.The reason is, that during save all new assignments are compared to all old assignments.Assignments being read by a filter are ignored for update.
-
If you have already developed some code with Identity API, check the listObjects calls for assigned privileges.Set filter = null and base = null if you do not intend filtering here or if you want to update the assignments afterwards.
How Web Center Uses the API
This section describes how Web Center uses the API.
How the API is Used in Initialization
After Tomcat starts, the first login request to Web Center triggers the following actions:
-
Create a new API session
-
Bind to the directory as technical user
-
Load the object descriptions
-
Authenticate the effective user
-
Pass the object descriptions to the API session.
After successful login, the Web Center support object is initialized and is ready for use.
How the API is Used in JSPs
The API is called from the JSPs implementing the actions. Using the Web Center taglibs rather than directly programming on the API accesses the standard Web Center functionality. The taglibs are implemented on top of the API. In special cases, the API is accessed directly by inserting Java code into the JSP.
The following steps are needed to use the API in a Web Center JSP:
-
Import the DataUtils class and the appropriate interfaces to the JSP. See section “DataUtils.java” in chapter “Utility Classes” for details on the DataUtils class.
-
Get an instance of the required interface by calling the appropriate getter for the support object from the DataUtils.
-
Call the API methods.
As a sample, look at the JSP WEB-INF/jsp/controller/tasks/setGroupForward.jsp. Here are some excerpts of that JSP. Note, that session is a predefined variable in a JSP holding the HTTP session.
...
1) <%@ page import="com.siemens.webMgr.identityAPI.Objects,
com.siemens.webMgr.model.DataUtils,
...
2) <% Objects objects = DataUtils.getObjectSupport(session);
3) forward = (String)objects.getObjectProperty(groupDN,
"targetsystem.dxrOptions(dialog)");
... %>
Using the API in a Standalone Application
This section describes how a standalone application uses the API.
Using the API in Initialization
If a standalone application uses the API, the initialization steps described in section “How the Web Center Uses the API” must be coded explicitly.
The following sequence of API calls is used:
| ServiceSupport.init | Initializes the API. It expects data for the system bind (technicalUser and technicalPassword) as well as a property mapper. The mapped item is expected to be an array of two strings containing the mapped type and the relation. This method must be be called only once in the application. It does not trigger any bind / connection but just stores the data in static variables for later use in startSession. |
|---|---|
Session.startSession |
Creates a new directory session. This action must be performed for each new user logging in to the application. The configuration will be loaded only once, thus the second and all subsequent calls are much faster than the first call. |
The interface of the ServiceSupport.init method is described here in more detail:
void init (java.util.Map[] objectConfigs, java.util.Map[] relationConfigs, java.util.Map rendererMapping, java.lang.String technicalUser, java.lang.String technicalPassword, java.lang.String passwordMode);
The first argument objectConfigs expects a Map array that contains the information of Web Center’s objects-config.xml file. Note that each Map in the array contains the information of one <object> element in the configuration file. The attribute names are mapped to the key, the values are stored as data of the Map.
The following table shows the mapping from the Map keys to the objects-config.xml attribute names:
| Key | Mapping |
|---|---|
name |
Value of id attribute |
setName |
Value of set attribute. If this does not exist, value of id attribute + “s” |
classInDatabase |
Value of dirClass attribute |
masterClass |
Value of masterClass attribute |
objectClass |
Value of nodeClass attribute |
Here is a programming sample for the “user” entry in the objects-config.xml:
User entry in objects-config.xml:
<object id="user" dirClass="dxrUser" nodeClass="siemens.dxr.service.nodes.SvcUser"/>
Code for populating the corresponding Map:
Map[] maps = new Map[23];
maps[0] = new Hashtable();
maps[0].put("name", "user"); // from id attribute
maps[0].put("setName", "users"); // the id attribute + "s"
maps[0].put("classInDatabase", "dxrUser"); // from dirClass
maps[0].put("objectClass", "siemens.dxr.service.nodes.SvcUser"); // from nodeClass
maps[1] = new Hashtable();
...
The second argument relationConfigs expects a Map array that contains the information of Web Center’s objects-config.xml file. Note that each Map in the array contains the information of one <relation> element in the file.
For each relation element, one Map is added to the array with two entries. The entry with key “name” contains the value of the name attribute, the entry with key “mappedTo” contains the value of the “value” attribute:
Entry in objects-config.xml:
<relation name="all" value=".all"/>
Code for population the corresponding Map:
Map[] relations = new Map[8];
Hashtable relation = new Hashtable();
relations[0] = relation;
relation.put("name", "all");
relation.put("mappedTo", ".all");
relation = new Hashtable();
relations[1] = relation;
...
As an easy alternative, you may let the utilitity class samples.util.ObjectsConfig generate the two Map arrays from an objects-config.xml file. This way, you don’t have to hardcode the maps into your program, but can simply use the objects-config.xml file delivered with Web Center. Just create an ObjectsConfig object, passing the path name of the objects-config.xml file as a parameter. Then call getObjectsConfig on the new object:
Map[][] objectsAndRelations = oc.getObjectsConfig();
if (objectsAndRelations != null) {
Map[] objectsMapArray = objectsAndRelations[0];
Map[] relationsMapArray = objectsAndRelations[1];
...
}
The third argument rendererMapping expects a Map containing the default renderer configuration. In a standalone application that does not use the Web Center rendering algorithms, an empty Map is used.
The last three arguments contain the technical user’s dn, the password, and the passwordMode, for example
ServiceSupport.init(maps, relations, "cn=DomainAdmin,cn=My-Company", "dirx", "identity");
| The values are stored in static variables for later use. No bind or other server interaction is performed within this method. |
The interface of the ServiceSupport.startSession method is described here in more detail:
int startSession(java.lang.String host,
int port,
java.lang.String domain,
java.lang.String user,
java.lang.String password);
| user must contain the effective user’s distinguished name. |
Here is a sample call to startSession in the My-Company domain:
int rc = session.startSession("localhost", 389, "cn=My-Company", "cn=Hungs Olivier,o=My-Company,cn=Users,cn=My-Company", "dirx");
startSession performs the technical bind (if it does not already exist) and authenticates the effective user. The result is stored in variable rc, with the following result codes:
| Result Code | Description |
|---|---|
BIND_OK |
All binds are OK, session is successfully created. |
BIND_TECHNICAL_ONLY |
The technical bind is OK, but authentication of the effective user failed. Must be repeated with the correct credentials of the effective user. |
BIND_NONE |
Technical bind failed. Init must be repeated with correct credentials. |
Using the API in a Java Application
To use the API in a standalone Java application, the support object implementing the interfaces that are provided by the API must be instantiated. This step can be performed in private members of a class:
private MetaRoleSupport support = new MetaRoleSupport();
private Session session = (Session)support;
private Objects objects = (Objects)support;
private Assignment assignment =(Assignment)support;
private Users users = (Users)support;
Next, the API must be initialized and a session must be started:
...
MetaRoleSupport.init (objectConfigs, relationConfigs, rendererMapping, technicalUser, technicalPassword, passwordMode);
...
int rc = session.startSession(host, port, domain, user, password);
A call to the API methods then is made with the same syntax as in the JSP environment.(See the section “How the API is Used in JSPs” for details.):
String forward = (String)objects.getObjectProperty(groupDN,
"targetsystem.dxrOptions(dialog)");
Sample Application UserSample.java
The use of the API is demonstrated in a simple sample application UserSample.java.The source code of the sample is provided in Web Center’s api/samples/src/samples/api folder.The sample executes the following tasks:
-
Initializes the API
-
Creates a user in the data store
-
Modifies the user’s attributes
-
Assigns a role to a user
-
Assigns a role with role parameters to a user
-
Removes a role assignment from a user
-
Displays the user’s attributes
-
Searches for users in the data store and lists the result.
The sample uses the following APIs:
-
Session
-
Objects
-
Users
-
Assignment.
Setting Up your IDE for the Sample
Perform the following steps in your Java IDE to set it up for the sample:
-
Create a new project for Java 8
-
Add the package samples.api to the new project’s source folder
-
Import the source file UserSample.java to that package
-
Add the jarfiles contained in Web Center’s WEB-INF/lib folder to the project’s class path. Note: You don’t really need all jarfiles from WEB-INF/lib; see file api/samples/readme.html for details.
Now you are ready to compile and run the sample in your IDE.
Initializing the API
Initialization is performed in the sample’s init method. Since only users, roles, and role assignments are subject to the sample, only three configuration entries are added to the property mapper (maps).
The sample runs in the My-Company domain. The DomainAdmin is used for the technical bind.
The effectiveUser is “Hungs Olivier”. His DN is passed to the sample’s bind method. Once the effective user has bound, the API is ready for use.
Creating a User
Use mode=”CREATE” (in main) to create a new user.
The parent folders that allow creation of a user depend on the effective user’s access policies. The method sample.getRootNodes displays all root nodes for user creation. It uses the API method Objects.getRootNodesForCreate.
By this method, the application can check if the logged-in user is allowed to create a new user (if there is at least one node returned), and what are the possible parent folders for user creation.
The user is created in sample.create user. This is performed in the following steps:
| No | Method | Description |
|---|---|---|
1 |
Users.createObject |
Creates an object of type “user” with the given RDN under the parentDN in memory. Default values of the object’s properties are calculated according to the object descriptions. No save to Ldap is performed at this step. |
2 |
Users.setObjectProperty |
Each call adds one property to the user object in memory. |
3 |
Users.saveObject |
Saves the user to the data store. Internally one Ldap modification set is created, and the user is added with one Ldap ADD operation. |
Use Objects.createObject to create other objects in memory. Setting the properties and saving the object is performed as described in steps 2 and 3 above.
Note, that “Olivier Hungs” has no create user access policy. Thus, no user is created, but the following error message is displayed:
Operation not allowed, no access policy found.
Just assign the group UserAdmins of the DirXmetaRole Target System to Olivier Hungs to enable him for user creation. Or use another login.
Modifying an Object
The newly created user is modified using sample.modifyData. This method may be used for all types of objects, not only for users.
Modification is performed in the following steps:
| No | Method | Description |
|---|---|---|
1 |
Objects.setObjectProperty |
Checks whether the object is present in the storage layer cache. If not, the object is loaded from the data store. Modifies the cached object’s property to the current value. Note that a value of null removes an attribute. No save to Ldap is performed at this step. |
2 |
Objects.saveObject |
Saves the modifications to the data store. |
Moving an Object
Moving an object to another parent DN is available in the Objects Interface. The method Objects.moveTo expects the parameters objectId (the DN of the object to be moved) and newParentId (the DN of the object’s new parent).
Note that Objects.moveTo does not check for access policies. You should call Users.isMoveAllowed to consider access policies prior to moving the object.
If you modify the object’s naming attribute by calling Objects.setObjectProperty and Objects.save (see above), the object is renamed in the data store. If you use a DirX Server, all DN changes (rename and move) are performed by the server in each attribute of type DirectoryDN, i.e. DN references to the object are automatically kept during move or rename.
Displaying an Object
Sample.showUserData displays some selected data of the user. It uses Objects.getObjectProperty to retrieve the data.
getObjectProperty first checks whether the object with the requested DN exists in the storage layer cache and loads it on demand. Next, it reads the property value from the object, taking into account the object description.
Note that multivalued properties are returned as an array, as it is shown with objectClass in the sample.
Searching Users
Sample.listUsers searches users in the directory and displays for each returned user the set of requested attributes.
The search is performed by Objects.listObjects. The method searches the directory according to the given filter and search base. It returns a two-dimensional list. The outer list contains one inner list for each object being returned by the search. The inner list contains the requested attributes in the order that was passed to listObjects.
Assigning a Role
To run the sample for assigning roles, change the mode in the main method to mode=”ASSIGN”. In this mode, sample.assignRole is called for the Gold Customer role, and sample.assignRoleWithParameters is called to assign the Project Member role, that requires the role parameter “Project” to be supplied with the assignment.
A role assignment of a role without parameters is performed in the following steps:
| No | Method | Description |
|---|---|---|
1 |
Objects.listObjects |
Checks if the role to be assigned is available. This is performed by calling listObjects for “availableRoles”. If a list of length = 0 is returned, then the role is not available for assignment. This may be due to a missing grant policy for the logged-in user. |
2 |
Assignment.assignObjectTo |
Assigns the privilege to the user in memory. |
3 |
Users.saveObject |
Saves the user and his assignments to the data store. Triggers an offline role resolution. |
In case a role with parameters is assigned, the role parameters must be added to the assignment. A sample for this procedure is shown in sample. assignRoleWithParameters. The assignment is performed in the following steps:
| No | Method | Description |
|---|---|---|
1 |
Objects.listObjects |
Checks if the role to be assigned is available. This is performed by calling listObjects for “availableRoles”. If a list of length = 0 is returned, then the role is not available for assignment. This may be due to a missing grant policy for the logged-in user. |
2 |
Assignment.assignObjectTo |
Assigns the privilege to the user in memory. |
3 |
Objects.listObjects |
Lists all assignedRoles of the user. For each assignment, the role’s cn, the assignment’s uid, and the role’s dn is requested. This step is required to get the assignment’s uid. |
4 |
Assignment. |
Checks if we have a role with role parameters |
5 |
Assignment. |
Returns the array of role parameters that are required for the considered role. |
6 |
aParam.getProposals |
Returns the array of possible values for that parameter. In a GUI, the user must select one or more parameter values and add it to the assignment. |
7 |
aParam.setValues |
Sets the selected role parameter values in the parameter object |
8 |
Assignment. |
Adds the parameter values to the assignment |
9 |
Users.saveObject |
Saves the user and his assignments to the data store. Triggers an offline role resolution. |
| Roles with role parameters may be assigned multiple times to the user. The assignment’s uid serves to identify the assignment in that case. |
| Multiple assignments (with and without role parameters) may be assigned or removed. All the edits are performed in memory, until the last step users.saveObject is called. A final call to Objects.resetObject (instead of saveObject) undoes all edits. |
Removing a Role Assignment
To run the sample for removing role assignments, change the mode in the main method to mode=”UNASSIGN”. In this mode, sample.unAssignRole is called for the Project Member role.
A role assignment is removed in the following steps:
| No | Method | Description |
|---|---|---|
1 |
Objects.listObjects |
Lists all roles being assigned to the user |
2 |
Assignment.unassignObjectFrom |
Removes the assignment in memory |
3 |
Users.saveObject |
Saves the user and his remaining assignments to the data store. Triggers an offline role resolution. |