Category Archives: Directory Services and LDAP

OpenDJ: REST to LDAP, part 4

OpenDJ Community Logo Since my last post on the subject, Matt and Jean-Noël have added additional features in REST/HTTP access to OpenDJ data, as well as fixes for issues found in testing.

  • The patch operation is now supported.
  • The HTTP connection handler now has its own access log.

Patch

OpenDJ now lets you patch JSON resources in addition to replacing them entirely. For example, you can replace an old email address with a new one. The data for the HTTP PATCH request would be an array with a single email value to replace that of the “emailAddress” field.

[
  {
    "operation": "replace",
    "field": "/contactInformation/emailAddress",
    "value": "babs@example.com"
  }
]

OpenDJ supports four patch “operation” types.

  1. “add”: ensures the target field of the resource contains the value(s) you provide, creating parent fields as necessary.
  2. “remove”: ensures the target field does not contain the value(s) you provide. If you do not provide a value, the entire field is removed if it already exists.
  3. “replace”: like a “remove” followed by an “add”, this removes existing values, replacing them with the values you provide.
  4. “increment”: increments numeric value(s) when you provide a positive number value. Decrements when you provide a negative number value.

For details on the patch operation types, in particular on how OpenDJ handles single-valued fields versus multi-valued fields, see the draft documentation that’s currently in review.

The “field” value points to the field you aim to change. An important nuance here is that OpenDJ handles arrays as sets. So you cannot have duplicates, and it is not meaningful to reference a value in array by its index. For many operations with identity data, you probably want sets anyway. For example, here’s how you would add Babs Jensen’s entry to a group.

$ curl
 --user kvaughan:bribery
 --request PATCH
 --header "Content-Type: application/json"
 --data '[
  {
    "operation": "add",
    "field": "/members",
    "value": [
      {
        "_id": "bjensen"
      }
    ]
  }
 ]'

http://opendj.example.com:8080/groups/Directory%20Administrators

 ?_prettyPrint=true
{
  "_rev" : "00000000b70c881a",
  "schemas" : [ "urn:scim:schemas:core:1.0" ],
  "_id" : "Directory Administrators",
  "displayName" : "Directory Administrators",
  "meta" : {
    "lastModified" : "2013-05-13T16:40:23Z"
  },
  "members" : [ {
    "_id" : "kvaughan",
    "displayName" : "Kirsten Vaughan"
  }, {
    "_id" : "rdaugherty",
    "displayName" : "Robert Daugherty"
  }, {
    "_id" : "bjensen",
    "displayName" : "Barbara Jensen"
  }, {
    "_id" : "hmiller",
    "displayName" : "Harry Miller"
  } ]
}

With the patch operation, you can also use resource revision numbers to make sure that you only patch the resource if it still is the version that you expect.

$ curl
 --user kvaughan:bribery
 "http://opendj.example.com:8080/users/bjensen?_prettyPrint=true&_fields=_rev"
{
  "_rev" : "00000000c1b6d4c7"
}
$ curl
 --user kvaughan:bribery
 --request PATCH
 --header "If-Match: 00000000c1b6d4c7"
 --header "Content-Type: application/json"
 --data '[
  {
    "operation": "add",
    "field": "/contactInformation/emailAddress",
    "value": "babs@example.com"
  }
 ]'

http://opendj.example.com:8080/users/bjensen?_prettyPrint=true

{
  "_rev" : "00000000f946d377",
  "schemas" : [ "urn:scim:schemas:core:1.0" ],
  "contactInformation" : {
    "telephoneNumber" : "+1 408 555 1862",
    "emailAddress" : "babs@example.com"
  },
  "_id" : "bjensen",
  "name" : {
    "familyName" : "Jensen",
    "givenName" : "Barbara"
  },
  "userName" : "babs@example.com",
  "displayName" : "Barbara Jensen",
  "meta" : {
    "lastModified" : "2013-05-13T16:56:33Z"
  },
  "manager" : [ {
    "_id" : "trigden",
    "displayName" : "Torrey Rigden"
  } ]
}

HTTP Access Log

HTTP access to OpenDJ is now logged in logs/http-access, next to the other OpenDJ log files. The HTTP access log format is what you would expect to see in a web server.

localhost kvaughan [13/May/2013:18:54:34 +0200] "GET /users/bjensen/_prettyPrint=true&_fields=_rev HTTP/1.1" 200 "curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4 OpenSSL/0.9.8r zlib/1.2.5"
localhost kvaughan [13/May/2013:18:55:37 +0200] "PATCH /users/bjensen/_prettyPrint=true HTTP/1.1" 200 "curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4 OpenSSL/0.9.8r zlib/1.2.5"

Internal operations performed by the HTTP connection handler are logged to the LDAP access log, logs/access. However, these are hidden by default, because by default the suppress-internal-operations property on the (LDAP) file based access log publisher is set to true. Set it to false if you want to see those internal operations in the LDAP access log. (To see this advanced property when running the dsconfig command interactively, try /path/to/opendj/bin/dsconfig --advanced.)

Although this OpenDJ and the gateway now support each of the CRUDPAQ operations, there are still some improvements on the way, from additional actions (think password modify) to paged results and sorting for searches. I’m still holding off on documenting how to configure authentication, expecting that we will see a simplification of the configuration model.

More to come…

Leave a Comment

Filed under Directory Services and LDAP

OpenDJ: REST to LDAP, part 3

OpenDJ Community Logo Since my last post on this topic, there have been some important changes in RESTful access to OpenDJ.

Here’s a short list.

  • Jean-Noël added an HTTP connection handler to OpenDJ directory server.

    All you have to do is enable the HTTP connection handler, and you can start using the RESTful API without installing any other software.

  • Matt added authentication support to let you do:
    • HTTP Basic authentication (with different ways to map the user ID to an entry)
    • OpenIDM-style authentication (using headers, by default X-OpenIDM-Username and X-OpenIDM-Password)
    • Something else if you want to write your own Servlet Filter to handle authentication
  • Matt added support for deleting resources.
  • Matt renamed the REST API HTTP query request parameter _filter to _queryFilter (which is more consistent with _queryId and _queryExpression in OpenIDM).

HTTP Connection Handler

Enable the HTTP connection handler after installing OpenDJ.

$ dsconfig set-connection-handler-prop \
--hostname opendj.example.com --port 4444 \
--bindDN "cn=Directory Manager" --bindPassword password \
--handler-name "HTTP Connection Handler" \
--set enabled:true --no-prompt

Once you have enabled the HTTP connection handler, OpenDJ listens on port 8080 by default. The paths start at the root context. (As of this writing, April 5, 2013, you also need to authenticate for GET.)

$ curl --user bjensen:hifalutin \

http://opendj.example.com:8080/users/bjensen?_prettyPrint=true

{
  "schemas" : [ "urn:scim:schemas:core:1.0" ],
  "contactInformation" : {
    "telephoneNumber" : "+1 408 555 1862",
    "emailAddress" : "bjensen@example.com"
  },
  "_id" : "bjensen",
  "name" : {
    "familyName" : "Jensen",
    "givenName" : "Barbara"
  },
  "userName" : "bjensen@example.com",
  "displayName" : "Barbara Jensen",
  "manager" : [ {
    "_id" : "trigden",
    "displayName" : "Torrey Rigden"
  } ]
}

You configure the HTTP connection handler in the same way you configure the REST LDAP gateway, by using a JSON format configuration file. By default, the file is /path/to/OpenDJ/config/http-config.json.

Authentication Support

Matt implemented authentication support a couple of weeks ago. Right now the docs are out of sync with the trunk.  I am waiting on an enhancement, OPENDJ-827 (Simplify Rest2LDAP’s authentication configuration model), before updating the appendix on configuration.

In the meantime, if you want to start reconfiguring authentication now, read the comments the configuration file.

Deleting Resources

As of this writing, April 5, 2013, you can delete resources through the gateway, though not yet through the HTTP connection handler. That is likely to change soon.

By default, the configuration has "useSubtreeDelete" : true, so if you try to delete as a user without access rights to perform a tree delete, you can get an error because that control is not in the ACIs.

$ curl --request DELETE \
--user kvaughan:bribery \

http://opendj.example.com:8080/rest2ldap/users/bjensen?_prettyPrint=true

{
  "code" : 500,
  "reason" : "Internal Server Error",
  "message" : "Unavailable Critical Extension: The request control with Object Identifier (OID) \"1.2.840.113556.1.4.805\" cannot be used due to insufficient access rights"
}

If you set "useSubtreeDelete" : false in the configuration file, opendj-rest2ldap-servlet.json and reload the gateway, then you can use delete for individual resources.

$ curl --request DELETE \
--user kvaughan:bribery \

http://opendj.example.com:8080/rest2ldap/users/bjensen?_prettyPrint=true

{
  "_rev" : "000000007f413b85",
  "schemas" : [ "urn:scim:schemas:core:1.0" ],
  "contactInformation" : {
    "telephoneNumber" : "+1 408 555 1862",
    "emailAddress" : "bjensen@example.com"
  },
  "_id" : "bjensen",
  "name" : {
    "familyName" : "Jensen",
    "givenName" : "Barbara"
  },
  "userName" : "bjensen@example.com",
  "displayName" : "Barbara Jensen",
  "manager" : [ {
    "_id" : "trigden",
    "displayName" : "Torrey Rigden"
  } ]
}

As you can see, the delete returns the resource you removed.

You can also use the resource revision in an If-Match header to assert that the resource to delete is in fact the same version of the resource that you expect.

To try this, get the revision.

$ curl --user kvaughan:bribery \
"http://opendj.example.com:8080/rest2ldap/users/ajensen?_fields=_rev&_prettyPrint=true"
{
  "_rev" : "000000002222a818"
}

If you have the wrong revision for the current resource and use the assertion, the delete fails.

$ curl --request DELETE \
--header "If-Match: wrong-rev" \
--user kvaughan:bribery \

http://opendj.example.com:8080/rest2ldap/users/ajensen?_prettyPrint=true

{
  "code" : 412,
  "reason" : "Precondition Failed",
  "message" : "Assertion Failed: Entry uid=ajensen,ou=People,dc=example,dc=com cannot be removed because the request contained an LDAP assertion control and the associated filter did not match the contents of the entry"
}

If you have the right revision, the delete can complete successfully.

$ curl --request DELETE \
--header "If-Match: 000000002222a818" \
--user kvaughan:bribery \

http://opendj.example.com:8080/rest2ldap/users/ajensen?_prettyPrint=true

{
  "_rev" : "000000007eea3869",
  "schemas" : [ "urn:scim:schemas:core:1.0" ],
  "contactInformation" : {
    "telephoneNumber" : "+1 408 555 7892",
    "emailAddress" : "ajensen@example.com"
  },
  "_id" : "ajensen",
  "name" : {
    "familyName" : "Jensen",
    "givenName" : "Allison"
  },
  "userName" : "ajensen@example.com",
  "displayName" : "Allison Jensen",
  "manager" : [ {
    "_id" : "kwinters",
    "displayName" : "Kelly Winters"
  } ]
}

More to come…

1 Comment

Filed under Directory Services and LDAP

OpenDJ: REST to LDAP Gateway, part 2

OpenDJ Community LogoThe REST to LDAP gateway that you read about a few days ago is continuing to improve. If you look at the latest configuration, you will notice some changes:

  • DN reference mapping lets you map LDAP attributes like manager and uniqueMember that take DN values.
  • The "/users" mapping adds "manager" and "groups" fields, taking advantage of the reference mapping capability.
  • The default configuration now also includes a "/groups" mapping.
  • The "/users" and "/groups" mappings add "meta" fields to JSON resources. In the default configuration the "meta" field shows information about when the underlying entry was created and last modified.
  • ID and revision attributes in the default config are now "_id" and "_rev" as in OpenIDM.

The reference mapping prevents RESTful client applications from having to understand LDAP DNs. For example, if you look at Babs Jensen’s entry through LDAP, you notice that her manager is trigden.

$ ldapsearch -p 1389 -b dc=example,dc=com "(uid=bjensen)" cn manager
dn: uid=bjensen,ou=People,dc=example,dc=com
cn: Barbara Jensen
cn: Babs Jensen
manager: uid=trigden, ou=People, dc=example,dc=com

In the JSON resource for Babs Jensen, trigden is mapped to "_id", and the manager’s name is pulled out of the referenced entry, so you can now see who trigden is without doing another search.

$ curl 'http://opendj.example.com:8080/rest2ldap/users/bjensen?_fields=displayName,manager&_prettyPrint=true'
{
  "displayName" : "Barbara Jensen",
  "manager" : [ {
    "_id" : "trigden",
    "displayName" : "Torrey Rigden"
  } ]
}

If you look at Torrey Rigden’s entry through LDAP, you see the groups that Torrey is a member of are also referenced by DN.

$ ldapsearch -p 1389 -b dc=example,dc=com "(uid=trigden)" cn isMemberOf
dn: uid=trigden,ou=People,dc=example,dc=com
cn: Torrey Rigden
isMemberOf: cn=PD Managers,ou=groups,dc=example,dc=com

The REST to LDAP gateway uses the reference mapping for this as well.

$ curl 'http://opendj.example.com:8080/rest2ldap/users/trigden?_fields=displayName,groups&_prettyPrint=true'
{
  "displayName" : "Torrey Rigden",
  "groups" : [ {
    "_id" : "PD Managers"
  } ]
}

The "/groups" mapping gives you what you would expect, using the reference mapping for members.

$ curl 'http://opendj.example.com:8080/rest2ldap/groups?_filter=true&_fields=displayName,members&_prettyPrint=true'
{
  "result" : [ {
    "displayName" : "Accounting Managers",
    "members" : [ {
      "_id" : "scarter",
      "displayName" : "Sam Carter"
    }, {
      "_id" : "tmorris",
      "displayName" : "Ted Morris"
    } ]
  }, {
    "displayName" : "Directory Administrators",
    "members" : [ {
      "_id" : "kvaughan",
      "displayName" : "Kirsten Vaughan"
    }, {
      "_id" : "hmiller",
      "displayName" : "Harry Miller"
    }, {
      "_id" : "rdaugherty",
      "displayName" : "Robert Daugherty"
    } ]
  }, {
    "displayName" : "HR Managers",
    "members" : [ {
      "_id" : "kvaughan",
      "displayName" : "Kirsten Vaughan"
    }, {
      "_id" : "cschmith",
      "displayName" : "Chris Schmith"
    } ]
  }, {
    "displayName" : "PD Managers",
    "members" : [ {
      "_id" : "kwinters",
      "displayName" : "Kelly Winters"
    }, {
      "_id" : "trigden",
      "displayName" : "Torrey Rigden"
    } ]
  }, {
    "displayName" : "QA Managers",
    "members" : [ {
      "_id" : "abergin",
      "displayName" : "Andy Bergin"
    }, {
      "_id" : "jwalker",
      "displayName" : "John Walker"
    } ]
  } ],
  "resultCount" : 5,
  "pagedResultsCookie" : null,
  "remainingPagedResults" : -1
}

Get the updated REST to LDAP gateway for yourself and look at opendj-rest2ldap-servlet.json to see how this works in the configuration. Updates to the doc for these changes are in review.

Still more to come…

1 Comment

Filed under Directory Services and LDAP

OpenDJ: REST to LDAP Gateway

OpenDJ Community LogoThe REST to LDAP mapping is a new feature for the next release of OpenDJ. Although it is still early and the features is not finished yet, you can already play with some of the new capabilities.

REST to LDAP exposes directory data over HTTP as JSON resources. This opens up directory data to applications that do not support LDAP.

The initial artifact for serving JSON resources is a REST to LDAP gateway, which is a Servlet. (The Servlet will be followed by a REST to LDAP connection handler within OpenDJ.) To give the gateway a try, run it with an OpenDJ directory server in back.

As of this writing, the gateway .war is not yet posted on the builds page. Try one of these options instead:

  • You can download a build of the .war from the ForgeRock Maven repository under opendj-rest2ldap-servlet/3.0.0-SNAPSHOT/.
  • You can get the code, and then build and run the gateway yourself.
    $ svn co https://svn.forgerock.org/opendj/trunk/opendj3
    $ cd opendj3/opendj-rest2ldap-servlet && mvn jetty:run

    By default, the gateway listens on localhost:8080, and connects to the directory server on localhost:1389 as cn=Directory Manager with password password. The gateway is also configured to work out of the box with sample data (entries under dc=example,dc=com, either those generated at setup time or loaded from Example.ldif).

With a default OpenDJ configuration, you probably only need to start the directory server. (Don’t have OpenDJ? Try the quick install.)

$ /path/to/OpenDJ/bin/start-ds

If the defaults do not work for your setup, know that the configuration file for the gateway is opendj3/opendj-rest2ldap-servlet/src/main/webapp/opendj-rest2ldap-servlet.json. If you downloaded and deployed the gateway .war, then find opendj-rest2ldap-servlet.json under the directory where you deployed the .war. Also see the links to the doc below.

Once the gateway and OpenDJ are configured and started, REST clients can access the gateway to get at directory data, as in the following example.

$ curl http://localhost:8080/users/bjensen?_prettyPrint=true
{
  "id" : "bjensen",
  "rev" : "000000002f43b789",
  "schemas" : [ "urn:scim:schemas:core:1.0" ],
  "contactInformation" : {
    "telephoneNumber" : "+1 408 555 1862",
    "emailAddress" : "bjensen@example.com"
  },
  "name" : {
    "familyName" : "Jensen",
    "givenName" : "Barbara"
  },
  "userName" : "bjensen@example.com",
  "displayName" : "Barbara Jensen"
}

At this early stage, the gateway supports three of the seven CRUDPAQ verbs: create, read, and query.

There is a bit of documentation for REST to LDAP. All of this is still in progress.

More to come…

3 Comments

Filed under Directory Services and LDAP

OpenDJ: Changing server certificates

The default validity period for OpenDJ self-signed certificates used to be 730 days. Those of you who generated keys & self-signed certificates a couple of years ago could have certificates that will expire soon.

There’s a new chapter in the OpenDJ Administration Guide that covers Changing Server Certificates, including not only replacing the keys for regular connection handlers, but also generating new keys & self-signed certs used to protect replication traffic.

You will find the Configuring Servers For Client Application Access chapter has been beefed up with more examples of manipulating certificates using the Java keytool command, including CA-signed certificates. Plus, the Performing LDAP Operations chapter now also demonstrates Authenticating Using a Certificate, showing the steps to have an application, for example, authenticate to OpenDJ without a user name and password.

Leave a Comment

Filed under Directory Services and LDAP, Docs

OpenAM: Start OpenDJ control panel on Mac OS X

Java 7 is the default on this Mac now, though Java 6 is still installed.

Each time I start OpenDJ Control Panel for embedded OpenDJ, I get the same NullPointerException. Then I search for this workaround:

OPENDS_JAVA_HOME=`/usr/libexec/java_home -v 1.6` ~/openam/opends/bin/control-panel

So I’m posting it here in the hope that I’ll find the workaround faster next time.

(The problem has been fixed in OpenDJ. It must have been fixed after OpenDJ 2.4.5.)

1 Comment

Filed under Access Management, Directory Services and LDAP

OpenDJ: Getting started with DSML

OpenDJ Community LogoBack when XML was overly popular, DSMLv2 became a standard (.xsd, .doc). Directory Services Markup Language basically lets you do LDAP over HTTP, wrapping messages in SOAP. I won’t advocate unnecessary multiplication of wrappers, but perhaps you do not always have a choice.

OpenDJ provides a DSML .war that you can grab from the download page. The DSML .war is a gateway, so you must have a directory server such as OpenDJ to which the DSML gateway connects when handling client requests. If you do not yet have a directory server, get OpenDJ from the download page, too, and install it in a few clicks. You can either generate sample data during install, or load Example.ldif. The examples below work with Example.ldif.

For the DSML Gateway, deploy the war in your web container, and then edit WEB-INF/web.xml as described in the OpenDJ Admin Guide. (At minimum, you want to make sure the LDAP port number is correct. If you want to be able to HTTP Basic Auth and have the user IDs mapped to entries in the directory, for example, set ldap.authzidtypeisid=true.) Restart to take your changes into account.

For the following examples, I have OpenDJ DSML gateway running in Tomcat on localhost:8080/dsml, and OpenDJ with the entries from Example.ldif on localhost:1389.

Searching the Directory

Here is what I want to do using ldapsearch.

$ /path/to/OpenDJ/bin/ldapsearch -p 1389 -b dc=example,dc=com \
 "(uid=bjensen)" description
dn: uid=bjensen,ou=People,dc=example,dc=com
description: Original description

Here it is in DSML, with the response pretty printed by hand to make it easier to read. Notice that this goes as a POST to http://localhost:8080/dsml/DSMLServlet.

$ cat /path/to/search-request.xml
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
 <soap-env:Body>
  <batchRequest xmlns="urn:oasis:names:tc:DSML:2:0:core" requestID="search">
   <searchRequest dn="dc=example,dc=com"
                  scope="wholeSubtree"
                  derefAliases="neverDerefAliases">
    <filter>
     <equalityMatch name="uid">
      <value>bjensen</value>
     </equalityMatch>
    </filter>
    <attributes>
     <attribute name="description" />
    </attributes>
   </searchRequest>
  </batchRequest>
 </soap-env:Body>
</soap-env:Envelope>

$ curl -X POST --data @/path/to/search-request.xml \
 -H "Content-Type: text/xml" \

http://localhost:8080/dsml/DSMLServlet

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
 <SOAP-ENV:Body>
  <batchResponse xmlns="urn:oasis:names:tc:DSML:2:0:core" requestID="search">
   <searchResponse>
    <searchResultEntry dn="uid=bjensen,ou=People,dc=example,dc=com">
     <attr name="description">
      <value>Original description</value>
     </attr>
    </searchResultEntry>
    <searchResultDone>
     <resultCode code="0"/>
    </searchResultDone>
   </searchResponse>
  </batchResponse>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Updating an Entry

Here is what I want to do using ldapmodify.

$ /path/to/OpenDJ/bin/ldapmodify -p 1389 \
 -D uid=bjensen,ou=people,dc=example,dc=com -w hifalutin
dn: uid=bjensen,ou=people,dc=example,dc=com
changetype: modify
replace: description
description: Going to change this with DSML

Processing MODIFY request for uid=bjensen,ou=people,dc=example,dc=com
MODIFY operation successful for DN uid=bjensen,ou=people,dc=example,dc=com

Here it is in DSML, again with the response pretty printed by hand.

$ cat /path/to/modify-request.xml

<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
 <soap-env:Body>
  <batchRequest xmlns="urn:oasis:names:tc:DSML:2:0:core" requestID="modify">
   <modifyRequest dn="uid=bjensen,ou=people,dc=example,dc=com">
    <modification name="description" operation="replace">
     <value>New description from DSML gateway</value>
    </modification>
   </modifyRequest>
  </batchRequest>
 </soap-env:Body>
</soap-env:Envelope>

$ curl -X POST --data @/path/to/modify-request.xml \
 -H "Content-Type: text/xml" -u bjensen:hifalutin \

http://localhost:8080/dsml/DSMLServlet

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
 <SOAP-ENV:Body>
  <batchResponse xmlns="urn:oasis:names:tc:DSML:2:0:core" requestID="modify">
   <modifyResponse>
    <resultCode code="0"/>
   </modifyResponse>
  </batchResponse>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Enjoy!

Leave a Comment

Filed under Directory Services and LDAP

OpenDJ: Finding configuration documentation

OpenDJ Community LogoThe Admin Guide comes right out and says it:

In addition to the dsconfig reference that covers subcommands, the Configuration Reference covers the properties you can set using the dsconfig command.

Easier written than fully understood.

OpenDJ has many configuration options, only a few of which are accessible through the OpenDJ control panel.* Most configuration procedures involve use of the dsconfig command.

The dsconfig command has many options. Starting the command interactively with OpenDJ 2.5.0-EXPRESS1 shows a menu that nearly scrolls off a 80×24 terminal:

    1)   Access Control Handler               21)  Log Publisher
    2)   Access Log Filtering Criteria        22)  Log Retention Policy
    3)   Account Status Notification Handler  23)  Log Rotation Policy
    4)   Administration Connector             24)  Matching Rule
    5)   Alert Handler                        25)  Monitor Provider
    6)   Attribute Syntax                     26)  Password Generator
    7)   Backend                              27)  Password Policy
    8)   Certificate Mapper                   28)  Password Storage Scheme
    9)   Connection Handler                   29)  Password Validator
    10)  Crypto Manager                       30)  Plugin
    11)  Debug Target                         31)  Plugin Root
    12)  Entry Cache                          32)  Replication Domain
    13)  Extended Operation Handler           33)  Replication Server
    14)  External Changelog Domain            34)  Root DN
    15)  Global Configuration                 35)  Root DSE Backend
    16)  Group Implementation                 36)  SASL Mechanism Handler
    17)  Identity Mapper                      37)  Synchronization Provider
    18)  Key Manager Provider                 38)  Trust Manager Provider
    19)  Local DB Index                       39)  Virtual Attribute
    20)  Local DB VLV Index                   40)  Work Queue

    q)   quit

Enter choice:

Suppose you arrive at this menu thinking, “I want to lock users out for 5 minutes if they get their password wrong 3 times in a row.” You scan the list of options. You quit and try `/path/to/OpenDJ/bin/dsconfig --help-all | grep -i lockout`, but come up empty. You ask a colleague who has no idea. You almost search for “opendj account lockout” and find it in the Admin Guide, but then you decide that you do not want to have to rely on finding something in the Admin Guide. Surely the Admin Guide will never cover everything you plan to do with OpenDJ. So you want to figure out how to use the reference documentation.

As the Admin Guide states, there are two parts** to the configuration reference documentation:

  • The dsconfig reference
    This covers dsconfig and all its many subcommands and options. Everything is also available through the dsconfig help built into the command, the advantage of the reference being that you can search through everything at once.
  • The OpenDJ configuration reference
    This covers all the individual configuration properties you can set with dsconfig, and also shows you how the configuration properties are attached to configuration objects, plus the configuration object inheritance. You need to know inheritance because dsconfig is arranged by kinds of objects. Some objects are abstract parents of the configuration objects you create.

You open the OpenDJ configuration reference to the default page, where the left frame shows Inheritance, and you search for “account”. This turns up account status notification handler configuration objects. You search for “lockout”. Nothing. You think, “Okay, where’s the alphabetical list of everything I can configure?” You find it under the Properties tab in the left frame, and you search again for “lockout”. Now you are getting somewhere:

lockout-duration [ Password Policy ]

lockout-failure-count [ Password Policy ]

lockout-failure-expiration-interval [ Password Policy ]

lockout-failure-count and lockout-duration look promising. Perhaps you can set lockout-failure-count to 3 and lockout-duration to 5m. There’s also a lockout-failure-expiration-interval that might be useful to avoid locking users out if consecutive failures happened over hours or days rather than all in a row. You notice that these properties are configured on Password Policy configuration objects.

You could click the links and read more, but instead you go back to the interactive dsconfig session, and you choose 27)  Password Policy. From there, the menu-driven interaction makes it relatively easy to discover and then change the settings.

And thus you are on your way to becoming a dsconfig guru. (After you get the hang of it, read about the options --advanced, and especially --commandFilePath, and --batchFilePath in the dsconfig command reference so that you can really do everything including generate scripts from your interactive sessions that you can use again later for tasks you repeat.)


* It’s not quite strictly true that you cannot configure more of OpenDJ through the control panel. If you Manage Entries > Base DN > cn=config, you can hack the config. Realize that you are accessing a private interface in that case, however. What you are doing is similar to editing OpenDJ/config/config.ldif directly. Mistakes can break your server.

** Someday, there might be one part. See OPENDJ-386.

Leave a Comment

Filed under Directory Services and LDAP, Docs

Searching ForgeRock Community Sites

ForgeRock Community Logo Someone said it is hard to find the search box on the *.forgerock.org community sites. Also, the searches were scoped too narrowly to look in the mailing lists.

Before the changes the search box is tucked away in the left menu, and scoped to site:<project>.forgerock.org.

OpenDJ site before the change

OpenDJ Before: Search box in left menu

The new, improved version has a more obvious search box. Searches now cover everything at site:forgerock.org.

OpenAM after improving the search box

OpenAM After: Search box top right, now with colors

Leave a Comment

Filed under Access Management, Directory Services and LDAP, Identity Management, Tools

OpenAM: Connecting to OpenDJ over SSL

OpenAM Community Logo You can easily connect OpenAM to an external OpenDJ directory server. The key to connecting securely from OpenAM to OpenDJ using LDAP over SSL (LDAPS) is making sure the OpenDJ certificate is recognized on the OpenAM side.

OpenDJ Community LogoWhen you install OpenDJ, you can choose to enable LDAP secure access. By default OpenDJ generates a self-signed certificate used that to protect communications. The big advantage is that you do not need to get a certificate signed by a certificate authority just to try LDAP secure access. The big disadvantage is that no other applications recognize the self-signed certificate as a valid certificate because no recognized certificate authority has signed it. In order for the self-signed certificate to be recognized on the OpenAM side, you must take some additional steps.

(Dave Koelmeyer already wrote up how to do this with GlassFish when he explained how to enable secure LDAP container based authentication with JSPWiki. Let me reiterate here in the context of OpenAM running in Apache Tomcat.)

Export the OpenDJ self-signed certificate with alias server-cert to a file.

$ cd /path/to/OpenDJ/config
$ keytool -export -alias "server-cert" \
 -keystore keystore -storepass `cat keystore.pin` \
 -file /tmp/server-cert.cer
Certificate stored in file </tmp/server-cert.cer>

Import the OpenDJ self-signed certificate into the trust store used by the container where OpenAM runs. In the case of Apache Tomcat, for example, you can create a trust store and update the JAVA_OPTS for Tomcat to tell it to use the trust store.

Set up the trust store by importing the OpenDJ self-signed certificate.

$ cd /path/to/tomcat/conf
$ keytool -import -v -trustcacerts -alias "server-cert" \
 -keystore truststore -keypass changeit \
 -file /tmp/server-cert.cer
Enter keystore password: 
Re-enter new password:
Owner: CN=laptop.example.com, O=OpenDJ Self-Signed Certificate
Issuer: CN=laptop.example.com, O=OpenDJ Self-Signed Certificate
Serial number: 5023849b
Valid from: Thu Aug 09 11:36:27 CEST 2012 until: Sat Aug 09 11:36:27 CEST 2014
Certificate fingerprints:
      MD5:  00:A4:AA:86:2F:59:96:95:71:6B:43:C4:8D:72:8A:B8
      SHA1: D1:F5:D9:D6:0F:FB:61:2D:32:F5:0C:40:0C:D6:BC:4F:12:6A:16:D6
      Signature algorithm name: SHA1withRSA
      Version: 3
Trust this certificate? [no]:  yes
Certificate was added to keystore
[Storing truststore]

Edit the Tomcat environment to make Tomcat use the trust store. The JAVA_OPTS value should all be on one line in your version.

$ cd /path/to/tomcat/bin
$ vi catalina.sh
$ grep ^JAVA_OPTS catalina.sh
JAVA_OPTS="-Xmx1024m -XX:MaxPermSize=256m
 -Djavax.net.ssl.trustStore=/path/to/tomcat/conf/truststore
 -Djavax.net.ssl.trustStorePassword=changeit"

When you are ready to deploy into production, you might want to avoid the hassle by using CA-signed certificates. The method shown here is cheaper and easier when you’re only using a couple of servers on your laptop or in your lab, and you might be throwing everything away and starting over often.

Leave a Comment

Filed under Access Management, Directory Services and LDAP