Skip to Content
Product Information

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! 🙂

 

12 Comments
You must be Logged on to comment or reply to a post.
  • 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.

     

    • 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!

      • Thanks Mani!

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

        • 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

  • 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

    • 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

  • 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
    • 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

       

      • 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

        • 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?

  • 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