openldap configuration

openldap configuration

Blog

Linux, SysAdmin, Ldap, Tech

by maria on 08 Mar 2013 - 01:27  

It use to be you edited slapd.conf to change configurations, but now openldap has its configuration in the database itself. Which means you can change the configuration without having to restart ldap. Or you can totally screw it up while its running. Cool. At any rate, the guides all helpfully say, now you change your configs just like you change anything else in your database by ldapmodify. Great. But, wait, how do I do that exactly? Well, first you need to know the cn, which isn't going to be the same as the changes you usually make. Fortunately, it is easy, cn=config. For an example, what if you want to check what schemas are loaded?

ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b cn=schema,cn=config dn

The -L option used here causes the results to be displayed in LDAP Data Interchange Format (LDIF). A second -L will disable comments, and a third one will prevent the LDIF version from being printed. The default is to use extended LDIF. The -Q will enable SASL Quiet mode. Never prompt. The -Y will specify we want the EXTERNAL (usually TSL) authentication mechanism. If you want to see the entire structure of the schemas, omit the dn from the end.

To get a nice overview of the configurations:

ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b cn=config "(|(cn=config)(olcDatabase={1}hdb))"

When I first started using the new configuration scheme, I could not authenticate to make any configuration changes, even though I could still make changes to our database. Something happened when I converted from ldapd.conf to the new configuration, so that I got this error message when trying to authenticate:

LDAP "Invalid credentials (49)" for cn=config (10.04 svr)

The problem is that normally I use cn=admin for making database changes, but to make configuration changes you have to use the olcRootDN, cn=admin,cn=config.

If you search by authenticating as config, you can tell if you will have this problem:

ldapsearch -xLLL -b cn=config -D cn=admin,cn=config -W olcDatabase={1}hdb

To fix this I re-created the olcRootDN and password. First get the encrypted version of your password by running this command:

slappasswd -h {MD5}

Type your password twice and copy the result in to a file with the following contents (I used emacs config.ldif):

dn: cn=config
changetype: modify

dn: olcDatabase={0}config,cn=config
changetype: modify
add: olcRootDN
olcRootDN: cn=admin,cn=config

dn: olcDatabase={0}config,cn=config
changetype: modify
add: olcRootPW
olcRootPW: {MD5}your password here

dn: olcDatabase={0}config,cn=config
changetype: modify
delete: olcAccess

Include the {MD5} part before the actual password. The delete: olcAccess is so that users other than root can have administrative access. Now load the config file:

ldapadd -Y EXTERNAL -H ldapi:/// -f config.ldif

One thing I wanted to do was change what was being indexing, so I created a file index.ldif

dn: olcDatabase={1}hdb,cn=config
changetype: modify
add: olcDbIndex
olcDbIndex: uid eq
-
add: olcDbIndex
olcDbIndex: cn eq
-
add: olcDbIndex
olcDbIndex: uidNumber eq

and loaded that:

ldapmodify -QY EXTERNAL -H ldapi:/// -f index.ldif

I decided what to index on by looking at the log files to see what was being searched on, but wasn't indexed.

There was something else strange that happened when I upgraded, the shadowLastChange attribute was missing from all of the people. So, I tried adding it back using this in my change.ldif file:

dn: uid=jd,ou=people,dc=example,dc=com
changetype: modify
replace: shadowLastChange
shadowLastChange: 15771

I got the following message:

add shadowLastChange:
        15771
modifying entry "uid=jd,ou=people,dc=example,dc=com"
ldap_modify: Constraint violation (19)
        additional info: attribute 'shadowLastChange' cannot have multiple values

That's strange. So, maybe it thinks it already has that attribute. let's see what happens if we try to modify it instead of add it:

replace shadowLastChange:
        15771
modifying entry "uid=jd,ou=people,dc=example,dc=com"
modify complete

Huh, well that seemed to have worked. Let's see what the value is now.

annette:~# ldapsearch -x "uid=jd" shadowLastChange
# extended LDIF
#
# LDAPv3
# base <dc=example,dc=com> (default) with scope subtree
# filter: uid=jd
# requesting: shadowLastChange 
#

# jd, people, example.com
dn: uid=jd,ou=people,dc=example,dc=com

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

Um, so where is it? Interestingly, if I do stop ldap and do a slapcat, it shows up in the ldif file. So, it is there, I just can't see it using ldapsearch. Let's check permissions:

ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b cn=config "(|(cn=config)(olcDatabase={1}hdb))"

...
olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn=
 "cn=admin,dc=example,dc=com" write by * none
olcAccess: {1}to dn.base="" by * read
olcAccess: {2}to * by self write by dn="cn=admin,dc=example,dc=com" write by * read
...

So, for userPassword and shadowLastChange the last permission is by * none, which effectively means that no one can read it. That is what we want for userPassword, but not what we want for shadowLastChange. Hmmm. So, now we learn how to change permissions. Probably it is easiest to just make separate entries for userPassword and shadowLastChange. So, I created this file:

dn: olcDatabase={1}hdb,cn=config
changetype: modify
delete: olcAccess
olcAccess: {0}
-
add: olcAccess
olcAccess: {0}to attrs=shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=example,dc=com" write by * read
-
delete: olcAccess
olcAccess: {1}
-
add: olcAccess
olcAccess: {1}to attrs=userPassword by self write by anonymous auth by dn="cn=admin,dc=example,dc=com" write by * none
-
delete: olcAccess
olcAccess: {2}
-
add: olcAccess
olcAccess: {2}to dn.base="" by * read
-
add: olcAccess
olcAccess: {3}to * by self write by dn="cn=admin,dc=example,dc=com" write by * read

Order is important, which is why I rewrote all of the olcAccess attributes. Also syntax is important. Make sure you are using the correct dn, have the changetype, etc. Now implement your changes:

ldapmodify -QY EXTERNAL -H ldapi:/// -D cn=admin,cn=config -f change.config

And that should do it. But, no, now even though I have these permissions:

olcAccess: {0}to attrs=shadowLastChange by self write by anonymous auth by dn=
 "cn=admin,dc=example,dc=com" write by * read
olcAccess: {1}to attrs=userPassword by self write by anonymous auth by dn="cn=
 admin,dc=example,dc=com" write by * none
olcAccess: {2}to dn.base="" by * read
olcAccess: {3}to * by self write by dn="cn=admin,dc=example,dc=com" write by * read

I still can't read the shadowLastChange.

Aha! And now another lesson in openldap permissions. Order is important. I have stated in my permission for shadowLastChange 'by anonymous auth', so if I try to look at shadowLastChange anonymously, we come to this directive and stop, cause it looks like we don't have permission to read. Doesn't matter that later on, we say that anyone can read. So, be careful when you are adding a new directive that you put it in the correct place, and that there isn't a directive there already that contradicts it. In this case, the way I added the new rule 'by read *', I was effectively saying, everyone but anonymous has read permission. If we move the directive 'by read *' earlier, we give anonymous read permission by giving everyone read permission, and it makes no sense to then say they have auth permission, which is more restricted access. So, we drop that directive altogether. Here is my new configuration:

olcAccess: {0}to attrs=shadowLastChange by self write by dn="cn=admin,dc=example,dc=com" write by * read
olcAccess: {1}to attrs=userPassword by self write by dn="cn=admin,dc=example,dc=com" write by anonymous auth by * none
olcAccess: {2}to dn.base="" by * read
olcAccess: {3}to * by self write by dn="cn=admin,dc=example,dc=com" write by * read

And, seems like a good idea to post the who and the what:

SpecifierEntities
*All, including anonymous and authenticated users
anonymousAnonymous (non-authenticated) users
usersAuthenticated users
selfUser associated with target entry
dn[.<basic-style>]=<regex>Users matching a regular expression
dn.<scope-style>=<DN>Users within scope of a DN

Access Levels:

LevelPrivilegesDescription
none=0no access
disclose=dneeded for information disclosure on error
auth=dxneeded to authenticate (bind)
compare=cdxneeded to compare
search=scdxneeded to apply search filters
read=rscdxneeded to read search results
write=wrscdxneeded to modify/rename
manage=mwrscdxneeded to manage

Of course, all of this information and more is in the docs

openldap configuration ~ Comments: 0

Add Comment



  LinkedIn