Skip to Content
Product Information
Author's profile photo Sana Faraz

Search Operation in LDAP Adapter in SAP Cloud Platform Integration

LDAP is lightweight directory access protocol. A directory is a location on the network that helps us locate some information. LDAP is designed to access large set of data fast hence improving the performance. LDAP is widely used for authentication for storing users and their data.

LDAP is used in Microsoft’s Active Directory (AD) and in open source tools like Open LDAP. In the examples mentioned below I will be using both Active Directory and Open LDAP for your disposal.

In SAP Cloud Platform Integration(CPI), we have the LDAP Receiver Adapter for making calls to your LDAP server. We support operations Insert, Modify, Delete and Search. The operations Insert and Modify are explained in this post and Delete operation is pretty straightforward, if you provide the Distinguished Name of the entity and that will be deleted.

In this blog post, we will be focusing on only the Search operation and its use cases. We have also assumed that you are aware of the cloud connector configuration and use of the virtual host as the address of the LDAP server in the integration flow.


Search Operation Configuration

When using LDAP Adapter version 1.3, you should be able to see the ‘Search’ in the operation drop down

Base DN

Entity from where you will begin the search. This is not a mandatory field, but we highly suggest using this to refine your search. In some LDAP serves, there is a default base DN and other servers mandate this.

Scope

Target portion that is defined to find the potential matches. There are 3 kinds of scopes:

  1. Object Specifies that only the base DN will be considered
  2. One Level – Specifies that the immediate level after the base DN be considered
  3. Subtree – Specifies the entire subtree after the base DN to be considered

Search Filter

Criteria which should qualify to fulfill the search

Output Type

Result of search operation, can be perceived as either XML data or as JNDI Attributes

  1. XML Output will be in XML structure. Below is the sample response structure for the XML Output Type. Notice that now there is a new <Entry> tag which is used to differentiate between the result entries. <DistinguishedName> and <ObjectClass> will be populated only if they have been selected. You can also use the same payload to do Insert or Modify operations provided that there is just one <Entry> because these operation insert/update only one entity at one time.
<Schema>
	<Entry>
		<DistinguishedName>...</DistinguishedName>
		<ObjectClass>...</ObjectClass>
		<Attributes>
			<Attribute1>...</Attribute1>
			<Attribute2>...</Attribute2>
		.
		.
			<AttributeN>...</AttributeN>
		</Attributes>
	</Entry>
	.
	.
	<Entry>
		<DistinguishedName>...</DistinguishedName>
		<ObjectClass>...</ObjectClass>
		<Attributes>
			<Attribute1>...</Attribute1>
			<Attribute2>...</Attribute2>
		.
		.
			<AttributeN>...</AttributeN>
		</Attributes>
	</Entry>
</Schema>
  1. Java (JNDI) Attributes – This will set the output body as List<javax.naming.directory.Attributes>. Each entry will be a part of the list. You should ideally use the script step after to make manipulation to the body according to your usecase.

Attributes

The list of attributes you want to fetch in the search. All attributes will be returned if nothing is entered. This is case insensitive. If you have entered an incorrect attribute, the search will not fail, the result will just not have that attribute.

Size limit

Maximum number of entries to be returned from the search. This must be numeric and zero signifies no size limit i.e all entries will be returned.

Timeout

Maximum time in minutes that the search can take. Zero implies that the client will wait indefinitely for the result.


Performing Search

Unlike other LDAP operation like insert and update that are limited to just one entity at one time, the search operation can return multiple entities based on the criteria mentioned by you. In this section, we will perform some basic searches to get you started.

Sample Integration Flow

The integration flow used in this blog post is timer triggered and gets the data from the LDAP server and attaches it to the message processing log as an attachment.

Example Scenarios

As mentioned earlier I will be using Active Directory as well as Open LDAP servers in this section. The data and schema maintained in both are different. This is done just so that you can have an overview of how search can be performed.

Disclaimer: The same result can be achieved in many ways, below are examples which you can refer to.

Active Directory Examples

  • Get names of all ‘Users’ entity

The processing tab of the LDAP Receiver Adapter would look like below.  I am selecting the root of users as the base DN with my search criteria ‘objectClass=user’ and selecting only the name attribute.

Response
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Schema>
  <Entry>
    <Attributes>
      <name>Administrator</name>
    </Attributes>
  </Entry>
  <Entry>
    <Attributes>
      <name>Guest</name>
    </Attributes>
  </Entry>
  <Entry>
    <Attributes>
      <name>John</name>
    </Attributes>
  </Entry>
..
..
</Schema>

  • Getting all details of disabled Users whose CN contains ‘John’

Use * as a wildcard for such filter operations and & operand ensures both conditions are true to qualify. The attributes field is empty to view all attributes.

Response
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Schema>
  <Entry>
    <objectClass>top;person;organizationalPerson;user</objectClass>    <distinguishedName>CN=john,CN=Users,DC=XXXXXX,DC=XXXXXX,DC=sap,DC=corp</distinguishedName>
    <Attributes>
      <proxyAddresses>abc@sap.com;test@gmail.com</proxyAddresses>
      <sAMAccountType>805306368</sAMAccountType>
      <primaryGroupID>513</primaryGroupID>
      <badPasswordTime>0</badPasswordTime>      <objectCategory>CN=Person,CN=Schema,CN=Configuration,DC=XXXXXX,DC=XXXXXX,DC=sap,DC=corp</objectCategory>
      <mail>john.doe@sap.com</mail>
      <cn>john</cn>
      <userAccountControl>514</userAccountControl>
      <telephoneNumber>2343434</telephoneNumber>
      <dSCorePropagationData>16010101000000.0Z</dSCorePropagationData>
      <codePage>0</codePage>
      <whenChanged>20191219091709.0Z</whenChanged>
      <whenCreated>20191219091709.0Z</whenCreated>
      <pwdLastSet>0</pwdLastSet>
      <logonCount>0</logonCount>
      <accountExpires>9223372036854775807</accountExpires>
      <lastLogoff>0</lastLogoff>
      <objectGUID>c5142903-68fb-4dab-9f47-b10da758e707</objectGUID>
      <lastLogon>0</lastLogon>
      <uSNChanged>259902</uSNChanged>
      <uSNCreated>259901</uSNCreated>
      <objectSid>S-1-5-21-3722266703-2459750493-1115606453-17015</objectSid>
      <countryCode>0</countryCode>
      <sAMAccountName>john</sAMAccountName>
      <instanceType>4</instanceType>
      <badPwdCount>0</badPwdCount>
      <name>john</name>
    </Attributes>
  </Entry>
  <Entry>
    <objectClass>top;person;organizationalPerson;user</objectClass>    <distinguishedName>CN=johnny,CN=Users,DC=XXXXXX,DC=XXXXXX,DC=sap,DC=corp</distinguishedName>
    <Attributes>
      <sAMAccountType>805306368</sAMAccountType>
      <primaryGroupID>513</primaryGroupID>
      <badPasswordTime>0</badPasswordTime>      <objectCategory>CN=Person,CN=Schema,CN=Configuration,DC=XXXXXX,DC=XXXXXX,DC=sap,DC=corp</objectCategory>
      <mail>johnny.doe01@sap.com</mail>
      <cn>johnny</cn>
      <userAccountControl>514</userAccountControl>
      <codePage>0</codePage>
      <whenChanged>20191219091734.0Z</whenChanged>
      <whenCreated>20191219091734.0Z</whenCreated>
      <pwdLastSet>0</pwdLastSet>
      <logonCount>0</logonCount>
      <accountExpires>9223372036854775807</accountExpires>
      <lastLogoff>0</lastLogoff>
      <objectGUID>e8e94bd0-73c9-44fc-8382-229b25773621</objectGUID>
      <lastLogon>0</lastLogon>
      <uSNChanged>259905</uSNChanged>
      <uSNCreated>259904</uSNCreated>
      <objectSid>S-1-5-21-3722266703-2459750493-1115606453-17016</objectSid>
      <countryCode>0</countryCode>
      <sAMAccountName>johnny</sAMAccountName>
      <instanceType>4</instanceType>
      <badPwdCount>0</badPwdCount>
      <name>johnny</name>
    </Attributes>
  </Entry>
</Schema>

  • Searching with ObjectGUID with Java (JNDI) Attributes return type

For ObjectGuid: 2ac32557-be63-407e-a428-02341fa39b7f you will have to convert it to escaped hexadecimal bytes to use it in search which becomes \57\25\c3\2a\63\be\7e\40\a4\28\02\34\1f\a3\9b\7f

Response
// String representation of the list
[{distinguishedname=distinguishedName: CN=hci1,CN=Users,DC= XXXXXX,DC= XXXXXX,DC=sap,DC=corp}]
Example script to interpret the response
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.List;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.NamingEnumeration;
def Message processData(Message message) {
    //Body 
       List<Attributes> body = message.getBody();
       // Iterate over the entities
       for(Attributes attributes : body){
       NamingEnumeration enumeration = attributes.getAll();
       // Iterate over the attributes of the entity
        while (enumeration.hasMore()) {
            BasicAttribute attribute = (BasicAttribute) enumeration.next();
            // Attribute Key
            String attributeName = attribute.getID();
            // Attribute Value
            String attributeValue = (String) attribute.get();
            def messageLog = messageLogFactory.getMessageLog(message);
            if(messageLog != null){
                messageLog.addAttachmentAsString(attributeName, attributeValue, "text/xml");
            }
        }
    }
       
}

Open LDAP Examples

  • Get 5 women of ‘OrganizationalPerson’ who reside in Bangalore

Here we have 3 conditions to fulfil with objectClass to identify the category, address to look for Bangalore and title to look for women. Size limit is 5 to imply maximum of 5 employees to fetch who qualify these conditions

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Schema>
	<Entry>
		<Attributes>
			<name>Annie Benitha</name>
			<age>28</age>
			<title>Miss</title>
			<registeredAddress>Richmond Road, Bangalore</registeredAddress>
		</Attributes>
	</Entry>
	<Entry>
		<Attributes>
			<name>Sadiya Kauser</name>
			<age>29</age>
			<title>Mrs</title>
			<registeredAddress>Tippsandra Colony, Bangalore</registeredAddress>
		</Attributes>
	</Entry>
	<Entry>
		<Attributes>
			<name>Deepa U</name>
			<age>31</age>
			<title>Mrs</title>
			<registeredAddress>HSR Layout, Bangalore</registeredAddress>
		</Attributes>
	</Entry>
	<Entry>
		<Attributes>
			<name>Mahashwetha Rao</name>
			<age>39</age>
			<title>Ms</title>
			<registeredAddress>Ganganagar,2nd cross,Sector 8, Bangalore</registeredAddress>
		</Attributes>
	</Entry>
	<Entry>
		<Attributes>
			<name>Aliya Amreen</name>
			<age>35</age>
			<title>Mrs</title>
			<registeredAddress>HRBR Layout Bangalore</registeredAddress>
		</Attributes>
	</Entry>
</Schema>

  • Getting multi values attributes

Some attributes have multiple values in CPI, we differentiate them with a ;(semicolon), for example objectClass.

Response
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Schema>
	<Entry>
		<objectClass>top;person;company</objectClass>    
	</Entry>
	<Entry>
		<objectClass>top;person;company</objectClass>    
	</Entry>
</Schema>

 

Summary

Now that you know how easy it is to use search in the LDAP adapter.Go ahead and try it yourself. I would also suggest to get rid of the script step where you have manually tried searching, use the adapter instead, to control all your configurations.

Feel free to write a comment for feedback. Looking forward to hearing from you! 🙂

 

Assigned Tags

      28 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Praveen Varriam
      Praveen Varriam

      Hi Sana,

      This blog was right on time. Nicely written and covered different search filters.

      I have tried the search LDAP option and it works fine just as mentioned.

      Is there any way that we can assign parameter in Search Filter box and pass the required value from message mapping to search criteria for dynamic search operation/lookup?

       

      Thanks

      Praveen.

       

      Author's profile photo Mani Rajendran
      Mani Rajendran

      Hi Praveen, Yes it is possible.

      You can give something like as follows:

      (&(ObjectClass=User)(userPrincipalName=${property.email}))

      Make sure that email parameter is assigned with value from incoming xml in previous content modifier.

      All the best!

      Author's profile photo Sana Faraz
      Sana Faraz
      Blog Post Author

      Thanks Mani!

      You can not only have dynamic values with properties with ${property.<propertyName>} but also using headers with ${header.<headerName>}

      Author's profile photo Praveen Varriam
      Praveen Varriam

      Thank you Mani and Sana.

      I could add both Headers and Property names without trouble and able to successfully connect LDAP with XML output which I have used for additional message mapping requirements.

      Much appreciated for your direction!

      Thanks!

      Praveen Varriam

      Author's profile photo Mani Rajendran
      Mani Rajendran

      Good Blog Sana and right on time. Cheers

      Author's profile photo Daniel Zutzmann
      Daniel Zutzmann

      Hi Sana,

       

      thank you for the blog, works like a charm.

       

      I have one question/demand. The MS active directory usually is set to a pagesize of 1000. Let's assume that we cannot increase this limit and the data set is 15000. Is it possible to loop through the pages in the ldap adpater so I get back all the data? Can we manipulate a filter parameter for this requirement?

      Regards,

      Daniel

      Author's profile photo Sana Faraz
      Sana Faraz
      Blog Post Author

      Hi Daniel,

      As of now, we do not have such a feature in CPI. You can however design your integration flow with looping integration process. The filter parameter can be injected into the LDAP adapter dynamically by using it as a header or property.

      Regards,
      Sana

      Author's profile photo Vineeth Bangalore
      Vineeth Bangalore

      Hi Sana,

       

      This blog is really helpful.

      In continuation to your above answer, could you please explain it in more detail. You're asking us use filter paramter dynamically right, so is there a way to specify in pagination in it? If so, could you please let us know what is the syntax for it.

       

      Regards,

      Vineeth.B

      Author's profile photo silverbird pantalch
      silverbird pantalch

      Hi Sana,

       

      We have the same situation. We need to extract records from AD however it is only returning 1,000 records.

       

      Hope you can provide guidance how this was addressed.

       

      Br,

      Charles

      Author's profile photo Shameer Shaik
      Shameer Shaik

      Hi Daniel,

       

      I have same query, Usually MS active directory is set to 1000 page size considering performance issues. We are able to pull only 1000 records from CPI. Did you find any way to pull full set of records using pagination or any other way?

      Author's profile photo Wajahat Imam
      Wajahat Imam

      Hi Sana,

       

      Thank you for the blog, its really help for us to do through operation instead of script.

       

      I am facing an issue during search a user.

       

      when I am deploying this process it is giving me below error.

       

      com.sap.it.rt.adapter.ldap.exception.LdapRuntimeException: nested exception is javax.naming.PartialResultException [Root exception is javax.naming.NamingException: problem generating object using object factory [Root exception is java.lang.IllegalArgumentException: argument must be a 'datasource:/' URL string or an array of them]]
      Can you please help on this issue?
      Thank you in advance,
      Wajahat Imam
      Author's profile photo Sana Faraz
      Sana Faraz
      Blog Post Author

      Hi Wajahat,

      Looks like something is incorrect either in your Base DN or the address of the LDAP server. Could you please recheck those.

       

      Regards,
      Sana

       

      Author's profile photo Wajahat Imam
      Wajahat Imam

      Hi Sana,

       

      Thank you for quick response.

       

      My connection URL and Base DN is working good because I was using the same above mentioned search query through groovy and working well.

       

      You can see in below screen shots when I remove the user search and only keep objectClass=user,

      integration is running well.

       

      Please advice.

       

       

      Thank you,

      Wajahat Imam

      Author's profile photo Sana Faraz
      Sana Faraz
      Blog Post Author

      Hi Wajahat,

       

      I tried a similar scenario with my AD server but unable to reproduce the issue. Could you then change the base DN to start from user and then look for your 'sAMAccountName' in the filter?

      Author's profile photo Sana Faraz
      Sana Faraz
      Blog Post Author

      Hi Wajahat,

       

      I found a limitation in the search with referrals in Active Directory servers. I am in the process of fixing this and it should resolve your issue.

       

      Regards,
      Sana

      Author's profile photo Lavanya Lakshminarasimhan
      Lavanya Lakshminarasimhan

      Hi Sana

      Thank you for the blog, I am receiving the same error as Wajahat Imam when I use the scope as subtree. I do get an error free response (Empty schema) when the scope is Object. Is there a solution for this.

       

      Thanks

      LL

      Author's profile photo Sana Faraz
      Sana Faraz
      Blog Post Author

      Hi Lavanya,

      As informed by you, you have fixed the issue by adding OU to Base DN.

      Author's profile photo Shruthi Anantha
      Shruthi Anantha

      Hi Sana,

      How can I query to get samAccount Name through SuccessFactors userId using LDAP adapter.

      Author's profile photo Sana Faraz
      Sana Faraz
      Blog Post Author

      Hi Shruthi,

      You can parameterize your userId from SuccessFactor as header or property and then use it in the query of the search operation.

      Author's profile photo Pushkar Patel
      Pushkar Patel

      Hi Sana,

       

      I am trying to add a user in AD group using insert in LDAP connector.  I am getting getting INSUFF_ACCESS_RIGHTS) error code back from AD. I have been advised by Infra team user do have sufficient access.

       

      When I tried Modify operation, user is added to the group but LDAP call is deleting existing members of that group.

      LDAP Insert Query ->
      {dn=CN=GrTesting,OU=Groups,OU=APAC,DC=global,DC=company,DC=com,DC=au, DistinguishedName_Previous=null,

      attributes={ObjectClass=ObjectClass: group, member=member: cn=Pushkar Patel,OU=User Accounts,OU=Test,OU=APAC,DC=global,DC=company,DC=com,DC=au}}

      I am using below XML schema to create above query.

      <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:element name="Schema">
      <xs:complexType>
      <xs:sequence>
      <xs:element type="xs:string" name="objectClass"/>
      <xs:element type="xs:string" name="distinguishedName"/>
      <xs:element name="Attributes">
      <xs:complexType mixed="true">
      <xs:sequence>
      <xs:element type="xs:string" name="member" minOccurs="0"/>
      </xs:sequence>
      </xs:complexType>
      </xs:element>
      </xs:sequence>
      </xs:complexType>
      </xs:element>
      </xs:schema>

      Any suggestion what could be wrong here?

      Thanks,
      Pushkar

      Author's profile photo Sana Faraz
      Sana Faraz
      Blog Post Author

      Hi Pushkar,

      The member field allows insert of multiple attributes, modifying it in CPI removes the existing ones and adds the new one. This is currently a limitation.

      A workaround solution would be to search for the existing members and then concatenate that to the new one you wish to add and then use the modify operation.

      \

       

      Author's profile photo sai chintalapudi
      sai chintalapudi

      Hi Sana,

      I have requirement to add delta query in search filter like if lastmodified is with in 30 days , i have to get those.

      Please let me know any search attributes for this.

      Thanks,

      Saidarao

      Author's profile photo Sana Faraz
      Sana Faraz
      Blog Post Author

      You could try writing a script which stores header with the current date and end date. Use these headers in your search field in LDAP

      Author's profile photo Krushna Band
      Krushna Band

      Hi Sana/All,

      I am beginner in SAP CPI and wanted to learn about LDAP adapter. I wanted to ask, how will I get Connection parameters for this adapter, Do I need to install any software, Can you please guide here It would be a great help.

      Author's profile photo Sana Faraz
      Sana Faraz
      Blog Post Author

      Hi Krushna,

      Check this blog: https://blogs.sap.com/2017/11/05/sap-cloud-integration-cloud-connector-ldap-integration/. Should give you some tips on how to get started!

      Author's profile photo Prasenjit Sarkar
      Prasenjit Sarkar

      Thank you, it worked smoothly for me. So happy we have this feature now.

      Author's profile photo Kate Tsan
      Kate Tsan

      Hi Experts,

      I'm new of CPI and using LDAP adapter to connect AD server with below parameters. However, it shows error message : "com.sap.it.rt.adapter.http.api.exception.HttpResponseException: An internal server error occured: LDAP connection has been closed."

      Is there anyone could give me some hint?

      Thanks in advance

       

      Author's profile photo Sana Faraz
      Sana Faraz
      Blog Post Author

      Mostly likely a cloud connector issue, please check if you are missing any location id and if the internal host is configured correctly.