SAP Cloud Platform

Updating Employees in Microsoft Active Directory from SAP CPI using LDAP Search and Modify Operations

Introduction:

In this blog post, I will be sharing a scenario which I have implemented to update an employee to AD using the LDAP Search and Modify Operations.

Scenario:

I will be getting data from an API. From that data,

  1. All the Active employees should be updated to AD.
  2. All the Terminated employees should be disabled in AD and their respective manager name should be removed.
  3. If an employee state is missing, I must raise a mail to the HR.

Prerequisites:

Cloud Connector: As AD which used here is an On-Premise system, we must establish a connectivity to CPI Tenant using SAP Cloud Connector.

Once the Cloud Connector part is done, we can start the development in CPI.

Design:

I have used Process Calls in the Integration for better readability and error handling.

Main Integration:

  • Used Content Modifier as a Source for this Integration Process for testing.
  • Used Parallel Multicast to share the same incoming data to all the Process Calls

1. Process Call: Active

  • As a first step, Filtered the incoming records to check the employee_status = ‘Active’.
  • Content Modifier to Add the root node after filter step as it removes the root.
  • General Splitter to separate the records as AD accepts only one record at a time for Updating.
  • Content Modifier to store the incoming attributes in Header as the structure is getting changed after the Request-Reply step. [These Header names will be used in the subsequent steps for performing the Search operation and in Updating the AD]
  • Router is used because, Manager attribute for few employees is empty in the payload and AD will not accept a Manager if empty.

So, used router to separate the incoming payload

  • Default route will used for records with Manager name.
  • Route 1 will be for the records with no Manager name.

I. Default Route:

  • Once the record is having Manager name, we need to get the Manager distinguishedName from AD as the manager name will be his DN in AD.
  • To achieve this, I have performed Search Operation to get the Manager distinguishedName from AD using his name coming in the payload.
  • For this we are using Request-Reply [1] with LDAP Adaptor.

Address: Provide the Virtual address what you have provided in the Cloud Connector.

Proxy Type: On-Premise

Authentication: Simple

Credential Name: Name what you gave to store the credentials in Security Material.

Operation: Search

Base DN: Entity from where you will begin the search.

Search Filter: Criteria which should qualify to fulfil the search.

Attribute: Here we are getting distinguishedName.

  • XSLT to remove extra header information.
  • Content Modifier to catch the Manager distinguishedName into header using XPATH.
  • Request-Reply [2] to get the Employee Distinguished Name from AD as we need to pass the DN as reference for the employee to AD to make sure the right record gets updated.
  • For this step, I have performed the same search operation what we did in the above step to get the Manager distinguishedName but changed the (cn=${header.display_name}).
  • Content Modifier to catch the Employee distinguishedName into header using XPATH.
  • Java Script to map the attributes as per the AD Structure.
importClass(com.sap.gateway.ip.core.customdev.util.Message);
importClass(java.util.HashMap);
importClass(javax.naming.directory.Attribute);
importClass(javax.naming.directory.BasicAttribute);
importClass(javax.naming.directory.BasicAttributes);
importClass(javax.naming.directory.Attributes);
function processData(message) {
var body = message.getBody();
var pMap=message.getHeaders();
var employeeNumber = pMap.get("employee_number");
var displayName = pMap.get("display_name"); 
var department = pMap.get("department"); 
var TelephoneNumber = pMap.get("business_phone");
var Company = pMap.get("company_name"); 
var UserPrincipalName = pMap.get("employee_SSO"); 
var employeeType = pMap.get("employee_category"); 
var ExtensionAttribute1 = pMap.get("employee_group"); 
var Title = pMap.get("job_title"); 
var mobile = pMap.get("mobile_phone"); 
var City = pMap.get("work_city"); 
var Country = pMap.get("work_country"); 
var PhysicalDeliveryOfficeName = pMap.get("work_location"); 
var Extensionattribute3 = pMap.get("work_region"); 
var State = pMap.get("work_state"); 
var manager_dn = pMap.get("distinguishedName"); 
var UserAccountControl = pMap.get("userAccControl");
var Employee_dn = pMap.get("employee_dn");
 var dn= Employee_dn;
           var EmployeeNumber = new BasicAttribute("EmployeeNumber", employeeNumber); 
            var DisplayName = new BasicAttribute("DisplayName", displayName); 
            var Department = new BasicAttribute("Department", department); 
            var telephonenumber = new BasicAttribute("telephonenumber", TelephoneNumber); 
            var company = new BasicAttribute("company", Company); 
            var userprincipalname = new BasicAttribute("userprincipalname", UserPrincipalName); 
            var employeetype = new BasicAttribute("employeetype", employeeType); 
            var extensionAttribute1 = new BasicAttribute("extensionAttribute1", ExtensionAttribute1); 
            var title = new BasicAttribute("title", Title); 
            var Mobile = new BasicAttribute("Mobile", mobile); 
            var l = new BasicAttribute("l", City); 
            var co = new BasicAttribute("co", Country); 
            var physicalDeliveryOfficeName = new BasicAttribute("physicalDeliveryOfficeName",   PhysicalDeliveryOfficeName); 
            var extensionattribute3= new BasicAttribute("extensionattribute3", Extensionattribute3); 
            var st= new BasicAttribute("st", State); 
            var Manager= new BasicAttribute("Manager", manager_dn); 
            var description= new BasicAttribute("description", Title); 
            var userAccountControl= new BasicAttribute("userAccountControl", UserAccountControl);  
   
    var attributes = new BasicAttributes();
    attributes.put(EmployeeNumber); 
    attributes.put(DisplayName); 
    attributes.put(Department); 
   attributes.put(telephonenumber); 
     attributes.put(company); 
   attributes.put(userprincipalname);
    attributes.put(employeetype);
    attributes.put(extensionAttribute1);
    attributes.put(title);
    attributes.put(Mobile);
    attributes.put(l);
    attributes.put(co);
    attributes.put(physicalDeliveryOfficeName);
    attributes.put(extensionattribute3);
    attributes.put(st);
    attributes.put(Manager);
    attributes.put(description);
     attributes.put(userAccountControl);
    var resultingMap = new HashMap();
    resultingMap.put("dn", dn);
    resultingMap.put("attributes", attributes);
    message.setBody(resultingMap);
        return message;
            return message;
}
  • Used Groovy to log the Payload for testing purpose.
  • Request-Reply [3] to Update the data into AD.

II. Route 1:

  • As we know that the records which comes in this way will not have Manager, we need to make it NULL.
  • Request-Reply [3] to get the Employee distinguishedName as we did the same to update the records with manager name.
  • Java Script to set the data. Used the same Script which I have used above except for the manager attribute.
  • For this I am changing var Manager= new BasicAttribute(“Manager”, null); from the above given code. [Here null is the keyword not the string]. If you pass a string, you will get Error.

2. Process Call 2: Terminated Employees

  • Filter to the incoming records to check the employee_status = ‘Terminated’.
  • Content Modifier to ADD the root node.
  • General Splitter to separate the records.
  • Content Modifier to save the incoming fields data into Header using the XPATH.
  • Request-Reply [1] to get the employee distinguishedName from AD as we for the Active Employees by performing Search
  • XSLT to remove extra header information.
  • Content Modifier to catch the Manager distinguishedName into header using XPATH.
  • Java Script to set the AD data. For this am using the same code which I have already provided in the previous step by changing userAccountControl attribute and the Manager Attribute.
  • To Disable an employee, set userAccountControl to 514.
  • Also change var Manager= new BasicAttribute(“Manager”, null); as Terminated employee will not have a manager
  • Request-Reply [2] to Update the Terminated employees into AD.
  • Followed the same procedure what I have done to update the Active Employees.

3. Process Call 3: Missing Data

  • Filter to the incoming records to check the work_state = ‘ ’.
  • Content Modifier to ADD the root node.
  • Used Router to stop unnecessary mails which will be triggered with only as we used content modifier to ADD root node.
  • Message Mapping to Map and get the work_location from the source as I was asked to send a mail with work_location of that state for which the data is missing.
  • General Splitter to separate the records.
  • Content Modifier to catch the work_location using XPATH.
  • Gather to combine the locations.
  • Used few more steps to build the final structure for Mail body and finally used send to send a mail sing the Mail Adaptor.

Leave a Reply

Your email address will not be published. Required fields are marked *