As of version 8.0, SAP Identity Management has a new redesigned java-based Lotus Notes Connector. It leverages completely the Lotus Domino’s server java API to greatly simplify the initial setup and to lower the cost of its consecutive usage by calling methods remotely using CORBA. This way it is no longer necessary to have the Lotus Notes Client installed locally on the Identity Management system nor to rely on Visual Basic or C components.
Since the Domino API’s resetUserPassword method is only supported on the server and cannot be invoked remotely, the Identity Management’s connector has to call a dedicated Domino Agent for this task.
In this blog post I am going to provide detailed instructions how to implement such Agent and how to use it with SAP Identity Management.
So what exactly is a Lotus Domino agent? As we can read in the IBM’s documentation: “Agents are stand-alone programs that perform a specific task in one or more databases. Agents are the most flexible type of automation…”. These stand-alone programs run on the Domino server and can be invoked either directly, based on event, or scheduled to run periodically. In our case, we are going to call Agent’s methods directly from the Identity Management Java connector.
To implement a Lotus Domino Agent, we will need the IBM Lotus Domino Designer which can be downloaded from here: http://www-03.ibm.com/software/products/en/ibmdominodesigner
After you have the Designer up and running, we can start with the implementation.
The new agent is created and automatically opened. You can see that in the Agent Contents tree there is a source folder with default package and Java class generated. Open the JavaAgent.java class.
You can see that inside, we have a NotesMain() method which is the entry point of the agent.
Now we have a placeholder for the resetUserPassword method which is part of the Session class. You can find its documentation here: http://www-01.ibm.com/support/knowledgecenter/SSVRGU_8.5.3/com.ibm.designer.domino.main.doc/H_RESETU.... From the documentation, we can read that the method “…is only supported on the server.” And “This method is only supported in agents.” Also it takes three string arguments: servername, username and password. The server name is the “Canonical name of the server or servers to execute the agent”. The username is the one of the user we want to change the password for. The password is the new password for this user.
As we saw earlier, the NotesMain() method which is the entry point of the agent does not have any parameters. So how do we send the servername, username and password from Identity Management? The Lotus Notes connector uses the runOnServer() method of the Domino API’s Agent class to run the password reset agent. This method comes in two flavors: the first one without any parameters, which just invokes the agent’s code (NotesMain()). The second one has one string argument which is the note id of a Notes document.
Notes Document or Note is a central part of the Lotus Notes architecture. It is an object data store which “is a compound structure of mixed data types arranged in fields that can be arbitrarily modified and extended. A note may contain text, rich text, binary blobs (attachments, ActiveX or Java applets, for instance), encryption keys, doclinks, and so on. Each Notes database contains a collection of notes, and includes meta-organizing structures for display, security, retrieval and access rights to the notes.”
In our case, we create a note document inside the Agent’s database and use this document to pass the parameters to the password reset method. So prior to invoke the agents code, the Identity Management connector creates a new Note and puts three key-value pairs: server, username and password with their respective values. Once the document is created, the connector gets its Note Id (or unique identifier) and passes it to the runOnServer() method.
On the agent’s side we have to open that document and extract the parameters from it. This is done in the following way:
First we need to acquire the current agent’s instance with the following code:
Agent thisAgent = agentContext.getCurrentAgent();
You can see that we use the agentContext which is already available in the generated agent code. Next we have to acquire the note id of the document holding the parameters:
String paramid = thisAgent.getParameterDocID();
Once we have the document id, we need to look up the agent’s database and from it to extract the document using its ID:
Database db = agentContext.getCurrentDatabase();
Document doc = db.getDocumentByID(paramid);
Now we have the document with our three parameters, but how to get their values? For this purpose we will use the getItemValue() method of the Document class. It has one parameter - the name of the item or in our case the parameter and returns a java.util.Vector of values. So to get the values of the three parameters, we can use these statements:
Vector serverVector = doc.getItemValue("server");
String server = null;
if (serverVector != null && serverVector.size() > 0) {
server = (String) serverVector.get(0);
}
Vector usernameVector = doc.getItemValue("username");
String username = null;
if (usernameVector != null && usernameVector.size() > 0) {
username = (String) usernameVector.get(0);
}
Vector passwordVector = doc.getItemValue("password");
String password = null;
if (passwordVector != null && passwordVector.size() > 0) {
password = (String) passwordVector.get(0);
}
Now we have all we need to call the method that will actually reset the user’s password:
session.resetUserPassword(server, username, password);
It is important that the resetUserPassword method as well as most methods from the Notes API can throw a NotesException. This is a checked exception and you have to surround its invocation with try-catch block. Also it is peculiar that the NotesException class is not standard exception – if you try to get the exception’s message using getMessage() method or the stack trace using getStackTrace(), you will most likely get something useless. Instead, the NotesException class has three public fields: id, text and internal. The first two are the error’s code and text description and the third one is the stack trace of the exception. So if you want to print useful error message to the log, use the id and the text fields.
To actually get a logging object with which to log the agent’s actions in a text file for example, you can use this snippet:
Log log = session.createLog(thisAgent.getName());
log.openAgentLog();
log.openFileLog("path-to-log-file.log");
Then you can use the logAction() method to log events:
log.logAction("Exception: " + e.id + “ – “ + e.text);
To return value back to the Identity Management connector, we will use the same Notes document with which the input parameters were passed. We will use the replaceItemValue() method of the Document class to add new key-value pair holding the result:
doc.replaceItemValue("result", Boolean.valueOf(isReset));
doc.save(true,true);
It is important to call the save() method to actually commit the changes.
Note: Unfortunately there is a weird quirk in the resetUserPassword() java method. It always returns false even if the password is reset successfully. For this reason the result handling is a little odd we have to check for NotesExceptions during password reset: if there are such, we return false otherwise we return true.
Once the agent is implemented, we have to set the appropriate access rights so that it would be able to reset passwords. First double-click on the agent to open its content. You should see the Properties view. It has three tabs: Basics, Security and Document Selection. In the Basics tab, you have to set the Runtime area settings as follows:
The rest should be with the default values. In the Security tab:
Next step is to make the user used to sign the agent to be a “Designated Password Re-setter”. First you have to check which username is used to sign the agent. In the Domino Designer, go to: “File -> Security -> User Security…”. In the “Who You Are” area you can see the Name value. In my case this is “Administrator/sap”.
For more details have a look at the IBM Domino Documentation: http://www-01.ibm.com/support/knowledgecenter/SSKTMJ_9.0.1/admin/conf_assigningpasswordresetauthorit...
Source code:
public class JavaAgent extends AgentBase {
public void NotesMain() {
Log log = null;
Document parametersDocument = null;
try {
Session session = getSession();
AgentContext agentContext = session.getAgentContext();
Agent currentAgent = agentContext.getCurrentAgent();
Database currentDatabase = agentContext.getCurrentDatabase();
log = session.createLog(currentAgent.getName());
log.openAgentLog();
log.openFileLog("C:\\D\\agentlogBackend2.txt");
String parametersDocumentId = currentAgent.getParameterDocID();
parametersDocument = currentDatabase.getDocumentByID(parametersDocumentId);
Vector serverVector = parametersDocument.getItemValue("server");
String server = null;
if (serverVector != null && serverVector.size() > 0) {
server = (String) serverVector.get(0);
}
Vector usernameVector = parametersDocument.getItemValue("username");
String username = null;
if (usernameVector != null && usernameVector.size() > 0) {
username = (String) usernameVector.get(0);
}
Vector passwordVector = parametersDocument.getItemValue("password");
String password = null;
if (passwordVector != null && passwordVector.size() > 0) {
password = (String) passwordVector.get(0);
}
log.logAction("Reseting password...");
session.resetUserPassword(server, username, password);
parametersDocument.replaceItemValue("result", "true");
parametersDocument.save(true, true);
log.logAction("Return value: true");
} catch (NotesException e) {
try {
log.logError(e.id, e.text);
parametersDocument.replaceItemValue("result", "false");
parametersDocument.save(true, true);
} catch (NotesException e1) {
e1.printStackTrace();
}
}
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
30 | |
19 | |
10 | |
10 | |
8 | |
7 | |
7 | |
7 | |
6 | |
6 |