Ubuntu 12.04 Ultimate Server Guide

Part 3: OpenLDAP

OpenLDAP is a directory service. Think of it as a database for storing all your users, their groups and other information. In time you can use it to store much more, but initially we’re going to use it as a centralised authorisation system. Clients will check usernames and permissions against those stored in the directory on the server. Though it is also possible to store passwords in LDAP and use it for authentication, we’ll be using Kerberos for this purpose.

The first step is to install OpenLDAP along with some utilities for administering it. This process will use your hostname to configure your LDAP domain, therefore it is very important that you have set this correctly BEFORE continuing, else you will get error(49) invalid bind credentials at the next step. In this example the domain is danbishop.org and the server is called neo, so make sure /etc/hosts contains a line like so: “127.0.1.1 neo.danbishop.org neo” if this is not the case, make this change then REBOOT. Now install OpenLDAP:

sudo apt-get install slapd ldap-utils

You will be prompted for an LDAP admin password, once you have set this, much of the manual configuration that had to be done in previous releases is handled automatically in 11.04 and above. Ubuntu will configure LDAP using the domain information we supplied in previous steps in this guide. If you do wish to make changes to this though, you can run “sudo dpkg-reconfigure slapd”. All that remains to be done is creating a place in the OpenLDAP directory to store our users and our groups.

This is done by creating a frontend.danbishop.org.ldif file like so:

dn: ou=Users,dc=danbishop,dc=org
objectClass: organizationalUnit
ou: Users

dn: ou=Groups,dc=danbishop,dc=org
objectClass: organizationalUnit
ou: Groups

Please note: it is important that you have a new line between “ou:Users” and “dn: ou=Groups,dc=danbishop,dc=org” if you’re copying and pasting the above, it will have a space at the beginning of the blank line, you must remove this!

Now we add the LDIF in the following way, entering your root LDAP password when prompted (the one you set during slapd installation):

sudo ldapadd -x -D cn=admin,dc=danbishop,dc=org -W -f frontend.danbishop.org.ldif

LDAP Indices

Although the above will work just fine, LDAP will complain every time a user is looked up in the database that you haven’t indexed the UIDs. Indexing allows LDAP to perform searches faster than it otherwise would. Though this increase in performance is negligible with only a few users, large scale deployments will see noticeable benefits. For the purpose of preparing for possible future expansion… and to keep our log clean, we’re going to create some indices.

Create an index.ldif file:

nano index.ldif

And insert the following:

dn: olcDatabase={1}hdb,cn=config
changetype: modify
add: olcDbIndex
olcDbIndex: uidNumber eq
olcDbIndex: gidNumber eq
olcDbIndex: loginShell eq
olcDbIndex: uid eq,pres,sub
olcDbIndex: memberUid eq,pres,sub
olcDbIndex: uniqueMember eq,pres

Now we’re going to run the modification like so:

sudo ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f index.ldif

AutoFS LDAP

Whilst we’re setting up LDAP, this would be a good time to create the necessary LDAP entries for AutoFS. This will handle the mounting of home directories on clients later on.

It isn’t necessary to use LDAP for AutoFS… you can simply specify the same settings on every client… the only problem with this is that if you decide to change something in the future, you have to manually change it on every client. LDAP provides a centralised way of doing this.

The first thing to do is tell LDAP what AutoFS is by defining a schema:

Create a file called autofs.ldif and enter the following data into it:

nano autofs.ldif
dn: cn=autofs,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: autofs
olcAttributeTypes: {0}( 1.3.6.1.1.1.1.25 NAME 'automountInformation' DESC 'Inf
 ormation used by the autofs automounter' EQUALITY caseExactIA5Match SYNTAX 1.
 3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
olcObjectClasses: {0}( 1.3.6.1.1.1.1.13 NAME 'automount' DESC 'An entry in an 
 automounter map' SUP top STRUCTURAL MUST ( cn $ automountInformation $ object
 class ) MAY description )
olcObjectClasses: {1}( 1.3.6.1.4.1.2312.4.2.2 NAME 'automountMap' DESC 'An gro
 up of related automount objects' SUP top STRUCTURAL MUST ou )

There’s nothing environment specific in there, so you won’t need to make any changes. Now add it to the LDAP database:

sudo ldapadd -Y EXTERNAL -H ldapi:/// -f autofs.ldif

Now to create our automount maps, make a new file, automount.ldif

nano automount.ldif

And enter the following data:

dn: ou=admin,dc=danbishop,dc=org
ou: admin
objectClass: top
objectClass: organizationalUnit

dn: ou=automount,ou=admin,dc=danbishop,dc=org
ou: automount
objectClass: top
objectClass: organizationalUnit

dn: ou=auto.master,ou=automount,ou=admin,dc=danbishop,dc=org
ou: auto.master
objectClass: top
objectClass: automountMap

dn: cn=/home,ou=auto.master,ou=automount,ou=admin,dc=danbishop,dc=org
cn: /home
objectClass: top
objectClass: automount
automountInformation: ldap:ou=auto.home,ou=automount,ou=admin,dc=danbishop,dc=org --timeout=60 --ghost

dn: ou=auto.home,ou=automount,ou=admin,dc=danbishop,dc=org
ou: auto.home
objectClass: top
objectClass: automountMap

dn: cn=/,ou=auto.home,ou=automount,ou=admin,dc=danbishop,dc=org
cn: /
objectClass: top
objectClass: automount
automountInformation: -fstype=nfs4,rw,hard,intr,fsc,sec=krb5 neo.danbishop.org:/home/$

This tells AutoFS to map all requests for /home/$USERNAME to the correct NFS share. Please note: as above, it is important that an empty new line exists between each section, if you are copy and pasting the above remember to remove the space character present on the blank lines!

Now we add it to the database:

sudo ldapadd -D cn=admin,dc=danbishop,dc=org -W -f automount.ldif

Sudo LDAP

So that clients know which users/groups can use sudo and that this can be centrally managed, we’re also going to create a schema for sudo.

Create a new file called sudo.ldif

nano sudo.ldif

And paste the following contents into it:

dn: cn=sudo,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: sudo
olcAttributeTypes: {0}( 1.3.6.1.4.1.15953.9.1.1 NAME 'sudoUser' DESC 'User(s) 
 who may  run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMa
 tch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
olcAttributeTypes: {1}( 1.3.6.1.4.1.15953.9.1.2 NAME 'sudoHost' DESC 'Host(s) 
 who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMat
 ch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
olcAttributeTypes: {2}( 1.3.6.1.4.1.15953.9.1.3 NAME 'sudoCommand' DESC 'Comma
 nd(s) to be executed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1
 466.115.121.1.26 )
olcAttributeTypes: {3}( 1.3.6.1.4.1.15953.9.1.4 NAME 'sudoRunAs' DESC 'User(s)
  impersonated by sudo (deprecated)' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1
 .4.1.1466.115.121.1.26 )
olcAttributeTypes: {4}( 1.3.6.1.4.1.15953.9.1.5 NAME 'sudoOption' DESC 'Option
 s(s) followed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115
 .121.1.26 )
olcAttributeTypes: {5}( 1.3.6.1.4.1.15953.9.1.6 NAME 'sudoRunAsUser' DESC 'Use
 r(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466
 .115.121.1.26 )
olcAttributeTypes: {6}( 1.3.6.1.4.1.15953.9.1.7 NAME 'sudoRunAsGroup' DESC 'Gr
 oup(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.14
 66.115.121.1.26 )
olcAttributeTypes: {7}( 1.3.6.1.4.1.15953.9.1.8 NAME 'sudoNotBefore' DESC 'Sta
 rt of time interval for which the entry is valid' EQUALITY generalizedTimeMat
 ch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
  )
olcAttributeTypes: {8}( 1.3.6.1.4.1.15953.9.1.9 NAME 'sudoNotAfter' DESC 'End 
 of time interval for which the entry is valid' EQUALITY generalizedTimeMatch 
 ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
olcAttributeTypes: {9}( 1.3.6.1.4.1.15953.9.1.10 NAME 'sudoOrder' DESC 'an int
 eger to order the sudoRole entries' EQUALITY integerMatch ORDERING integerOrd
 eringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
olcObjectClasses: {0}( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' DESC 'Sudoer En
 tries' SUP top STRUCTURAL MUST cn MAY ( sudoUser $ sudoHost $ sudoCommand $ s
 udoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ sudoOrder $ sudoNotB
 efore $ sudoNotAfter $ description ) )

Now we add this to our LDAP server like so:

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

LDAP now knows what sudo records are and how to store them, so now we can create a container and then fill it with records for our sudo enabled groups.

To do this, create a sudoMaster.ldif file:

nano sudoMaster.ldif

And enter the following contents:

dn: ou=sudoers,dc=danbishop,dc=org
objectclass: organizationalUnit
objectclass: top
ou: sudoers

dn: cn=defaults,ou=sudoers,dc=danbishop,dc=org
objectClass: top
objectClass: sudoRole
cn: defaults
description: Default sudoOptions go here
sudoOption: env_reset
sudoOption: mail_badpass
sudoOrder: 1

dn: cn=root,ou=sudoers,dc=danbishop,dc=org
objectClass: top
objectClass: sudoRole
cn: root
sudoUser: root
sudoHost: ALL
sudoRunAsUser: ALL
sudoRunAsGroup: ALL
sudoCommand: ALL
sudoOrder: 2

dn: cn=%admin,ou=sudoers,dc=danbishop,dc=org
objectClass: top
objectClass: sudoRole
cn: %admin
sudoUser: %admin
sudoHost: ALL
sudoRunAsUser: ALL
sudoCommand: ALL
sudoOrder: 3

dn: cn=%sudo,ou=sudoers,dc=danbishop,dc=org
objectClass: top
objectClass: sudoRole
cn: %sudo
sudoUser: %sudo
sudoHost: ALL
sudoRunAsUser: ALL
sudoRunAsGroup: ALL
sudoCommand: ALL
sudoOrder: 4

dn: cn=%domainadmins,ou=sudoers,dc=danbishop,dc=org
objectClass: top
objectClass: sudoRole
cn: %domainadmins
sudoUser: %domainadmins
sudoHost: ALL
sudoRunAsUser: ALL
sudoRunAsGroup: ALL
sudoCommand: ALL
sudoOrder: 5

PLEASE NOTE: As with other ldif files, the blank lines in the above must be exactly that! If you’re copying and pasting from this blog, you will have a single space character on each “blank” line. Be sure to remove it, leaving only a blank line! I will fix this one day…

Now we can add our information to the LDAP database like so:

ldapadd -f sudoMaster.ldif -D "cn=admin,dc=danbishop,dc=org" -W -x

And we’re done!

References

http://www.opinsys.fi/en/setting-up-openldap-on-ubuntu-10-04-lucid-part2
http://www.debian.org/doc/manuals/debian-reference/ch05.en.html#s-net-dns
https://help.ubuntu.com/community/AutofsLDAP

  • Christian Oswald

    Hello,
    it’s a very useful tutorial and I learned a lot from it.
    I had also the problem with “Error adding group domainusers to LDAP” and in my case I solved it with switches TLS off in the LDAP-Server. I made it with webmin because I can’t find the correct place for it in the configuration files. I think it depends from the defaults of the ubuntu installation (in my case 14.04).
    But I have also a problem with the kerberos authentification. It works nice on the server (kadmin.local runs, kinit brings a ticket …) but from a client I get all times the error “kadmin: Cannot contact any KDC for requested realm while initializing kadmin interface”.
    I have reinstalled all, checked the configuration file of dnsmasq, krb5 … nothing helps, no firewall runs …
    I have tested a lot – ping, nslookup works and give the correct server. But nmap said that only port 749 is open on the server but in the kdc.conf is written that port 750 and 88 is used. I don’t if it’s important.
    Has anyone any idea for the reason of this error?

    Thanks,
    Christian

  • Jezzirolk

    hey Dan, i have used your guides a few times and they are great. Still work with 14.04 i dont think there was any tweaking i really had to do. i have a question though, is there a reason you disabled cache_credntials. Not saying there arent possible security reasons but i was more curious if there were other technical reasons becasue when connecting a laptop it is providing to make this a bit harder.

    –jezzirolk

    • danbishop88

      Hi Jezzirolk,

      I believe my reason for this was to do with: https://bugs.launchpad.net/ubuntu/+source/sssd/+bug/1039151

      Basically, without it SSSD tends to come up before your network connection. This forces it into “offline” mode and it won’t even try to reconnect to your ldap/kerberos server until two minutes have elapsed. This prevents anyone from logging in for the full two minutes.

      A better workaround is listed in that thread, which is forcing the login screen to wait for the network to come up before appearing. I intend to move to that if I ever get round to finishing my 14.04 guide.

      Hope that helps…

      Dan

      • Jezzirolk

        Hey Dan,
        this still doesn’t really solve the issues i think, waiting for the network doesn’t do much for my case of a laptop. if i am off site it still wont connect properly unless you try to use cached credentials. Are we saying use cached credentials and then wait for network as to prevent the false negative of can not connect to ldap server? if that’s the case that might work.

        i guess the better question is if i log in off line. how does reconnecting once we end up back on a network with access to the server?

        Any thoughts on this and how to deal with the NFS mounts with laptop or systems that end up off site.

        –jezzirolk