New Imperva Java SDK: Greasing The Wheels for Active Directory Coding Projects

words and research by Gabriel Beyo.

According to StackOverflow’s 2018 Developer Survey, Java remains one of the world’s most popular coding languages, universally liked for its versatility and ease of adoption.

Even so, working under the pressures developers often do, a bit of help always goes a long way. To that end, we’ve put together a shiny new software development kit ( SDK) for Java developers laboring through complex tasks, meant to help them with Active Directory (AD) projects.

In this post, we’ll unpack our new Imperva Java SDK, designed to simplify communication with AD for small, medium and large development projects.

First things first: What is DDC?

Domain Directory Controller (DDC) is a SDK designed to simplify AD interaction for small, medium and large development projects. A portable Java library, DDC comes with a friendly API, allowing you to quickly compose simple, or complex queries against AD’s endpoints without any previous LDAP knowledge.

Communicating with AD and LDAP protocol

Until now, in order to communicate with an AD server, we’d have to handle a host of issues manually; connection retries, switching between primary & secondary servers, performing queries against multiple servers, paging results and several other known-issues which might not be directly related to the task at hand.

An additional pain in the neck was the LDAP protocol we’d have to learn and understand in order to perform our queries against the AD server.

LDAP’s complicated syntax also happens to be different from other syntaxes we’re used to. Allow me to demonstrate: if you had to search for AD users located in Italy or Germany and their last login time was in between 10am and 3pm, your query would have looked like this:

(&(|(co=Italy)(co=Germany)) (&(lastLogin>=2018100000.OZ)(lastLogin<=2018150000.OZ)))

Think that was complex, just wait.

LDAP… but better

DDC was designed with developers in mind, to help free up precious time for the ‘big’ tasks. The goal of this library is to enable easy interaction with any LDAP Directory Server by hiding all the related communication issues and internal bits-and-bytes.

Internally, DDC makes use of apache-directory-ldap API and builts on it with a host of enhancements:

  • Assemble LDAP queries easily via an Object-Oriented syntax instead of concatenating and parsing strings
  • Although DDC currently supports Microsoft Active Directory only, it was designed to be easily extended to fit any other LDAP implementation
  • Easy Paging API
  • Change Requests: Add, Remove, Replace AD’s objects
  • Secured connection
  • Perform automatically connection retries in case of failure
  • Automatically resolve host to IP
  • Support search in Multiple AD servers
  • Support Primary & Secondary AD servers

Let’s see it in action

Say you’re looking to query the phone numbers of people named Gabriel, and the city they’re currently living in. First, you’ll need to create an endpoint object and set the connectivity information.

 

Endpoint endpoint = new Endpoint();

endpoint.setPort(389);

endpoint.setHost(“10.100.10.11”);

endpoint.setSecondaryHost(“10.100.10.100”);

endpoint.setPassword(“somepass”);

endpoint.setUserAccountName(“domain\\user”);
//* You can use the user’s Distinguished Name as well

 

Now we can configure the search information, including the specific fields we want to query.

 

QueryRequest queryRequest = new QueryRequest();

queryRequest.setEndpoints(new ArrayList<Endpoint>(){{add(endpoint);}});

queryRequest.setObjectType(ObjectType.USER);

queryRequest.addRequestedField(FieldType.EMAIL);

queryRequest.addRequestedField(FieldType.CITY);

 

The last thing to do is to execute the query and page the results:

 

QueryResponse result = new QueryResponse();

try(Connector connector = new Connector(queryRequest)) {

Cursor cursor = connector.getCursor();

while (cursor.hasNext()) {

       result.addPartitionResponse(cursor.next().get());

}

}

List fields = result.getAll().stream().map(res -> res.getValue()).collect(Collectors.toList());

 

Voilà! We did it, and without writing a single LDAP line of code while getting a host of goodies from DDC, including: Primary-Secondary support, performing queries against multiple endpoints and paging results.

At the end the entire piece of code should like something like this:

 

Endpoint endpoint = new Endpoint();

endpoint.setPort(389);

endpoint.setSecondaryPort(389);

endpoint.setHost(“10.100.10.11”);

endpoint.setSecondaryHost(“10.100.10.100”);

endpoint.setPassword(“somepass”);

endpoint.setUserAccountName(“domain\\user”); //* You can use the user’s Distinguished Name as well

QueryRequest queryRequest = new QueryRequest();

queryRequest.setEndpoints(new ArrayList<Endpoint>(){{add(endpoint);}});

queryRequest.setObjectType(ObjectType.USER);

queryRequest.addRequestedField(FieldType.EMAIL);

queryRequest.addRequestedField(FieldType.CITY);

QueryAssembler queryAssembler;

queryAssembler = new QueryAssembler();

Sentence firstNameSentence = queryAssembler.addPhrase(FieldType.FIRST_NAME, PhraseOperator.EQUAL, “Gabriel”).closeSentence();

queryRequest.addSearchSentence(firstNameSentence);

QueryResponse result = new QueryResponse();

try(Connector connector = new Connector(queryRequest)) {

Cursor cursor = connector.getCursor();

while (cursor.hasNext()) {

    result.addPartitionResponse(cursor.next().get());

}

}

List fields = result.getAll().stream().map(res -> res.getValue()).collect(Collectors.toList());

 

Say no to spaghetti code

The above examples were focused on static queries, meaning that the size and type of the queries are fixed. But imagine a scenario where you need to assemble dynamic queries using LDAP syntax.

Say you want to fetch the email, city, phone number and the distinguished name of an arbitrary list; supplied at runtime, of users that are part of the IT department or are users with Italy as their ‘country’ results.

Your input, in this case, would be an arbitrary list of usernames and the output you’d want the LDAP query string to use. In this case, you’d end up with “ugly code” created with StringBuilder, loops and nested loops trying to compose something like this:

 

(|(&(|(givenName=Ivie)(givenName=Soren)(givenName=Lacey)(givenName=Gracie)(givenName=James)(givenName=William)(givenName=Harry)(givenName=Daniel)(givenName=Joseph))(department=IT))(co=Italy))

 

Here’s where DDC saves you from the struggle and enables you to work with a strong syntax that prevents silly mistakes.

Imperva DDC is an open source project. Source files, full documentation, and a starter kit project can be found in Imperva’s official Open Source repository.  Feel free to download, use it and contribute back to the community.

Keep your finger on the pulse

Sign up for updates from Imperva, our affiliated entities and industry news.