OpenLDAP: Implementation specific error 80 when adding TLS Certificate

Last weekend I was installing and configuring the OpenLDAP server slapd (Standalone OpenLDAP Daemon) with Puppet. For this I employed the camptocamp/openldap Puppet module.

When setting up the LDAP server I also wanted to add some encryption on top. But then I had this weird error ldap_modify: Other (e.g., implementation specific) error (80) when Puppet was applying the LDIF to modify the X.509 certificates and keys for slapd.

Just as a side note: slapd is configured through its own database to avoid any downtime. That’s why configuration changes are made through LDIF (LDAP Data Interchange Format) files. Read more about on-line configuration (OLC) in Chapter 6 of the “Open Source Guide to LDAP”.

So this was my initial Puppet code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class profile::openldap (
  String $server_name = 'example',
  String $tld = 'com',
  String $admin_password,
  String $ssl_key_path = '/etc/ssl/private/ssl-cert-snakeoil.key',
  String $ssl_cert_path = '/etc/ssl/certs/ssl-cert-snakeoil.pem',
) {

class { '::openldap::server':
  provider => 'olc',
  ssl_key => $ssl_key_path,
  ssl_cert => $ssl_cert_path,
}

openldap::server::database { "dc=${server_name},dc=${tld}":
  ensure => present,
  rootdn => "cn=admin,dc=${server_name},dc=${tld}",
  rootpw => $admin_password,
}

You don’t need to understand the code above, just look at the occurrences of the ssl_key_path and ssl_cert_path parameters (specifying the private key and certificate, respectively).

The Puppet modules automatically generates the LDIF to adjust the paths to these files:

1
2
3
4
5
6
7
dn: cn=config
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ssl/certs/ssl-cert-snakeoil.pem
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ssl/private/ssl-cert-snakeoil.key
-

But when Puppet was trying to apply this LDIF file - as well as when I applied it manually - ldapmodify returned the following error:

1
2
3
4
5
6
$ ldapmodify -Y EXTERNAL -H ldapi:/// -f /tmp/openldap_global_conf20190209-14638-1aj63yj
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
ldap_modify: Other (e.g., implementation specific) error (80)
modifying entry "cn=config"

The authentication worked fine, but afterwards there was this “implementation specific” error.

First I assumed it must have had something to do with the LDIF file, so I tried adding a changetype: modify and playing with the order of arguments in the file. But alas, none of that helped.

After digging around for quite some time I found the issue: slapd was unable to access the files! Albeit, this is a very bad error message for that.

1
2
3
4
$ ls -l /etc/ssl/private/ssl-cert-snakeoil.key
-rw-r----- 1 root ssl-cert 1704 Feb  9 18:00 /etc/ssl/private/ssl-cert-snakeoil.key
$ groups openldap
openldap : openldap

The certificate and key are owned by the user ‘root’ and members of the group ‘ssl-cert’ have read-access to them. But the ‘openldap’ user is not in that group, therefore it can’t read these files.

The fix was to add the ‘openldap’ user (which slapd runs as on Debian) to the ‘ssl-cert’ group. Also don’t forget to restart your slapd! (Otherwise the kernel won’t apply the permissions to the process)

1
2
$ usermod -aG ssl-cert openldap
$ systemctl restart slapd

Fix in Puppet:

1
2
3
4
5
user { 'openldap':
  groups => ['ssl-cert'],
  require => [ Package['ssl-cert'], Package['slapd'] ],
  notify => Service['slapd'],
}

Check if the ‘openldap’ user can now access the files:

1
2
3
4
$ sudo -u openldap file /etc/ssl/certs/ssl-cert-snakeoil.pem
/etc/ssl/certs/ssl-cert-snakeoil.pem: PEM certificate
$ sudo -u openldap file /etc/ssl/private/ssl-cert-snakeoil.key
/etc/ssl/private/ssl-cert-snakeoil.key: ASCII text

Afterwards Puppet ran just fine:

1
2
3
4
5
6
7
Notice: /Stage[main]/Openldap::Server::Install/Package[slapd]/ensure: created
Notice: /Stage[main]/Openldap::Server::Config/Shellvar[slapd]/value: value changed ['ldap:/// ldapi:///'] to ['ldap:/// ldapi:/// ']
Notice: /Stage[main]/Openldap::Server::Service/Service[slapd]: Triggered 'refresh' from 1 event
Notice: /Stage[main]/Openldap::Server::Slapdconf/File[/etc/ldap/slapd.d]/mode: mode changed '0755' to '0750'
Notice: /Stage[main]/Openldap::Server::Slapdconf/Openldap::Server::Globalconf[TLSCertificate]/Openldap_global_conf[TLSCertificate]/ensure: created
Notice: /Stage[main]/Openldap::Server::Slapdconf/Openldap::Server::Database[dc=my-domain,dc=com]/Openldap_database[dc=my-domain,dc=com]/ensure: removed
Notice: /Stage[main]/Profile::Openldap/Openldap::Server::Database[dc=example,dc=com]/Openldap_database[dc=example,dc=com]/ensure: created

Just a heads-up in case anyone else stumbles onto this meaningless error message.

Also posted at: https://github.com/camptocamp/puppet-openldap/issues/238