LDAP Functions(4.1)

The LDAP functions allow you to connect to an LDAP, using anonymous or simple authentication, and modify and delete entries or perform searches based on names, filters and explicitly define what attributes to be returned. The LDAP functions use connection pooling for best performance.

Note!

Due to the nature of LDAP, the following functions are not transaction safe and should therefore be used mainly for realtime workflows.


LDAP Related UDR Type

The UDR type created by default in the LDAP agent can be viewed in the UDR Internal Format Browser. To open the browser open an APL Editor, in the editing area right-click and select UDR Assistance...; the browser opens.


Error Handling

The default error handling for the functions ldapCreate, ldapSearch, and ldapScopeSearch is to handle all errors as exceptions, which means that the workflow will abort in the batch case and the request will typically be discarded in the realtime case.

If this is not desired behavior, it is possible to set these LDAP functions to suppress all communication errors and instead return null in error situations. In this case the error will be made available through the ldapGetLastError function.


Network Timeout Property

If there are network problems when communicating with the LDAP server the LDAP plugin commands use a network timeout of 5 minutes. This default timeout can be modified by setting the property mz.ldap.network.timeout to a timeout in milliseconds.

Set the property in the cell.conf or the relevant Execution Context <pico>.conf, depending on where where the workflow is executed.

Idle Connection Timeout

By default a connection remains within a pool in an idle state for five minutes before it is closed. To set the amount of time in milliseconds, set the property com.sun.jndi.ldap.connect.pool.timeout in the cell.conf or the relevant Execution Context <pico>.conf, depending on where the workflow is executed.


ldapCreate

Creates a connection towards an LDAP server, using either anonymous or simple authentication. This function is usually invoked in the initialize block.

any ldapCreate
   ( string  host , 
     int  port , 
     string  name ,
     string  principal ,    //Optional
     string  credentials  ) //Optional
ParameterDescription

host

The host name of the LDAP server

port

The port number of the LDAP server

name

Name which identifies the context in which the search will be performed. The value can span multiple naming systems and must be fully qualified and identify entries from the root of the LDAP server. If specified as null this means that the search will be performed from the LDAP root.

principal

Optional argument that defines the user to connect as. If omitted, the function will connect to the LDAP server using anonymous authentication. This argument requires that the credentials argument is supplied.

credentials

Optional argument that defines the user password.

Returns

An identifier used when invoking the search function.

If ldapSuppressErrors has been called, then this function returns null if an error is detected during communication with the LDAP server. ldapGetLastError should be used to get the error message in this case.

Example - Using ldapCreate

any ctx = ldapCreate("10.0.0.1", 389, "o=users");
...
any ctx = ldapCreate("10.0.0.1", 389, "o=users", 
            "cn=Administrator, o=users", "secret");


ldapAdd

The command is used to add an entry.

string ldapAdd
   ( any  identifier , 
     string  name , 
     list<string>  attributes  )

Parameters:

ParameterDescription

identifier

The connection identifier returned from ldapCreate.

name

The name of the entry to add. This is matched relative to the context specified with the name argument in ldapCreate. If no object matches the name, an error will be thrown stating there is no such name.

attributes

The new attribute value. If a delete operation is requested, the matching value is deleted.

Returns

In the event of an error, a message from LDAP server will be returned otherwise null.

ldapCloseCtx

The command is used to close a context that has previously been returned by ldapCreate.

int ldapCloseCtx
 ( object context )
ParameterDescription
context The context returned from ldapCreate.
ReturnsIf the function is successful, it will return 0.

ldapDelete

An APL command used to delete an entry.

string ldapDelete
   ( any  identifier , 
     string  name )
ParameterDescription

identifier

The connection identifier returned from ldapCreate.

name

The name of the entry to be deleted.

Returns

In the event of an error, a message from LDAP server will be returned otherwise null.


ldapGetLastError

Retrieves the error message of the last error reported for an LDAP command.

string ldapGetLastError()
ParameterDescription

Returns

The last error message that an LDAP function registered. This information is kept per thread and agent so it is only guaranteed to be present in the same APL code block as the function call causing the error.


ldapModify

An APL command used for modifying an entry by adding, replacing or deleting its attributes.

string ldapModify
   ( any  identifier , 
     string  name , 
     string  operation ,
     list<string>  attributeValue  ) //Optional
        
ParameterDescription

identifier

The connection identifier returned from ldapCreate

name

The name of the entry to modify

operation

The operation can be either ADD , REMOVE or REPLACE .

attributeValue

The list of new attribute values. If a REMOVE operation is requested, the matching values are deleted.

Returns

In the event of an error, a message from LDAP server will be returned otherwise null.


ldapSearch

Performs a search in a LDAP server based on a number of arguments.

list<ldapResult> ldapSearch
   ( any  identifier , 
     string  name , 
     string  filter ,          //Optional
     list<string>  retAttrs  ) //Optional
ParameterDescription

identifier

The connection identifier returned from ldapCreate

name

The name of the object to be searched for. This is matched relative to the context specified with the name argument in ldapCreate. If no object matches the name, an error will be thrown stating there is no such name.

filter

Optional value, specifying the attributes of the requested LDAP objects. This value conforms to RFC 2254. The specified filter will match objects, relative to the name parameter.

retAttrs

Optional list of strings that defines what attributes to be returned

Returns

A list of ldapResult UDRs, where every entry contains a name, an attribute and a list of values. The name value is the name relative to the target context of the search. If the target context matches the search filter, then the returned name will be an empty string. The attribute is the attribute name and the values are all values for the given attribute.

If ldapSuppressErrors has been called, then this function returns null if an error is detected during communication with the LDAP server. ldapGetLastError should be used to get the error message in this case.


ldapScopeSearch

Performs a search in a specified part of the LDAP server based on a number of arguments.

list<ldapResult> ldapScopeSearch
   ( any  identifier , 
     string  scope ,
     string  name ,
     string  filter ,          //Optional
     list<string>  retAttrs  ) //Optional
ParameterDescription

identifier

The connection identifier returned from ldapCreate

scope

The search scope, can be one of OBJECT_SCOPE , ONELEVEL_SCOPE or SUBTREE_SCOPE . For further information, see your LDAP manual.

name

The name of the object to be searched for. This is matched relative to the context specified with the name argument in ldapCreate. If no object matches the name, an error will be thrown stating there is no such name.

filter

Optional value, specifying the attributes of the requested LDAP objects. This value conforms to RFC 2254. The specified filter will match objects, relative to the name parameter.

retAttrs

Optional list of strings that defines what attributes to be returned

Returns

A list of ldapResult UDRs, where every entry contains a name, an attribute and a list of values. The name value is the name relative to the target context of the search. If the target context matches the search filter, then the returned name will be an empty string. The attribute is the attribute name and the values are all values for the given attribute.

If ldapSuppressErrors has been called, then this function returns null if an error is detected during communication with the LDAP server. ldapGetLastError should be used to get the error message in this case.

ldapSetPooling

The command is used to enable/disable connection pooling. Pooling is enabled by default.

void ldapSetPooling ( boolean value )
ParameterDescription
value The value should be set to either true or false.
ReturnsThe function returns nothing.


ldapSuppressErrors

An APL command used to change the error behavior of the other LDAP functions.

This function only changes the error behavior of the functions ldapCreate, ldapSearch, and ldapScopeSearch. It does not suppress errors for configuration errors (such as the user using invalid input for the function calls).

void ldapSuppressErrors
   ( boolean  value  )
ParameterDescriptionn

value

Whether or not errors should be suppressed.

Returns

Nothing

Example

Example - LDAP APL Plugins

// Demonstration of LDAP APL plugin functions

// The following code shows the following:
//
// 1) How to open a LDAP connection
// 2) How to add/delete an object to/from LDAP
// 3) How to change objects properties
// 4) How to perform different type of searches

void runDemoCode() {

  any ctx;
  string name = "DEMOUSER";
  string distinguisedName = "cn="+name;
  string error;
  list<string> attributes;
  list<ldapResult> result;

  // ==============================================
  // Opens a connection to a LDAP Server
  // ==============================================
  ctx = ldapCreate("127.0.0.1", 389, "dc=nodomain",
                   "cn=admin,dc=nodomain", "demo");    
             
  // ==============================================
  // Adding/Deleting/Modifying an LDAP Object
  // ==============================================
  
  //
  //Adds a new person object to the LDAP Server
  //
  attributes = listCreate(string);
  listAdd(attributes, "cn: "+name);
  listAdd(attributes, "objectClass: top");
  listAdd(attributes, "objectClass: person");
  listAdd(attributes, "sn: Test");
  listAdd(attributes, "description: Test Record");
  listAdd(attributes, "userPassword: {crypt}rkM1sTbxrERtE");
  
  error = ldapAdd(ctx, distinguisedName, attributes);
  if( error != null ) {
  debug("Error creating user: "+error);
  }
  
  //
  //Changes description for the created person object
  //
  attributes = listCreate(string);
  listAdd(attributes, "description: A demo user");
  
  error = ldapModify(ctx, distinguisedName, "REPLACE", 
                     attributes);
  if( error != null ) {
        debug("Error changing user description: "+error);
    }
    
  //
  //Removes user description from our person object
  //
  
  attributes = listCreate(string);
  listAdd(attributes, "description: A demo user");
  
  error = ldapModify(ctx, distinguisedName, "REMOVE", 
                     attributes);
  if( error != null ) {
  debug("Error removing user description: "+error);
  }
  
  //
  //Adds user description to our person object
  //
  attributes = listCreate(string);
  listAdd(attributes, "description: a description line");
  
  error = ldapModify(ctx, distinguisedName, "ADD", 
                     attributes);
  if( error != null ) {
  debug("Error adding user description: "+error);
  }
  
  //
  // Deletes our person object from the LDAP Server
  //
  error = ldapDelete(ctx, distinguisedName);
  if( error != null ) {
  debug("Error deleting user: "+error);
  }
  
  // ==============================================
  // Executing different searches against the LDAP
  // ==============================================

  // For demo purposes the LDAP tree should contain
  // two admin objects (a tree containing a backup
  // admin object).
  
  // Setup a filter for the search tests.
  // We are interested only in the attribute 'cn'.
  //
  list<string> attrFilter = listCreate(string);
  listAdd(attrFilter, "cn");
  
  //
  //Executes a normal search, should return size=1
  //
  result = ldapSearch(ctx, "dc=test", "cn=admin", attrFilter);
  debug("* Normal search");
  debug("result size="+listSize(result));
  printResultEntries(result);
  
  //
  //Scoped Search Types
  //
  //This search uses OBJECT scope, and should return size=1
  // Explanation:
  // The search only searches for a specific object, and the 
  // 'cn' attribute is returned for that object.
  //
  result = ldapScopeSearch(ctx, "OBJECT_SCOPE", "dc=test", 
                           "cn=admin", attrFilter);
  debug("* Object Scope");
  debug("result size="+listSize(result));
  printResultEntries(result);
  
  //
  //This search uses ONELEVEL scope, and should return size=1.
  //
  // Explanation:
  // The search executes a search on a unique level. Two objects
  // with the same name can not exists on the same level.
  //
  result = ldapScopeSearch(ctx, "ONELEVEL_SCOPE", "dc=test",
                           "cn=admin", attrFilter);
  debug("* Onelevel Scope");
  debug("result size="+listSize(result));
  printResultEntries(result);
  
  //
  //This search uses SUBTREE scope, and should return size=2.
  //
  // Explanation:
  // The search execute a search on sublevels, and return a
  // match for every admin object found (and we had two).
  //
  result = ldapScopeSearch(ctx, "SUBTREE_SCOPE", "dc=test",
                           "cn=admin", attrFilter);
  debug("* Subtree Scope");
  debug("result size="+listSize(result));
  printResultEntries(result);
}
  
//
// Help method that prints out the result of a ldapSearch
//

void printResultEntries(list <ldapResult> result)
{
  int resultIdx = 0;
  int resultCount = 0;
  int resultSize = listSize(result);
  while (resultCount < resultSize) {
      ldapResult entry = listGet(result, resultCount);
      debug("Name: " + entry.name);
      debug("Attribute: " + entry.attribute);
      int valueCount = 0;
      int valueSize = listSize(entry.values);
      while (valueCount < valueSize){
           debug("Value: " + listGet(entry.values, valueCount));
           valueCount = valueCount + 1;
      }
      resultCount = resultCount + 1;
    }
}