Last updated by ldaley 2 years ago
How do I create an LDAP server?
LDAP servers are controlled by the application config. Each entry under the key
ldapServers is an LDAP server.
Example...
File: grails-app/conf/Config.groovy
ldapServers {
d1 {
base = "dc=d1,dc=my,dc=org"
port = 10400
indexed = ["objectClass", "uid", "mail"]
}
d2 {} // use defaults
}This will embed
2 LDAP directories in your grails application.
The possible config parameters are:
| Name | Type | Description | Default | |
|---|
| base | String | The base component of your directory | "dc=grails,dc=org" | |
| port | Integer | The port to bind the LDAP server to | 10389 | |
| indexed | String[] | The attributes in the directory that should be indexed | ["objectClass", "uid", "ou"] | |
How do I add some static data to my directory?
As the directory is starting up, it looks for any
*.ldif files in
grails-app/ldap-servers/«name»/data and loads them in alphabetical order. Note that «name» is the name of the directory in the config, not the bean name.
How do I customise the schema of my directory?
To do this you need to know a little bit about how ApacheDS manages schema. I strongly recommend reading
this article to get some background on this. In short, ApacheDS stores the schema in the directory itself in
ou=schema in a certain structure.
Apache Directory Studio can export a schema in LDIF suitable for importing into an instance of ApacheDS.
To import this schema into your directory, place it in
grails-app/ldap-servers/«name»/schema . Each LDIF file in that directory will be loaded in alphabetical order when the directory is starting up and before any data is loaded. Note that «name» is the name of the directory in the config, not the bean name.
How do I access the server over LDAP?
You can connect to the LDAP server over the port specified in the config and with the following credentials:
userDn = "uid=admin,ou=system"
password = "secret"
How do I access the server bean at runtime?
Each server instance is available as a bean in the application context as «name»LdapServer, where «name» is the name of the directory in the config.
Example...
class MyIntegrationTest extends GroovyTestCase {
def d1LdapServer
}Server beans are instances of
grails.ldap.server.TransientGrailsLdapServer .
How do I load test data fixtures?
Server beans expose methods to load LDIF files from
grails-app/ldap-servers/«name»/fixtures as templates to be inserted into the directory.
Example...
File:grails-app/ldap-servers/d1/fixtures/personTemplate.ldif
dn: cn=${cn},dc=d1,dc=my,dc=org
cn: ${cn}
sn: ${sn}
objectClass: person
objectClass: top
objectClass: organizationalPersonThen to load the fixture...
d1LdapServer.loadFixture("personTemplate", cn: "test", sn: "person")Fixtures don't have to be templates, the following would have the same affect...
File:grails-app/ldap-servers/d1/fixtures/person.ldif
dn: cn=test,dc=d1,dc=my,dc=org
cn: test
sn: person
objectClass: person
objectClass: top
objectClass: organizationalPerson
Then to load the fixture...
d1LdapServer.loadFixture("person")There is also a
loadFixtures() variant that can load multiple fixtures at once (with out without templating)...
d1LdapServer.loadFixtures("ou", "person")The templating is achieved by using Groovy's
SimpleTemplateEngine . See
this article for more details.
How do I load arbitrary LDIF?
Server beans expose a
loadLdif(ldif) method that will add the specified LDIF to the directory.
If the argument is a…
- File object and is not a directory; it's content is consumed as LDIF.
- File object and is a directory; all files matching
*.ldif in that directory will be consumed.
- Anything else, the
String representation of that object will be consumed as LDIF.
How do I see if an entry exists in the directory?
Server beans expose a
exists(String dn) method that will return
true if an entry does exist at
dn .
Example...
assert d1LdapServer.exists("cn=test,dc=d1,dc=my,dc=org")How do I retrieve an entry from the directory?
Server beans implement
getAt(String dn) which returns a
Map of the entry at
dn 's values if it exists, or
null if it does not.
If the attribute is multi valued by definition (i.e. it's actual attribute definition in the schema), it's values will be in a
List . Be careful here because many common attributes that you might think aren't multi valued actually are (e.g 'cn', 'sn').
If the attribute value is binary, it will be a
byte[]@, otherwise it will be a @String .
Example...
def user = d1LdapServer["cn=user,dc=d1,dc=my,dc=org"]
assert "user" == entry.cn.first() // cn is a multi valued string attribute
assert entry.usercertificate.first() instanceof byte[] // usercertificate is a multi valued binary attributedef country = d1LdapServer["c=au,dc=d1,dc=my,dc=org"]
assert "au" == entry.countryName // countryName is a single valued string attribute
How do I revert the directory state?
Server beans expose a
clean() method which undoes any changes made to the directory
since it was loaded . This means that all custom schema and static data will still be there.
d1LdapServer.loadLdif("""
dn: cn=test,dc=d1,dc=my,dc=org
cn: test
sn: person
objectClass: person
objectClass: top
objectClass: organizationalPerson
""")assert d1LdapServer.exists("cn=test,dc=d1,dc=my,dc=org")) == trued1LdapServer.clean() // Removing anything added after startupassert d1LdapServer.exists("cn=test,dc=d1,dc=my,dc=org")) == falseHow do I stop/start the server?
You shouldn't need to do this, but if you do there are the following three methods on your server beans...
Starting a server includes reloading all custom schema and static data.