9
votes

Edit : Issue finally solved. The detail can be found in the troubleshooting part at the end of this message.

I leave the detailed steps here in case it could help somebody.

Setup OpenLDAP

I - Create the server

The documentation are often outdated and you will find multiple ways to achieve the same.
According to what I've read, the modern way to create a server is to use /etc/openldap/slapd.ldif instead of /etc/openldap/slapd.conf. Below is a sample configuration using letsencrypt certificates.

You can often convert a slapd.conf directive in slapd.ldif by prepending it with olc. Just make sure this is in the right dn block.

Make sure you create a directory /etc/openldap/slapd.d readable and writable by ldap user, and that slapd is stopped. Insert you're slapd.ldif into slapd.d with slapadd command. I run it using sudo -u ldap in order for slapadd to create files owned by ldap users. You can also run slapadd without sudo and then chown -R ldap:ldap /etc/openldap/slapd.d. What is important here is that all of you're /etc/openldap directory is readable / writable by user slapd run with.

$ sudo -u ldap slapadd -d -1 \
    -F /etc/openldap/slapd.d \
    -n 0 \
    -f /etc/openldap/slapd.ldif

OpenLDAP configuration:

# /etc/openldap/slapd.ldif
------------------------------------
dn: cn=config
objectClass: olcGlobal
cn: config
olcArgsFile: /run/openldap/slapd.args
olcPidFile: /run/openldap/slapd.pid
olcTLSCipherSuite: ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS
olcTLSCACertificateFile: /etc/letsencrypt/live/example/chain.pem
olcTLSCertificateFile: /etc/letsencrypt/live/example/cert.pem
olcTLSCertificateKeyFile: /etc/letsencrypt/live/example/privkey.pem
olcTLSVerifyClient: never

#
# Load dynamic backend modules:
#
dn: cn=module,cn=config
objectClass: olcModuleList
cn: module
olcModuleload: back_mdb.so


dn: cn=schema,cn=config
objectClass: olcSchemaConfig
cn: schema

include: file:///etc/openldap/schema/core.ldif
include: file:///etc/openldap/schema/cosine.ldif
include: file:///etc/openldap/schema/nis.ldif
include: file:///etc/openldap/schema/inetorgperson.ldif
include: file:///etc/openldap/schema/openldap.ldif
include: file:///etc/openldap/schema/kerberos.ldif
include: file:///etc/openldap/schema/openssh-lpk.ldif

# Frontend settings
#
dn: olcDatabase=frontend,cn=config
objectClass: olcDatabaseConfig
objectClass: olcFrontendConfig
olcDatabase: frontend
olcAccess: to dn.base="" by * read
olcAccess: to dn.base="cn=Subschema" by * read
olcAccess: to * 
    by self write 
    by users read 
    by anonymous auth


#######################################################################
# LMDB database definitions
#######################################################################
#
dn: olcDatabase=mdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: mdb
olcSuffix: dc=example,dc=com
olcRootDN: cn=Manager,dc=example,dc=com
olcRootPW: {SSHA}anEncryptedPassword
olcDbDirectory: /var/lib/openldap-data
# Indices to maintain
olcDbIndex: objectClass        eq
olcDbIndex: uid                pres,eq
olcDbIndex: memberUid          eq
olcDbIndex: uidNumber          eq
olcDbIndex: gidNumber          eq
olcDbIndex: uniqueMember       eq
olcDbIndex: cn                 pres,sub,eq
olcDbIndex: mail               pres,sub,eq
olcDbIndex: sn                 pres,sub,eq
olcDbIndex: givenname          eq,subinitial
olcDbIndex: dc                 eq
olcDbIndex: krbPrincipalName   eq,pres,sub
olcAccess: to attrs=userPassword,shadowLastChange,krbPrincipalKey,givenName,sn,photo 
    by self write 
    by anonymous auth 
    by dn.base="cn=Manager,dc=example,dc=com" write 
    by * none
olcAccess: to * 
    by self read 
    by dn.base="cn=Manager,dc=example,dc=com" write 
    by * read

II - Setup the Directory Information Tree (DIT)

Start the server: $ systemctl start slapd

This will create a /var/lib/openldap-data/data.mdb (the directory may differ on your distro). If you have trouble or if you want to reset your OpenLDAP, you can rm -rf /etc/openldap/slapd.d/* /var/lib/openldap-data/{data.mdb,lock.mdb} after stopping slapd service and return to step I.

I changed my slapd.service to destroy /var/lib/openldap-data/lock.mdb because on my setup, this file is not removed when shutting down slapd and this prevents it to start again.

Content of the slapd.service:

# /etc/systemd/system/slapd.service
------------------------------------
[Unit]
Description=OpenLDAP Server Daemon
After=network.target

[Service]
# "-d n" stops slapd from forking
ExecStartPre = /bin/rm -f /var/lib/openldap-data/lock.mdb
ExecStart = /usr/lib64/openldap/slapd -u ldap -g ldap -h ${SLAPD_URLS} $SLAPD_OPTIONS -d1
ExecStopPost = /bin/rm -f /var/lib/openldap-data/lock.mdb
Restart = always
RestartSec = 180

[Install]
WantedBy=multi-user.target

# /etc/systemd/system/slapd.service.d/00gentoo.conf
------------------------------------
[Service]
Environment="HOME=/var/lib/openldap"
# Use the slapd configuration directory:
Environment="SLAPD_OPTIONS=-F /etc/openldap/slapd.d"
Environment="SLAPD_URLS=ldaps:/// ldap://127.0.0.1:389/ ldapi://127.0.0.1"
Environment="KRB5_KTNAME=FILE:/etc/openldap/ldap.keytab"

Ensure certificates can be read by ldap user:

$ useradd -r letsencrypt
$ chown -R letsencrypt:letsencrypt /etc/letsencrypt
$ gpasswd -a ldap letsencrypt
$ chmod 750 /etc/letsencrypt/{live,archive}

Then add ldif files that builds the DIT:

$ ldapadd -x -W -D "cn=Manager,dc=example,dc=com" -f ${PATH_TO_FILES}

# example.com.ldif
------------------------------------
# Create example dn
dn: dc=example,dc=com
dc: example
objectClass: dcObject
objectClass: organization
o: Example Organization

# Create Manager role
dn: cn=Manager,dc=example,dc=com
cn: Manager
description: LDAP Administrator
objectClass: organizationalROle
objectClass: top
roleOccupant: dc=example,dc=com

# users.ldif
------------------------------------
dn: ou=People,dc=example,dc=com
objectClass: top
objectClass: organizationalUnit
ou: People
description: Users of Example

# groups.ldif
------------------------------------
dn: ou=Group,dc=example,dc=com
objectClass: top
objectClass: organizationalUnit
ou: Group
description: Groups of Example

III - Setup the LDAP client

Configure ldap.conf:

# /etc/openldap/ldap.conf
------------------------------------
BASE    dc=example,dc=com
URI ldaps://example.com

TLS_CACERT      /etc/letsencrypt/live/example/chain.pem
TLS_REQCERT     allow
TIMELIMIT       2

Setup Kerberos

I - Configure the server

Server config (mit-krb5):

# /etc/krb5.conf
------------------------------------
[logging]
    default = FILE:/var/log/krb5/libs.log
    kdc = FILE:/var/log/krb5/kdc.log
    admin_server = FILE:/var/log/krb5/kadmind.log

[libdefaults]
    default_realm = EXAMPLE.COM

[realms]
    EXAMPLE.COM = {
        kdc = example.com
        admin_server = example.com
        default_domain = example.com
        database_module = openldap_ldapconf
    }

[domain_realm]
    example.com = EXAMPLE.COM
    .example.com = EXAMPLE.COM

[dbdefaults]
    ldap_kerberos_container_dn = cn=krbContainer,dc=example,dc=com

[dbmodules]
    openldap_ldapconf = {
        db_library = kldap
        ldap_kdc_dn = "cn=Manager,dc=example,dc=com"

        ldap_kadmind_dn = "cn=Manager,dc=example,dc=com"

        ldap_service_password_file = /etc/krb5kdc/service.keyfile
        ldap_servers = ldaps://example.com
        ldap_conns_per_server = 5
    }

Then, create the realm: $ kdb5_util -r EXAMPLE.COM create -s

II - Configure OpenLDAP backend

Setup the Kerberos OpenLDAP subtree:

$ kdb5_ldap_util -D "cn=Manager,dc=example,dc=com" create -subtrees dc=example,dc=com -r EXAMPLE.COM -s -H ldap://127.0.0.1"

and create a local copy of the master key that resides in encrypted form on the KDC’s local disk for linking with OpenLDAP:

$ kdb5_ldap_util -D "cn=Manager,dc=example,dc=com" stashsrvpw -f /etc/krb5kdc/service.keyfile cn=Manager,dc=example,dc=com

This is also known as (aka) stash file.

III - Create a principal

Start the MIT Kerberos v5 services (krb5):

$ systemctl start krb5-kdc krb5-kadmind

Systemd services have been taken from ArchLinux packages (since Gentoo didn't provides those files):

krb5-kdc.service:

# /etc/systemd/system/krb5-kdc.service
------------------------------------
[Unit]
Description=Kerberos 5 KDC

[Service]
ExecStart=/usr/sbin/krb5kdc -n
Restart=always

[Install]
WantedBy=multi-user.target

krb5-kadmind:

# /etc/systemd/system/krb5-kadmind.service
------------------------------------
[Unit]
Description=Kerberos 5 administration server

[Service]
ExecStart=/usr/sbin/kadmind -nofork

[Install]
WantedBy=multi-user.target

Fire up a kadmin console using $ kadmin.local:

Add this principal to kadm5.acl:

# /var/lib/krb5kdc/kadm5.acl
------------------------------------
root/[email protected] *

IV - Configure Key Distribution Center (KDC)

Configure kdc.conf:

# /var/lib/krb5kdc/kdc.conf
------------------------------------
[kdcdefaults]
kdc_ports = 750,88

[realms]
EXAMPLE.COM = {
    database_name = /var/lib/krb5kdc/principal
    acl_file = /var/lib/krb5kdc/kadm5.acl
    key_stash_file = /var/lib/krb5kdc/.k5.EXAMPLE.COM
    kdc_ports = 750,88
    max_life = 10h 0m 0s
    max_renewable_life = 7d 0h 0m 0s
}

Then restart krb5 services: $ systemctl restart krb5-kdc krb5-kadmind

V - Setup saslauthd

SASLAuthD is the daemon that will catch SASL requests from LDAP and convert them into Kerberos (or whatever authentication mecanism you use) requests. It is required if you want to use passwords of you're authentication service instead of LDAP passwords and will allow you for example:

userPassword: {SASL}[email protected]

whereby EXAMPLE.COM is your realm and user is a principal.

Configure SASL2 slapd:

# /etc/sasl2/slapd.conf (Gentoo) or /usr/lib/sasl2 (Ubuntu)
------------------------------------
pwcheck_method:saslauthd

Make sure saslauthd is using Kerberos v5:

# /etc/conf.d/saslauthd (Gentoo) or /etc/default/saslauthd (Ubuntu)
------------------------------------
# -a describe the mechanism used
# -m is the working directory, where socket will be located
SASLAUTHD_OPTS="-a kerberos5 -m /run/saslauthd"

You can check the parameters in the man page or using $ saslauthd -h. Make sure to use the appropriate variables in this files. You can see which one are used with $ systemctl cat saslauthd on a systemd setup.

Make also sure the socket (/run/saslauthd/mux) is readable / writable by saslauthd.

Start the service using

$ systemctl start saslauthd

and check saslauthd is working using:

$ testsaslauthd -r YOURREALM -u someusernameyouwant -p somepassword

VI - Setup GSSAPI/SASL Authentication

Open up a kadmin console using $ kadmin.local and create GSSAPI principals and keytab files:

First create a service principal inside Kerberos database for your directory server, and create a keyfile containing an entry for that principal into openldap configuration directory.
You can replace instances of example.com but ldap/ should be written litteraly.

$ addprinc -randkey ldap/[email protected]
$ ktadd -k /etc/openldap/ldap.keytab ldap/[email protected]

Then create a host principal for the client, and its keytab. You can replace instances of example.com but host/ should be written litteraly.

$ addprinc -randkey host/[email protected]
$ ktadd -k /etc/krb5.keytab host/[email protected]

And quit: $ quit

Make sure ldap.keytab is readable for ldap user/group only:

$ chown ldap:ldap /etc/openldap/ldap.keytab
$ chmod 640 /etc/openldap/ldap.keytab

Ensure to get a fresh Kerberos ticket:

$ kinit

And it's done, you've setup a Kerberos server with OpenLDAP backend.

You can now tell OpenLDAP to use Kerberos passwords when you create / modify users:

userPassword: {SASL}[email protected]

For example, you can create a file.ldif containing the following, and add it using ldapadd as previously:

dn: uid=root,ou=People,dc=example,dc=com
uid: root
cn: root
objectClass: account
objectClass: posixAccount
objectClass: top
objectClass: shadowAccount
userPassword: {SASL}[email protected]
loginShell: /bin/zsh
uidNumber: 0
gidNumber: 0
homeDirectory: /root
gecos: root

You can also search using ldapsearch with no arguments.

Troubleshooting

As my initial question is now solved

Server ldap/[email protected] not found in Kerberos database)

here are some tips when you encounter some problems:

Check logs

  • slapd.service: Use journalctl -xe (My service type is not Forking, and the flag -d 9 will print the log in systemd journal. You can disable logging with -d 0, but keep the flag -d, or declare it as Type: Forking)
  • krb5-kdc: Check out /var/log/krb5/kdc.log or whatever you've set inside /etc/krb5.conf
  • krb5-kadmind: Check /var/log/krb5/kadmind.log or whatever you've set inside /etc/krb5.conf
  • saslauthd: You need to enable debugging with flag -d. Either run saslauthd in a shell with this flag or add this flag to /etc/conf.d/saslauthd (Gentoo) or /etc/default/saslauthd (Ubuntu) and use journalctl -xe to see them.

Problem

Server ldap/[email protected] not found in Kerberos database

When I run $ ldapsearch or $ ldapwhoami, I'm having the following error:

ldap_sasl_interactive_bind_s: Local error (-2)
additional info: SASL(-1): generic failure: GSSAPI Error: Unspecified GSS failure.
Minor code may provide more information (Server ldap/[email protected] not found in Kerberos database)

Solution

Check that you correctly followed step V and VI of Kerberos setup. You need a keytab readable by OpenLDAP. You can place it where you want and name it as you want. Also make sure the Environmental variable KRB5_KTNAME is set (either in systemd service or in you're init system / in the shell you run slapd), pointing to that keytab.

The host keytab should be placed at /etc/krb5.keytab. It may not be important for ldapsearch / ldapapi (I didn't check if it works without) but it is required for daemons such as SSSD.

Problem

ldap_sasl_interactive_bind_s: Invalid credentials (49)

When I run $ ldapsearch or $ ldapwhoami, I'm having the following error :

SASL/GSSAPI authentication started
ldap_sasl_interactive_bind_s: Invalid credentials (49)
        additional info: SASL(-13): authentication failure: GSSAPI
Failure: gss_accept_sec_context

Solution

Try to refresh you're Kerberos ticket: $ kinit

Credits

Hope those steps could help some others beginners, credits goes to:

And some others guides (check out Setting Up Kerberos Authentication on Fedora)

1
I'm following your steps, however, in step V Setup saslauthd, I cant find kerberos5 as the auth provider. My os is SLES12. Am I missing any package? Any ideas?orak

1 Answers

4
votes

Ok so I finally solved my answer :

I simply needed to create the server on Kerberos, and create a keyfile containing it.

$ addprinc -randkey ldap/[email protected]
$ ktadd -k /etc/openldap/ldap.keytab ldap/[email protected]

Slapd wasn't aware of that file so I added the environment variable to my slapd.service :

# /etc/krb5.conf
------------------------------------
Environment="KRB5_KTNAME=FILE:/etc/openldap/ldap.keytab"

I also needed to configure saslauthd and run it :

Configure daemon :

# /etc/conf.d/saslauthd (gentoo) or /etc/default/saslauthd (ubuntu)
------------------------------------
# -a describe the mechanism used
# -m is the working directory, where socket will be located
SASLAUTHD_OPTS="-a kerberos5 -m /run/saslauthd"

Configure options :

# /etc/sasl2/slapd.conf (gentoo) or /usr/lib/sasl2 (ubuntu)
------------------------------------
pwcheck_method:saslauthd

Start it : $ systemctl start saslauthd

An error then showed up :

SASL/GSSAPI authentication started
ldap_sasl_interactive_bind_s: Invalid credentials (49)
        additional info: SASL(-13): authentication failure: GSSAPI
Failure: gss_accept_sec_context

This was because my kerberos ticket expired. I just ran $ kinit and it solved the problem.

I edited the question to add missing steps to the "guide" part, feel free to edit name / improve it / copy / paste. Thanks.