We (temporarily ?) have a pretty nice graph of our bug trend, on the issue tracker page of the OpenDJ project.
Kudos to Matt and Mark who’ve been really focusing on preparing two major areas of the project : the LDAP client SDK and the Core documentation for the whole project.
Month: May 2011
OpenDJ: Enabling the External Change Log on a single server
Yesterday, I described how easy it is to enable Multi-Master Replication between 2 instances of OpenDJ. One of the nice thing with OpenDJ replication, is that all changes are also publicly available (subject to access control) through LDAP under the cn=changelog suffix, also nick-named the External Change Log.
But the command to enable replication and thus the External Change Log requires 2 servers. So what if you want to enable the External Change Log on a single server ?
Note that this is not a fully supported procedure, but is handy for unit testing against the External Change Log. In production environment, you will have multiple servers for high availability and thus the External Change Log will be automatically configured.
Well you cannot use the dsreplication command, but you can configure the OpenDJ instance with the dsconfig utility.
$ bin/dsconfig create-replication-server -h ldap1.example.com -p 4444 \ -D "cn=directory manager" -w secret12 -X -n \ --provider-name "Multimaster Synchronization" --set replication-port:8989 \ --set replication-server-id:2 --type generic $ bin/dsconfig create-replication-domain -h ldap1.example.com -p 4444 \ -D "cn=directory manager" -w secret12 -X -n \ --provider-name "Multimaster Synchronization" --set base-dn:dc=example,dc=com \ --set replication-server:ldap1.example.com:8989 --set server-id:3 \ --type generic --domain-name example_com
If you want to be able to join this server in a replication topology, you should also create the global administrator’s entry. If you do so, then you will be able to use the dsreplication enable command as illustrated here.
$ bin/dsframework create-admin-user -X -h ldap1.example.com -p 4444 \ -D "cn=Directory Manager" -w secret12 --userID admin --set password:password
Once enabled, you can read or search the changes with ldapsearch or other LDAP clients :
$ bin/ldapsearch -D cn=directory\ manager -w secret12 -h ldap1.example.com -p 1389 \ -J "1.3.6.1.4.1.26027.1.5.4:false:;" -b "cn=changelog" '(objectclass=*)' dn: cn=changelog cn: changelog objectClass: top objectClass: container # Public changelog exchange control(1.3.6.1.4.1.26027.1.5.4): dc=example,dc=com:0000012fd9bdf863000300000001; dn: replicationCSN=0000012fd9bdf863000300000001,dc=example,dc=com,cn=changelog targetDN: cn=a,ou=people,dc=example,dc=com changeNumber: 0 changes:: b2JqZWN0Q2xhc3M6IHBlcnNvbgpvYmplY3RDbGFzczogdG9wCmNuOiBhCnNuOiBhCmVudH J5VVVJRDogNWQzMTNlY2UtYjY4Mi00MDFiLTg2NmYtM2NiZWNlMWNjNTJjCmNyZWF0ZVRpbWVzdGFtc DogMjAxMTA1MTAxMTQ5NTZaCmNyZWF0b3JzTmFtZTogY249RGlyZWN0b3J5IE1hbmFnZXIsY249Um9v dCBETnMsY249Y29uZmlnCg== changeType: add changeTime: 20110510114956Z objectClass: top objectClass: changeLogEntry # Public changelog exchange control(1.3.6.1.4.1.26027.1.5.4): dc=example,dc=com:0000012fd9be46af000300000002; dn: replicationCSN=0000012fd9be46af000300000002,dc=example,dc=com,cn=changelog targetDN: cn=a,ou=people,dc=example,dc=com changeNumber: 0 changes:: YWRkOiBkZXNjcmlwdGlvbgpkZXNjcmlwdGlvbjogTmV3IG9uZQotCnJlcGxhY2U6IG1vZG lmaWVyc05hbWUKbW9kaWZpZXJzTmFtZTogY249RGlyZWN0b3J5IE1hbmFnZXIsY249Um9vdCBETnMsY 249Y29uZmlnCi0KcmVwbGFjZTogbW9kaWZ5VGltZXN0YW1wCm1vZGlmeVRpbWVzdGFtcDogMjAxMTA1 MTAxMTUwMTZaCi0K changeType: modify changeTime: 20110510115016Z objectClass: top objectClass: changeLogEntry
Note: the search above uses the “Cookie Control” which is the optimized way to search the External Change Log. The value “;” means that the “cookie” is unknown, and therefore the search starts from the first change. If you want to continue from the last change received, provide the string value that is either in the ChangeLogCookie operational attribute (returned if asked for) or the comment before the change itself.
OpenDJ: Quick Replication setup
As we develop OpenDJ, we spend a lot of time testing, whether it’s a new feature or a correction to an existing one. We usually write some unit tests to validate the code and then some functional tests to check the feature from a “user” point of view. While the unit tests are typically run with a single server, the functional or integration tests are run with configurations that match our customers deployment. And one of the given fact for any directory service deployment with OpenDJ that I’m aware of, is that the service is made of two or more OpenDJ directory servers with Multi-Master Replication enabled between them.
Setting up Multi-Master Replication with OpenDJ is quite easy and I’m going to demonstrate it here:
Lets assume we want to install 2 OpenDJ servers on the following hosts : ldap1.example.com and ldap2.example.com. For simplicity and because for test we avoid running tests with root privileges, we will configure the server to use port 1389 and 1636 for LDAP and LDAPS respectively.
On ldap1.example.com
$ unzip OpenDJ-2.4.2.zip $ cd OpenDJ-2.4.2 $ ./setup -i -n -b "dc=example,dc=com" -d 20 -h ldap1.example.com -p 1389 \ --adminConnectorPort 4444 -D "cn=Directory Manager" -w "secret12" -q -Z 1636 \ --generateSelfSignedCertificate
Do the same on ldap2.example.com, the parameters being the same except for the -h option that should be ldap2.example.com
Now, you have 2 instances of OpenDJ configured and running with 20 sample entries in the suffix “dc=example,dc=com”. Let’s enable replication:
$ bin/dsreplication enable --host1 ldap1.example.com --port1 4444\ --bindDN1 "cn=directory manager" \ --bindPassword1 secret12 --replicationPort1 8989 \ --host2 ldap2.example.com --port2 4444 --bindDN2 "cn=directory manager" \ --bindPassword2 secret12 --replicationPort2 8989 \ --adminUID admin --adminPassword password --baseDN "dc=example,dc=com" -X -n
And now make sure they both have the same data:
$ bin/dsreplication initialize --baseDN "dc=example,dc=com" \ --adminUID admin --adminPassword password \ --hostSource ldap1.example.com --portSource 4444 \ --hostDestination ldap2.example.com --portDestination 4444 -X -n
For my daily tests I’ve put the commands in a script that I can run and will deploy 2 servers, enable replication between them and initialize them, all on a single machine (using different ports for LDAP and LDAPS).
Now if you want to add a 3rd server in the replication topology, install and configure it like the first 2 ones. And join it to the replication topology by repeating the last 2 commands above, replacing ldap2.example.com with the hostname of the 3rd server. Need a 4th one ? Repeat again, keeping ldap1.example.com as the server of reference.
More OpenDJ Tips…
I’ve already mentioned that Mark Craig has joined ForgeRock and started to blog about OpenDJ.
Here’s a few tips he’s recently posted about OpenDJ :
- Start OpenDJ at boot time on Linux
- JSPWiki/Tomcat using LDAP auth
- LDAP Account Manager and OpenDJ
- XWiki LDAP authentication with OpenDJ
- …
I’m sure there are more to come.
If you’re not following Mark’s blog feed yet, you should !
LDAP Advanced Administration for Enterprises…
OpenDJ directory server has one default administrator that can manage all aspects of the server.
In an earlier post, I’ve described how to create multiple administrative accounts in OpenDJ, and in another one, I’ve talked about the Privilege system and how it can be used to tailor the administrative roles of each account.
In most enterprises, administrators are usually employees and therefore have their own entries and password. For auditing purpose, security processes require that a change or an administrative task on the directory be done as the true person and not the administrative account. But often there are multiple administrators, and they can change role frequently. So what is the best practice for granting employees some administrative privileges ?
An efficient and manageable way is to create an Administrators’ group and grant the privileges to all members of that group. When an employee, is no longer administrator, simply remove him from the group and he will loose all privileges associated. Likewise, adding a new administrator is just adding a member in the group.
With OpenDJ, this can be done with 2 simple entries : a group and a privilege collective attribute subentry.
The Group :
dn: cn=Administrators,ou=Groups,dc=example,dc=com objectClass: groupOfNames objectClass: top description: LDAP Administrators Group cn: Administrators member: uid=ludo,ou=People,dc=example,dc=com member: uid=Matt,ou=people,dc=example,dc=com
The Collective Attribute Subentry :
dn: cn=Administrators Privilege,dc=example,dc=com objectClass: extensibleObject objectClass: collectiveAttributeSubentry objectClass: top objectClass: subentry cn: Administrators Privilege ds-privilege-name;collective: config-read ds-privilege-name;collective: config-write ds-privilege-name;collective: ldif-export ds-privilege-name;collective: modify-acl ds-privilege-name;collective: password-reset ds-privilege-name;collective: proxied-auth subtreeSpecification: {base "ou=people", specificationFilter "(isMemberOf=cn=Administrators,ou=groups,dc=example,dc=com)" }
How does it work ?
Collective Attributes is a standard based LDAP functionality that allows to define attributes and value that are defined once and appear in all entries that match the subtreeSpecification. Collective Attributes are defined in RFC 3671. For those who are familiar with Sun Directory Server’s Class Of Service, Collective Attributes provide a similar function, but based on industry approved standard.
OpenDJ collective attributes feature supports a few extensions to facilitate their use.
First, the standard way to define a collective attribute is to define it in the schema with a “c–” prefix. With OpenDJ, any existing attribute can be defined as collective with the ;collective attribute option.
Second, the scope of a Collective Attribute subentry as defined by the standard is a subtree, but the only filter possible is to specify the object class it applies to. We’ve extended the specificationFilter to accept an arbitrary LDAP filter, allowing a finer grained control of which entries are targeted.
In the example above, the filter is used to restrict the Privilege Collective Attribute subentry to apply only to entries that have the isMemberOf attribute with the value “cn=Administrators,ou=Groups,dc=example,dc=com”.
IsMemberOf is an operational read-only attribute (virtual) that is a back-link to the groups a user belongs to. OpenDJ does support the isMemberOf attribute for static groups, nested static groups and dynamic groups.
The subtreeSpecification also contains a base “ou=people” to restrict the targeted entries to the ou=people subtree. There are additional field allowed in the subtreeSpecification to indicate a depth in the tree for example.
As a result, collective attribute subentries, combined with groups, provide a flexible way to “inject” attributes and values to a specified set of entries, either to grant them specific privileges like in our example, or to decorate entries based on some common properties.
This said, remember that privileges are set in addition to the Access Controls. So giving a user the password-reset privilege for example, will be useless if there is no ACI allowing him or her to modify the userPassword attribute of other users. Granting access through an ACI to a group is as simple as using groupdn=”ldap:///cn=Administrators,dc=example,dc=com”; to designate the authorized identities.