TinyCA2 as a replacement for YaST’s CA-tools on Opensuse Leap servers with TLS/SSL – II

In my last article on TinyCA2

TinyCA2 as a replacement for YaST’s CA-tools on Opensuse Leap servers with TLS/SSL – I

I discussed how to open an new CA and how to create a server certificate (plus private key) with SHA256 as the preferred hashing algorithm. We saw that TinyCA2 offers an option to export the certificate’s private key with or without password. I also gave an “openssl” command for stripping a key off its password later on – even if it was exported with a password in the beginning.

We have followed a policy of using a server wide TLS/SSL-certificate for all TLS/SSL-based services run on a server – in our case on a server “myserv.anraconc.de”. Therefore we have copied the certificate’s pem file and the key’s pem file to the directory “/etc/ssl/servercerts” with file names “servercert.pem” and “serverkey.pem”.

In addition we naively copied the CA certificate as file “anraconc-CA.pem” into the central directory “/etc/ssl/certs” which contains (links to) all trusted certificates on an Opensuse system.

If the private key was exported with a password we have a problem with automated system and service starts: As the private key of a server certificate must in some cases also by system users starting and running services we would be asked to provide a password interactively, whenever the service is started – e.g. during system startup. To avoid such a situation we need a private key without password – hence we have to deal carefully with read access rights. Actually, we need to find out which services – not started or run by root – need the access right for its special system user. For the time being we took away all read rights for “others” from the server key for the system “myserv”.

In this second article I discuss the changes to be made to the configuration of two services – Apache2 and OpenLDAP on server “myserv”. After a test we shall detect that Opensuse rebuilds the contents of “/etc/ssl/certs” during a reboot – and references of our services to the CA’s certificate will fail. I shall show where to save our CA certificate to make it permanently available.

Re-configuring a local Apache service for the new CA and the changed server certificate

As I had used a server wide certificate on “myserv” already at times when YaST’s CA-administration was still available, I expected that the required changes to the service configuration would be limited to providing the path to the new CA certificate. The example of the Apache service proved that this really was true.

In my case I use virtual domains with my Apache server for Intranet sites. The configuration of the SSL-setup then is to be found in either a central file as “/etc/apache2/ssl-global.conf” or in “/etc/apache2/vhosts.d/vhost-ssl.conf” for individual domains. I used the latter file. I shall only show the most simple case here – with just a main standard domain associated on an Opensuse system with the directory “/srv/www/htdocs”. Other domains would get the same SSL settings (if you do not plan to issue different certificates for each intranet domain):

<VirtualHost *:443>

        #  General setup for the virtual host
        DocumentRoot "/srv/www/htdocs/"
        ServerName myserv
        #ServerAdmin webmaster@example.com
        ErrorLog /var/log/apache2/error_log
        TransferLog /var/log/apache2/access_log

        #   SSL Engine Switch:
        #   Enable/Disable SSL for this virtual host.
        SSLEngine on

        #   SSL Cipher Suite:
        #   List the ciphers that the client is permitted to negotiate.
        #   See the mod_ssl documentation for a complete list.
        SSLCipherSuite ALL:!
ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL

        #   Server Certificate:
        #   Point SSLCertificateFile at a PEM encoded certificate.  If
        #   the certificate is encrypted, then you will be prompted for a
        #   pass phrase.  
        SSLCertificateFile /etc/ssl/servercerts/servercert.pem

        #   Server Private Key:
        #   If the key is not combined with the certificate, use this
        #   directive to point at the key file.  
        SSLCertificateKeyFile /etc/ssl/servercerts/serverkey.pem

        #   Server Certificate Chain:
        #   Point SSLCertificateChainFile at a file containing the
        #   concatenation of PEM encoded CA certificates which form the
        #   certificate chain for the server certificate. 
        SSLCertificateChainFile /etc/ssl/certs/anraconc-CA.pem
        #
        # NOTE: here you should later on use the Common Name of your CA certificate !
        # See below ! 
.....
......

Note that I referred to the CA certificate at “/etc/ssl/certs” in the CA chain setting. The server certificate and key files are referred to already by the standard paths “/etc/ssl/servercerts/servercert.pem” and “/etc/ssl/servercerts/serverkey.pem”.

With this changed configuration file we restart our Apache service:

myserv:/etc/apache2/vhosts.d # vi vhost-ssl.conf
myserv:/etc/apache2/vhosts.d # systemctl restart apache2.service
myserv:/etc/apache2/vhosts.d # systemctl status apache2.service
● apache2.service - The Apache Webserver
   Loaded: loaded (/usr/lib/systemd/system/apache2.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2019-07-20 15:37:29 CEST; 11s ago
  Process: 20435 ExecStop=/usr/sbin/start_apache2 -DSYSTEMD -DFOREGROUND -k graceful-stop (code=exited, status=0/SUCCESS)
 Main PID: 20443 (httpd-prefork)
   Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"
    Tasks: 6
   CGroup: /system.slice/apache2.service
           ├─20443 /usr/sbin/httpd-prefork -DSYSCONFIG -DSSL -C PidFile /var/run/httpd.pid -C Include /etc/apache2/sysconfig.d//loadmodule.conf -C Include /etc/a>
           ├─20449 /usr/sbin/httpd-prefork -DSYSCONFIG -DSSL -C PidFile /var/run/httpd.pid -C Include /etc/apache2/sysconfig.d//loadmodule.conf -C Include /etc/a>
           ├─20450 /usr/sbin/httpd-prefork -DSYSCONFIG -DSSL -C PidFile /var/run/httpd.pid -C Include /etc/apache2/sysconfig.d//loadmodule.conf -C Include /etc/a>
           ├─20451 /usr/sbin/httpd-prefork -DSYSCONFIG -DSSL -C PidFile /var/run/httpd.pid -C Include /etc/apache2/sysconfig.d//loadmodule.conf -C Include /etc/a>
           ├─20452 /usr/sbin/httpd-prefork -DSYSCONFIG -DSSL -C PidFile /var/run/httpd.pid -C Include /etc/apache2/sysconfig.d//loadmodule.conf -C Include /etc/a>
           └─20453 /usr/sbin/httpd-prefork -DSYSCONFIG -DSSL -C PidFile /var/run/httpd.pid -C Include /etc/apache2/sysconfig.d//loadmodule.conf -C Include /etc/a>

Jul 20 15:37:29 myserv systemd[1]: Starting The Apache Webserver...
Jul 20 15:37:29 myserv start_apache2[20443]: [Sat Jul 20 15:37:29.522427 2019] [so:warn] [pid 20443] AH01574: module authn_core_module is already loaded, skipping
Jul 20 15:37:29 myserv systemd[1]: Started The Apache Webserver.

Obviously, only root needs to read “/etc/ssl/servercerts/serverkey.pem” for starting the service – although multiple “httpd-prefork” processes later on are run by the system user “wwwrun”. However, the first one is run by root.

Note:
If you get any trouble here, please have a look into the Apache log files (in my case in “/var/log/apache2/error.log”). If you see something there like

[Sat Jul 20 14:56:15.132380 2019] [ssl:emerg] [pid 13320] AH02561: Failed to configure certificate myserv:443:0, check /etc/ssl/servercerts/servercert.pem
[Sat Jul 20 14:56:15.
132404 2019] [ssl:emerg] [pid 13320] SSL Library Error: error:140AB18E:SSL routines:SSL_CTX_use_certificate:ca md too weak
AH00016: Configuration Failed
[Sat Jul 20 15:00:53.251242 2019] [ssl:emerg] [pid 14285] AH02561: Failed to configure certificate myserv:443:0, check /etc/ssl/servercerts/servercert.pem
[Sat Jul 20 15:00:53.251268 2019] [ssl:emerg] [pid 14285] SSL Library Error: error:140AB18E:SSL routines:SSL_CTX_use_certificate:ca md too weak
AH00016: Configuration Failed

then you are confronted with a point I mentioned in my first article. The error message criticizes that the “md”-hashing algorithm is too weak. But didn’t we use SHA256?

Well, you meant to do so – because it my have been shown as the option chosen by default for the “Digest”. And you did not change this setting. However, if you did not click the radio button explicitly after some other value you may not have gotten what you saw. Without your explicit interaction with the radio buttons the default is “md”. So, it is important for all certificates to explicitly choose a different value first and then click on the right radio button for a digest again. The same is true for the setting of the key length and other options.

For other services than Apache2 you would basically proceed in an analogous way. So far – so good. Unfortunately, our approach is still not good enough!

How to make a CA certificate pem file system wide and permanently available on Opensuse Leap 15.x?

One of the most frustrating things that may happen to you is that you think everything you changed works now and then – after a system restart – you find a mess of non-starting or working services again. Well, this is exactly what happens if you just place a CA’s certificate (pem) file into the location “/etc/ssl/certs”. Just try a reboot; you will find that the file /etc/ssl/certs/anraconc-CA.pem” does not start any more afterwards – with severe consequences for the services referring to it.

“/etc/ssl/certs” is in so far a reasonable central directory as legacy applications may read it for CA certificates. So, one would use it also for our TLS/SSL-dependent server services. Especially, because you may really find it as a default in some configuration files.

The location “/etc/ssl/certs” actually is a link to “/var/lib/ca-certificates/pem” which will not help much as the contents of this directory is refreshed after each system restart, too. I was too lazy to analyze this in detail. However, you find some information in the scripts under “/usr/lib/ca-certificates/update.d/“.

Another substantial piece of information is provided by the the answer to a related question at “Stack Exchange” : how-do-i-install-a-system-wide-ssl-certificate-on-opensuse.

Here, as well as in one of the “update.d”-files, the directory “/etc/pki/trust/anchors” is mentioned as a suitable place to save CA certificate files by the admin for system wide usage. So, we may think that it is enough to copy our CA pem file into the directory “/etc/pki/trust/anchors/“.

Before you get frustrated again: The “trust”-program which among other things refreshes “/etc/ssl/certs” is intelligent:
It extracts the “Common Name” from the certificate and uses it to name the pem-file which it writes at system start into “/etc/ssl/certs”.

So, here are the rules if all your SSL-based services shall be configured to read your trusted CA certificate at “/etc/ssl/certs”:

  1. Place your CA’s certificate file (as exported from TinyCA2) into “/etc/pki/trust/anchors” (and if you have sub-CAs also their certificate files!)
  2. Then refer to the file “/etc/ssl/certs/CAs_COMMON_NAME.pem” – where CAs_COMMON_NAM is the common name you used when you set up your CA. Do not use any other name you may originally have given your exported CA certificate (pem) files.

In our case we need the file name “anraconc-CA.pem”. So, this is already consistent with the name which we chose at export time in the first article. However, this happened by chance, only. We could have chosen quite a different name for the pem-file. (Well, I knew about the pitfall 🙂 )

If you had given your file a name like “myCA-cacert.pem”, you would experience some trouble after having placed it into “/etc/pki/trust/anchors” and referred to it in CA chain configuration settings for any service by “/etc/ssl/certs/myCA-cacert.pem”. Despite the files name “myCA-cacert.pem” it would in our case appear in “/etc/ssl/certs” with the name “anraconc-CA.pem”. It took me a little while to figure this out !

SSL-reconfiguration for OpenLDAP and missing rights for the system user “ldap”

After we have made our CA certificate permanent, we proceed to the reconfiguration of the OpenLDAP service. This is a bit more complicated due to two reasons: There are potentially more configuration files to take care of and there may appear a problem with read rights. In addition you have to think of the “sssd.service” for providing encrypted connections to clients for authentication services – here for LDAP-clients.

The first point depends a bit on your specific configuration. There may be a file “/etc/ldap.conf” (controlling local LDAP-clients). In my case I had to change the entry for “tls_cacertfile“:

bind_policy soft
uri ldap://myserv.anraconc.de
base dc=anraconc,dc=de
nss_map_attribute uniqueMember member
ssl start_tls
pam_password exop
pam_filter objectClass=posixAccount
tls_cacertdir /etc/ssl/certs
tls_cacertfile /etc/ssl/certs/anraconc-CA.pem
....
...

However, your main configuration will probably reside in “/etc/openldap/”. There is also a “/etc/openldap/ldap.conf“, which we need to modify:

tls_cacert      /etc/ssl/certs/anraconc-CA.pem

Then we have in addition the central file “slapd.conf” which must get proper TLS/SSL entries :

...
TLSCACertificateFile /etc/ssl/certs/anraconc-CA.pem
TLSCertificateFile /etc/ssl/servercerts/servercert.pem
TLSCertificateKeyFile /etc/ssl/servercerts/serverkey.pem
...

Hint: On Opensuse systems the file “/etc/sysconfig/openldap” should also contain a line:

...
OPENLDAP_START_LDAP="yes"
...
## Type:           yesno
## Default:        no
## ServiceRestart: ldap
# If set to "yes" the "ldap over ssl" feature of slapd will be enabled. Don't
# forget to add the "TLSCertificateFile" and "TLSCertificateKeyFile" options 
# to the /etc/openldap/slapd.conf (man slapd.conf).
# Note: Don't confuse this with "START_TLS", the preferred method for 
#       making encrypted LDAP connections, which is enabled as soon as You
#       specify "TLSCertificateFile" and "TLSCertificateKeyFile" in your config
#       file
#
OPENLDAP_START_LDAPS="yes"
...

But setting the right value for “TLSCACertificateFile” in “/etc/openldap/ldap.conf” is not enough:

The SSL settings also play a decisive role in the file “cn=config.ldif” (in “/etc/openldap/slapd.d/”) as the core of modern LDAP services is configured by ldif-files.

Warning:
When editing the file “cn= config.ldif” file you have to be extremely careful. Make a backup first! One normally should not edit this file directly!. But as our LDAP service is not running any more we are brave and use

myserv:/etc/openldap/slapd.d # vi cn\=config.ldif

Note the escaping backslash. Then you edit the following entries

...
olcTLSCACertificateFile: /etc/ssl/certs/anraconc-CA.pem
olcTLSCertificateFile: /etc/ssl/servercerts/servercert.pem
olcTLSCertificateKeyFile: /etc/ssl/servercerts/serverkey.pem
....

This may afterwards lead to some warnings in log files regarding the checksum for this file. You could correct this later on by using “ldapmodify” to reedit the entries again on the then (hopefully) running LDAP-server.

Unfortunately, a service restart leads to trouble:

myserv:/etc/openldap/slapd.d # rcslapd restart
Job for slapd.service failed because the control process exited with error code.
See "systemctl  status slapd.service" and "journalctl  -xe" for details.

myserv:/etc/openldap/slapd.d # rcslapd status
● slapd.service - OpenLDAP Server Daemon
   Loaded: loaded (/usr/lib/systemd/system/slapd.service; enabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since Sat 2019-07-20 16:45:37 CEST; 45s ago
  Process: 13254 ExecStart=/usr/lib/openldap/start (code=exited, status=1/FAILURE)
 Main PID: 11608 (code=exited, status=0/SUCCESS)

Jul 20 16:45:37 myserv slapd[13254]: main: TLS init def ctx failed: -1
Jul 20 16:45:37 myserv slapd[13254]: slapd stopped.
Jul 20 16:45:37 myserv slapd[13254]: connections_destroy: nothing to destroy.
Jul 20 16:45:37 myserv start[13254]: Starting ldap-server
Jul 20 16:45:37 myserv systemd[1]: slapd.service: Control process exited, code=exited status=1
Jul 20 16:45:37 myserv systemd[1]: Failed to start OpenLDAP Server Daemon.
Jul 20 16:45:37 myserv systemd[1]: slapd.service: Unit entered failed state.
Jul 20 16:45:37 myserv systemd[1]: slapd.service: Failed with result 'exit-code'.

You see the message in the middle? main: TLS init def ctx failed: -1

Now, you could google. It will not help much! It took me some time to find out that I simply had a rights problem! I saw this when comparing the old contents of /etc/ssl/servercerts” from a backup with the new one:

myserv:/etc/ssl # la servercerts.orig
total 16
drwxr-xr-x  2 root root 4096 May 30  2013 .
drwxr-xr-x  7 root root 4096 Jul 20 15:03 ..
-rw-r--r--  1 root root 2155 Jul 10  2017 servercert.pem
-rw-------+ 1 root root 3272 Jul 10  2017 serverkey.pem
myserv:/etc/ssl # la servercerts
total 16
drwxr-xr-x 2 root root 4096 Jul 20 16:40 .
drwxr-xr-x 7 root root 4096 Jul 20 15:03 ..
-rw-r--r-- 1 root root 2492 Jul 20 15:19 servercert.pem
-rw------- 1 root root 3243 Jul 20 15:22 serverkey.pem

You see the tiny difference? The “+” – sign in the original rights?
Oops! ACL-settings? What for?

myserv:/etc/ssl # getfacl servercerts.orig/serverkey.pem 
# file: servercerts.orig/serverkey.pem
# owner: root
# group: root
user::rw-
user:ldap:r--
group::r--
mask::r--
other::---

OK! lets try this for the user “ldap” in the new setup:

 
myserv:/etc/ssl # setfacl -m u:ldap:r servercerts/serverkey.pem 
myserv:/etc/ssl # setfacl -m g::- servercerts/serverkey.pem
myserv:/etc/ssl # getfacl servercerts/serverkey.pem 
# file: servercerts/serverkey.pem
# file: servercerts/serverkey.pem
# owner: root
# group: root
user::rw-
user:ldap:r--
group::---
group:root:---
mask::r--
other::---

myserv:/etc/ssl # systemctl restart slapd.service
myserv:/etc/ssl # systemctl status slapd.service
● slapd.service - OpenLDAP Server Daemon
   Loaded: loaded (/usr/lib/systemd/system/slapd.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2019-07-20 17:00:21 CEST; 5s ago
  Process: 15869 ExecStart=/usr/lib/openldap/start (code=exited, status=0/SUCCESS)
 Main PID: 15889 (slapd)
    Tasks: 3 (limit: 4915)
   CGroup: /system.slice/slapd.service
           └─15889 /usr/sbin/slapd -h ldap:/// ldaps:/// 
ldapi:/// -F /etc/openldap/slapd.d -u ldap -g ldap -o slp=off

Jul 20 17:00:21 myserv systemd[1]: Stopped OpenLDAP Server Daemon.
Jul 20 17:00:21 myserv systemd[1]: Starting OpenLDAP Server Daemon...
Jul 20 17:00:21 myserv slapd[15869]: @(#) $OpenLDAP: slapd 2.4.46 $
                                          opensuse-buildservice@opensuse.org
Jul 20 17:00:21 myserv slapd[15869]: ldif_read_file: checksum error on "/etc/openldap/slapd.d/cn=config.ldif"
Jul 20 17:00:21 myserv slapd[15869]: ldif_read_file: checksum error on "/etc/openldap/slapd.d/cn=config/olcDatabase={0}config.ldif"
Jul 20 17:00:21 myserv slapd[15889]: slapd starting
Jul 20 17:00:21 myserv start[15869]: Starting ldap-server
Jul 20 17:00:21 myserv systemd[1]: Started OpenLDAP Server Daemon.
myserv:/etc/ssl # 

Obviously, the user “ldap” needs read rights on the (private) key of the server certificate!
Note that the user which runs the slapd.service may have a different name on your system – e.g. “openldap”.

One can dispute whether ACLs is a reasonable way to handle this problem. Of course you could try and do something else. For other services I found in backups for older SuSE installations a special group “tls” which contained root and system users which needed read rights. This group was then assigned to “/etc/ssl/servercerts/serverkey.pem”.

E.g. in case you are concerned about any of these solutions you could create a separate special certificate for the LDAP service and place the key in a special directory with read access rights for the file limited to root and the user “ldap”. Of course, in this case, the service’s configuration files must be adjusted for all TLS/SSL relevant data. However, before you follow such an approach of different certificates for services on one and the same server, think a bit about side consequences. As the FQDN of the server has to be identical to the certificate’s common name you would have to issue certificates for different common names of your various server services.
This in turn makes your network and DNS configuration more complicated – you either need to associate one IP with multiple FQDNs or provide multiple IPs for one and the same server. To avoid such trouble I would rather combine this with a container approach for each separate service.

Adjusting the configuration of the SSSD-service

Having a running LDAP service does not mean that external clients can access it. On modern systems the exchange of auth-information between clients and server services is often handled by the “sssd”-service. This is true in my case, too. Therefore, a running slapd will not be sufficient if we use the LDAP-service for authentication from some clients in the network. We need to adjust the sssd-configuration, too. The relevant file is “/etc/sssd/sssd.conf” :

...
[sssd]
config_file_version = 2
services = nss,pam
domains = default
# SSSD will not start if you do not configure any domains.
# Add new domain configurations as [domain/<NAME>] sections, and
[nss]
filter_groups = root
filter_users = root
[pam]
# Section created by YaST
[domain/default]
ldap_uri = ldap://myserv.anraconc.de
ldap_search_base = dc=anraconc,dc=de
ldap_schema = rfc2307bis
id_provider = ldap
ldap_user_uuid = entryuuid
ldap_group_uuid = entryuuid
;ldap_id_use_start_tls = True
ldap_id_use_start_tls = False
enumerate = True
chpass_provider = ldap
auth_provider = ldap
cache_credentials = False

ldap_tls_cacertdir = /etc/ssl/certs
ldap_tls_cacert = /etc/ssl/certs/anraconc-CA.pem
....
...

Again, the most important settings are done in the last 2 lines displayed.
The setting for start_tls is up to you. If you use “start_tls” then the OpenLDAP configuration must provide the necessary entries.

Note: You have to provide similar sssd-settings on external LDAP-client-systems! One such client could be an email/imap-server – we shall have a look at its configuration in the next article.

On “myserv” we restart the “sssd.service”:

myserv:/etc/ssl # vi /etc/sssd/sssd.conf
myserv:/etc/ssl # rcsssd restart
myserv:/etc/ssl # systemctl status sssd.service 
● sssd.service - System Security Services Daemon
   Loaded: loaded (/usr/lib/systemd/system/sssd.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2019-07-20 17:29:11 CEST; 18s ago
 Main PID: 20021 (sssd)
    Tasks: 4 (limit: 4915)
   CGroup: /system.slice/sssd.service
           ├─20021 /usr/sbin/sssd -i --logger=files
           ├─20022 /usr/lib/sssd/sssd_be --domain default --uid 0 --gid 0 --logger=files
           ├─20023 /usr/lib/sssd/sssd_nss --uid 0 --gid 0 --logger=files
           └─20024 /usr/lib/sssd/sssd_pam --uid 0 --gid 0 --logger=files

Jul 20 17:29:10 myserv systemd[1]: Starting System Security Services Daemon...
Jul 20 17:29:10 myserv sssd[20021]: Starting up
Jul 20 17:29:11 myserv sssd[be[20022]: Starting up
Jul 20 17:29:11 myserv sssd[20024]: Starting up
Jul 20 17:29:11 myserv sssd[20023]: Starting up
Jul 20 17:29:11 myserv systemd[1]: Started System Security Services Daemon.

Conclusion

We can use TinyCA2 to replace the missing YaST-feature for an effective administration both of CAs and server certificates. The major work has to be done in adjusting the configuration of the services. But after the method for installing a CA certificate server wide and permanently became clear the service configuration became reduced to a more or less dumb editing job. This job could be delegated to a script; but be careful to check the specific names of the relevant SSL/TLS entries for each service!

A special challenge came with the LDAP service; the related system user must get read rights to the used server certificate’s private key!

In the next and final article of this series

TinyCA2 as a replacement for YaST’s CA-tools on Opensuse Leap servers with TLS/SSL – III

we shall have a look at the reconfiguration of a cyrus and posfix service on a different server “mymail”, which would then be a client for the LDAP service on “myserv” (for the authentication of IMAP/SMTP-users).

Links

Server wide and permanent installation of a trusted CA’s certificate
stackexchange.com: how-do-i-install-a-system-wide-ssl-certificate-on-opensuse

 

Upgrade OpenLDAP-Server unter Opensuse auf Leap 42.2 – Fehler – OLC-Konfiguration für Datenbank Backends

Heute bin ich endlich eine Aufgabe angegangen, dass ich schon seit einem Jahr vor mir her schiebe: Ich habe einen LDAP-Server, der noch unter Opensuse 13.1 lief auf Opensuse Leap 42.2 umgestellt.

Die Umstellung habe ich schrittweise abgewickelt : OS 13.1 => OS 13.2 => Leap 42.1 => Leap 42.2. Beschreibungen eines generellen Upgrade-Vorgehensmodell auf Basis von “zypper” für Opensuse finden sich hier:

https://www.unixmen.com/upgrade-opensuse-13-2-opensuse-13-1/
https://www.unixmen.com/how-to-upgrade-to-opensuse-42-1-from-opensuse-13-2/
http://www.2daygeek.com/how-to-upgrade-from-opensuse-leap-42-1-to-opensuse-leap-42-2/2/

Die Paket-Updates liefen (bis auf bekannte Kleinigkeiten) eigentlich ganz gut ab; jede neue erzielte Opensuse-Version konnte erfolgreich gebootet werden. Auch praktisch alle Services liefen – mit Ausnahme eines bekannten Apache-Problems, das nach den Updates ein Eingreifen in bestimmte Konfigurationseinstellungen erfordert. Und eben auch bis auf den LDAP-Service; nach dem letzten Update musste ich schnell zur Kenntnis nehmen, dass es da ein gravierendes Problem gab.

Nach Upgrade zu Leap 42.2 war kein Login mehr auf anderen Servern möglich

Nach dem Übergang von Leap 42.1 zu Leap 42.2 konnte ich mich mit definierten UIDs (außer root) nicht mehr auf Server-Systemen in unserem LAN einloggen. Praktisch alle unsere Server beziehen Authentifizierungsinformationen eben vom zwischenzeitlich upgegradeten OpenLDAP-Server.

Die Authentifizierung läuft dabei über eine Kombination aus SSSD-Services und OpenLDAP (unter TLS). Zunächst dachte ich deshalb, dass ggf. der SSSD-Dämon auf dem OpenLDAP Server nicht laufen würde. Der erfreute sich aber selbst nach den drei Updates bester Gesundheit:

serv:~ # rcsssd status
● sssd.service - System Security Services Daemon
   Loaded: loaded (/usr/lib/systemd/system/sssd.service; enabled; vendor preset: disabled)
   Active: active (running) since Thu 2017-06-01 15:21:30 CEST; 1h 9min ago
  Process: 1249 ExecStart=/usr/sbin/sssd -D -f (code=exited, status=0/SUCCESS)
 Main PID: 1294 (sssd)
    Tasks: 4 (limit: 512)
   CGroup: /system.slice/sssd.service
           ├─1294 /usr/sbin/sssd -D -f
           ├─1297 /usr/lib/sssd/sssd_be --domain default --uid 0 --gid 0 --debug-to-files
           ├─1298 /usr/lib/sssd/sssd_nss --uid 0 --gid 0 --debug-to-files
           └─1299 /usr/lib/sssd/sssd_pam --uid 0 --gid 0 --debug-to-files

Jun 01 15:21:27 serv systemd[1]: Starting System Security Services Daemon...
Jun 01 15:21:29 serv sssd[1294]: Starting up
Jun 01 15:21:29 serv sssd[be[1297]: Starting up
Jun 01 15:21:29 serv sssd[1299]: Starting up
Jun 01 15:21:29 serv sssd[1298]: Starting up
Jun 01 15:21:30 serv systemd[1]: Started System Security Services Daemon.

Vom OpenLDAP-Service ließ sich das dagegen nicht behaupten; so zeigte ein Blick in das systemd Journal mittels
“journalctl -xe” :

Jun 01 15:48:17 serv systemd[1]: Starting OpenLDAP Server Daemon...
-- Subject: Unit slapd.service has begun start-up
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
-- 
-- Unit slapd.service has begun starting up.
Jun 01 15:48:17 serv slapd[15835]: @(#) $OpenLDAP: slapd 2.4.44 $
                                          opensuse-buildservice@opensuse.org
Jun 01 15:48:17 serv slapd[15835]: UNKNOWN attributeDescription "OLCDBCACHESIZE" inserted.
Jun 01 15:48:17 serv slapd[15835]: UNKNOWN attributeDescription "OLCDBCHECKPOINT" inserted.
Jun 01 15:48:17 serv slapd[15835]
: UNKNOWN attributeDescription "OLCDBCONFIG" inserted.
Jun 01 15:48:17 serv slapd[15835]: UNKNOWN attributeDescription "OLCDBIDLCACHESIZE" inserted.
Jun 01 15:48:17 serv slapd[15835]: UNKNOWN attributeDescription "OLCDBINDEX" inserted.
Jun 01 15:48:17 serv slapd[15835]: config error processing olcDatabase={1}hdb,cn=config:
Jun 01 15:48:17 serv slapd[15835]: DIGEST-MD5 common mech free
Jun 01 15:48:17 serv slapd[15835]: slapd stopped.
Jun 01 15:48:17 serv slapd[15835]: connections_destroy: nothing to destroy.
Jun 01 15:48:17 serv start[15835]: Starting ldap-server
Jun 01 15:48:17 serv systemd[1]: slapd.service: Control process exited, code=exited status=1
Jun 01 15:48:17 serv systemd[1]: Failed to start OpenLDAP Server Daemon.
-- Subject: Unit slapd.service has failed
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
-- 
-- Unit slapd.service has failed.
-- 
-- The result is failed.
Jun 01 15:48:17 serv systemd[1]: slapd.service: Unit entered failed state.
Jun 01 15:48:17 serv systemd[1]: slapd.service: Failed with result 'exit-code'.

Auch ein manueller Start von OpenLDAP mittels

serv:/etc/openldap/slapd.d # /usr/sbin/slapd -u ldap -h ldap://127.0.0.1:389/ -d 256

lieferte die gleichen Fehlermeldungen. Der Grund für die fehlgeschlagenen Logins lag also schlicht darin, dass ausgerechnet der OpenLDAP-Service, über den in unserem LAN User und Gruppen verwaltet werden, nach den Upgrades – genauer: nach dem letzten Upgrade – nicht mehr lief.

Eigenschaften der LDAP “Datenbank Backends” wurden offenbar nicht erkannt

Die Fehlermeldungen deuteten an, dass Eigenschaften des eingesetzten Datenbank-Backends (in meinem Fall hdb) dem System nicht bekannt waren. Daraus ergibt sich die Frage: Weiß die neue OpenLDAP-Installation unter Laep 42.2 überhaupt irgendetwas von ihren Backends?

Wenn man sich ein wenig mit LDAP beschäftigt hat, hat man sicher mitbekommen, dass die Datenbank-Backends in neueren OpenLDAP-Versionen (wie andere LDAP-Komponenten auch) über Module geladen und konfiguriert werden können. In früheren Versionen haben dagegen Build-Optionen bei der Erzeugung der LDAP-Programme dafür gesorgt, dass diverse Backends von Haus verfügbar waren. Einträge in der “slapd.conf” dienten dann der Auswahl der konkret heranzuziehenden Datenbank-Variante.

Man kann Backends aber eben auch dynamisch nachladen. Typischerweise sollte das in der Grundkonfiguration von OpenLDAP geschehen; was wenn das aber unter Leap 42.2 nicht der Fall ist?

Mit ein wenig Recherche im Internet findet man genügend Hinweise, wie man Datenbank-Backend-Module lädt und dass das tatsächlich in etlichen Installationen der Fall ist: Siehe etwa

http://vaab.blog.kal.fr/2010/03/06/how-to-add-a-schema-in-openldap-24/
(siehe dort den Abschnitt (“How to add a database?”)).

https://www.digitalocean.com/community/tutorials/how-to-configure-openldap-and-perform-administrative-ldap-tasks
http://nodedirector.bigsister.ch/refdoc/group__ref__cfg–director__slapd__conf.html
https://github.com/yast/yast-auth-server/blob/master/package/yast2-auth-server.changes
https://cat.pdx.edu/~nibz/openldap/openldap-server.html
und
http://www.openldap.org/doc/admin24/backends.html
http://www.openldap.org/doc/admin24/
slapdconf2.html

Im letzteren Artikel siehe insbesondere Absatz 5.2.2.

Die genannten Artikel deuten an, dass man die Direktive “olcModuleLoad” in der sogenannten OLC-Grundkonfiguration des LDAP-Servers einsetzen soll.

Dass in meiner aktuellen LDAP-Konfiguration tatsächlich Module geladen werden, zeigte folgender Befehl:

  
serv:/etc/openldap/slapd.d # grep -r ModuleLoad .
./cn=config/cn=module{0}.ldif:olcModuleLoad: {0}back_monitor.la

Leider handelt es sich hier aber nicht um ein Datenbank-Backend-Modul! Die nächste Frage war also: Welche Datenbank-Module werden denn überhaupt benutzt?

  
serv:/etc/openldap/slapd.d/cn=config # grep -r olcDatabase .
./olcDatabase={2}monitor.ldif:dn: olcDatabase={2}Monitor
./olcDatabase={2}monitor.ldif:objectClass: olcDatabaseConfig
./olcDatabase={2}monitor.ldif:olcDatabase: {2}Monitor
./olcDatabase={-1}frontend.ldif:dn: olcDatabase={-1}frontend
./olcDatabase={-1}frontend.ldif:objectClass: olcDatabaseConfig
./olcDatabase={-1}frontend.ldif:olcDatabase: {-1}frontend
./olcDatabase={-1}frontend.ldif:structuralObjectClass: olcDatabaseConfig
./olcDatabase={0}config.ldif:dn: olcDatabase={0}config
./olcDatabase={0}config.ldif:objectClass: olcDatabaseConfig
./olcDatabase={0}config.ldif:olcDatabase: {0}config
./olcDatabase={0}config.ldif:structuralObjectClass: olcDatabaseConfig
./olcDatabase={1}hdb.ldif:dn: olcDatabase={1}hdb
./olcDatabase={1}hdb.ldif:objectClass: olcDatabaseConfig
./olcDatabase={1}hdb.ldif:olcDatabase: {1}hdb

Aha, ich hatte die LDAP-Datenbanken bei der ursprünglichen Servereinrichtung unter OS 13.1 offenbar als “hdb”-Banken aufgesetzt. Es lag daher nahe, mal versuchsweise das entsprechende Backend-Modul zu laden.

Ergänzungen in slapd.conf sind nicht hinreichend, wenn zur Konfiguration OLC [cn=config] benutzt wird

Dummerweise bin ich bei den Recherchen dann aber auch über folgenden Ratschlag gestolpert:

https://forums.opensuse.org/showthread.php/522385-SlapD-will-nach-Update-von-42-1-nicht-mehr?p=2817944#post2817944

Dem bin ich dann naiverweise gefolgt – und habe zunächst lediglich die “slapd.conf” so ergänzt, dass alle Backends geladen werden:

# Load backend modules such as database engines
modulepath /usr/lib64/openldap
moduleload back_mdb.la
moduleload back_hdb.la
moduleload back_bdb.la

Das reichte in meinem Fall natürlich aber nicht ! Warum? Ich hatte die LDAP-Konfiguration beim Aufsetzen des LDAP-Servers unter Opensuse 13.1 mittels OLC, also über Einträge unter “cn=config“, vorgenommen! (Für weniger LDAP-Kundige: Die Konfigurationseinträge unter OLC sind ganz im Stil von LDAP-Datenbank-Records gehalten.)

Unter Opensuse wird die Verwendung der sog. Online-[OLC]-Konfiguration des OpenLDAP-Servers in der Datei “/etc/sysconfig/openldap” über die Option

OPENLDAP_CONFIG_BACKEND= “files|ldap”

festgelegt. In meinem Fall:

OPENLDAP_CONFIG_BACKEND=”ldap”

Das steuert dann den Aufruf des LDAP-Services und den Start des zugehörigen Programms. Letzteres wird dann die Konfigurationseinstellungen unter dem Verzeichnis “/etc/openldap/slapd.d/cn=config” auslesen und zur Anwendung bringen.

Die OLC-Konfiguration des OpenLDAP-Servers kann selbst über LDIF-Dateien oder LDAP-CLI-Kommandos (“ldapadd”, “ldapmodify”) angepasst werden. Damit werden dann die Einträge unter “cn=config” passend modifiziert.

Die notwendige initiale Datenbank-Konfiguration beim Starten des LDAP-Servers erfolgt unter dem Verzeichnis “cn=config” übrigens über folgende LDIF-Datei:

/etc/
openldap/slapd.d/cn=config/olcDatabase\=\{0\}config.ldif

Eine andere Stelle, die grundsätzlich auch für das Laden von Modulen mit Hilfe von “olcLoadModule”-Statements in Frage käme, wäre die grundlegende Konfigurationsdatei für Module:

/etc/openldap/slapd.d/cn=config/cn=module{0}.ldif

Sie hat in meinem Fall den Inhalt:

# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
# CRC32 5b49ffc3
dn: cn=module{0}
objectClass: olcModuleList
cn: module
cn: module{0}
structuralObjectClass: olcModuleList
entryUUID: 49b0aac8-614a-1032-8c55-83b54eef05ad
creatorsName: cn=config
createTimestamp: 20130604100720Z
olcModuleLoad: {0}back_monitor.la
entryCSN: 20130604100720.232512Z#000000#000#000000
modifiersName: cn=config
modifyTimestamp: 20130604100720Z

Ein möglicher Weg zur Ergänzung von Statements, mit denen man alle üblichen Datenbank-Module laden würde, sähe hierfür in etwa so aus:

serv:/etc/openldap/slapd.d # ldapadd -Y EXTERNAL -H ldapi:///
dn: cn=module{0},cn=config
objectClass: olcModuleList
cn: module{0}
olcModulePath: /usr/lib64/openldap
olcModuleLoad: back_bdb.la
olcModuleLoad: back_hdb.la
olcModuleLoad: back_mdb.la          

Würde das im vorliegenden Fehlerfall funktionieren? Natürlich nicht – der OpenLDAP-Server läuft ja überhaupt nicht und ein “ldapadd”-Befehl könnte deshalb gar nicht umgesetzt werden!

Direktes Editieren der Konfiguration?

Manche mutige Zeitgenossen wagen es bei kleineren Änderungen (und nach einem vorherigen Sicherheits-Backup der LDAP-Konfiguration), die Einträge in den LDIF-Dateien unter dem Verzeichnis “/etc/openldap/slapd.d/cn=config” auch direkt über Editor-Befehle zu modifizieren. An dieser Stelle muss allerdings gesagt werden, dass die offiziellen OpenLDAP Aministrationshandbücher davon streng abraten. Na ja …

In meinem Fall war eigentlich nur eine Ergänzung erforderlich (s.o.). Ich verhielt mich also mutig; nach einem

serv:/etc/openldap/slapd.d/cn=config # vi olcDatabase\=\{0\}config.ldif 

habe ich die folgende Zeile in der genannten Datei hinzugefügt:

olcModuleLoad: {0}back_hdb

Insgesamt sieht die entsprechende Konfigurationsdatei “olcDatabase\=\{0\}config.ldif” nun so aus:

# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
# CRC32 a4b13d6e
dn: olcDatabase={0}config
objectClass: olcDatabaseConfig
olcDatabase: {0}config
olcRootDN: cn=config
structuralObjectClass: olcDatabaseConfig
entryUUID: 14a9819c-624a-1032-8687-49710846e729
creatorsName: cn=config
createTimestamp: 20130604100551Z
entryCSN: 20130604100551.266001Z#000000#000#000000
modifiersName: cn=config
modifyTimestamp: 20130604100551Z
olcModuleLoad: {0}back_hdb

Man sieht nebenbei: Mein OpenLDAP-Server ist schon was älter. Nach der obigen Modifikation lief und läuft er jedoch auch unter Leap 42.2 wieder und verrichtet nun erneut seinen wichtigen Dienst im Netz:

serv:/etc/openldap/slapd.d/cn=config # systemctl start slapd.service 
serv:/etc/openldap/slapd.d/cn=config # systemctl status slapd.service 
● slapd.service - OpenLDAP Server Daemon
   Loaded: loaded (/usr/lib/systemd/system/slapd.service; enabled; vendor preset: disabled)
   Active: active (running) since Thu 2017-06-01 16:32:38 CEST; 2h 28min ago
  Process: 2632 ExecStart=/usr/lib/openldap/start (code=exited, status=0/SUCCESS)
 Main PID: 2735 (slapd)
    Tasks: 5 (limit: 512)
   CGroup: /system.slice/slapd.service
           └─2735 /usr/sbin/slapd -h ldap:/// ldaps:/// ldapi:/// -F /etc/openldap/slapd.d -u ldap -g ldap -o slp=off

Jun 01 19:00:25 serv slapd[2735]: conn=1304 op=37 SEARCH RESULT tag=101 err=0 nentries=0 text=
Jun 01 19:00:49 serv slapd[2735]: conn=1325 op=6 SRCH base="dc=superduper,dc=de" scope=2 deref=0 filter="(&(
objectClass=posixAccount)(uid=*)(uidNumber=*)(gidNumber=*))"
Jun 01 19:00:49 serv slapd[2735]: conn=1325 op=6 SRCH attr=objectClass uid userPassword uidNumber gidNumber gecos homeDirectory loginShell krbPrincipalName cn memberOf entryuuid modi...
Jun 01 19:00:49 serv slapd[2735]: conn=1325 op=6 SEARCH RESULT tag=101 err=0 nentries=5 text=
Jun 01 19:00:50 serv slapd[2735]: conn=1325 op=7 SRCH base="dc=superduper,dc=de" scope=2 deref=0 filter="(&(objectClass=posixGroup)(cn=*)(&(gidNumber=*)(!(gidNumber=0))))"
Jun 01 19:00:50 serv slapd[2735]: conn=1325 op=7 SRCH attr=objectClass cn userPassword gidNumber member entryuuid modifyTimestamp modifyTimestamp
Jun 01 19:00:50 serv slapd[2735]: conn=1325 op=7 SEARCH RESULT tag=101 err=0 nentries=0 text=
Jun 01 19:00:50 serv slapd[2735]: conn=1325 op=8 SRCH base="dc=superduper,dc=de" scope=2 deref=0 filter="(&(objectClass=ipService)(cn=*)(ipServicePort=*)(ipServiceProtocol=*))"
Jun 01 19:00:50 serv slapd[2735]: conn=1325 op=8 SRCH attr=objectClass cn ipServicePort ipServiceProtocol modifyTimestamp
Jun 01 19:00:50 serv slapd[2735]: conn=1325 op=8 SEARCH RESULT tag=101 err=0 nentries=0 text=
Hint: Some lines were ellipsized, use -l to show in full.

Ich rate dennoch zur Vorsicht! Wer lieber nicht mutig sein will und eher einen sauberen Weg bevorzugt, findet einen alternativen Vorschlag in den Diskussionsbeiträgen unter folgender Bug-Meldung:
https://bugzilla.opensuse.org/show_bug.cgi?id=1011582.

Viel Spass mit OpenLDAP unter Opensuse Leap 42.2 !