When monitoring LDAP servers, one very common way is to use the check_ldap plugin from either nagios-plugins or monitoring-plugins projects. This plugin works for both LDAP and encrypted LDAPS.
However when using LDAPS, you might run into connection issue due to the server certificate.
Monitoring a LDAPS server is straight forward, especially if you have been using check_ldap in the past for LDAP servers. The additional arguments -T (for using a STARTTLS connection) and -p 636 (for using the LDAPS port) should usually be enough for a change.
ck@icinga:~$ /usr/lib/nagios/plugins/check_ldap -H ldap.example.com -T -p 636 -3 -b "OU=Users,dc=example,dc=com" -D "CN=Service Account Icinga,OU=Service Accounts,OU=Users,DC=example,DC=com" -P "secret"
LDAP OK - 0.025 seconds response time|time=0.024745s;;;0.000000
To take the command apart:
Another possibility is to use the -U parameter to connect to a LDAP server using an URL format:
ck@icinga:~$ /usr/lib/nagios/plugins/check_ldap -U ldaps://ldap.example.com -T -p 636 -3 -b "OU=Users,dc=example,dc=com" -D
"CN=Service Account Icinga,OU=Service
Accounts,OU=Users,DC=example,DC=com" -P "secret"
LDAP OK - 0.033 seconds response time|time=0.033222s;;;0.000000
Note: The -U parameter is currently only available in check_ldap from the nagios-plugins project.
Both ways (using -H or -U) used a FQDN hostname. Why this is important? We'll see right away...
In many Nagios/Icinga monitoring environments, checks are executed against the IP addresses of the servers ($HOSTADDRESS$ in Nagios or $host.address$ in Icinga2).
The Icinga2 ITL documentation for the "ldap" command also mentions that vars.ldap_address defaults to the server's address:
ldap_address Optional. Host name, IP Address, or unix socket (must be an absolute path). Defaults to “$address$” if the host’s address attribute is set, “$address6$” otherwise.
Using the LDAP servers IP address works fine to check LDAP:
ck@icinga:~$ /usr/lib/nagios/plugins/check_ldap -H 192.168.0.100 -3 -b "OU=Users,dc=example,dc=com" -D
"CN=Service Account Icinga,OU=Service
Accounts,OU=Users,DC=example,DC=com" -P "secret"
LDAP OK - 0.012 seconds response time|time=0.011560s;;;0.000000
But the check does not work for LDAPS:
ck@icinga:~$ /usr/lib/nagios/plugins/check_ldap -H 192.168.0.100 -T -p636 -3 -b "OU=Users,dc=example,dc=com" -D
"CN=Service Account Icinga,OU=Service
Accounts,OU=Users,DC=example,DC=com" -P "secret"
Could not bind to the LDAP server
The following systems architecture drawing shows such a situation, where a HAProxy is placed in front of multiple LDAP servers, serving the LDAPS certificate:
The reason behind it is not obvious at all (and the plugin won't tell it either). The LDAP connection fails because the LDAPs certificate was issued for "ldap.example.com" - yet the communication connects to the IP address. The LDAPS certificate therefore does not match the requested hostname.
A similar "problem" happens on HTTPS connection. But check_http solves this nicely with the possibility to combine -I (for the HTTP server's IP address) and -H (for sending a HTTP Host Header).
Unfortunately there is no such (IP address) parameter available in check_ldap.
"Let's fix the check_ldap plugin!" That was my first thought and wouldn't have been my first contribution in the nagios-plugins or monitoring-plugins project. However I quickly became to realize, that the OpenLDAP C library (which is used by check_ldap) does not allow a "mix" of LDAP IP and LDAP Hostname:
check_ldap uses ldap_init, ldap_open and ldap_initialize (for the LDAP URL style in the nagios-plugins project). Neither of them support multiple arguments:
OpenLDAP LDAP (libldap, -lldap)
#include <ldap.h>
LDAP *ldap_open(host, port)
char *host;
int port;
LDAP *ldap_init(host, port)
char *host;
int port;
int ldap_initialize(ldp, uri)
LDAP **ldp;
char *uri;
#include <ldap_pvt.h>
int ldap_init_fd(fd, proto, uri, ldp)
ber_socket_t fd;
int proto;
char *uri;
LDAP **ldp;
I was hoping for optional arguments in one of the functions, something in the style of:
LDAP *ldap_init(host, port [, servername])
char *host;
int port;
char *servername;
But, as far as I can tell from my research, there's currently no way around it with these three LDAP connection functions.
As a potential workaround I looked at the ldap_set_option function, which allows to set LDAP options for a LDAP connection. I saw the option LDAP_OPT_HOST_NAME and wanted to test if this could be set for a connection using an IP address:
/* initialize ldap claudiokuenzler */
printf ("CK Tests\n");
if (ldap_set_option (ld, LDAP_OPT_HOST_NAME, &ld_host) != LDAP_OPT_SUCCESS ) {
printf(_("Could not set host_name %s\n"), ld_host);
return STATE_CRITICAL;
}
else {
printf(_("host_name %s set\n"), ld_host);
}
if (!(ld = ldap_init ("192.168.0.100", ld_port))) {
printf ("Could not connect to the server %s at port %i\n", ld_host, ld_port);
return STATE_CRITICAL;
}
But this would have been too nice for a workaround. Unfortunately this idea sacked:
ck@icinga:~$ ./plugins/check_ldap -H ldap.example.com -p636 -3 -b "OU=Users,dc=example,dc=com" -D
"CN=Service Account Icinga,OU=Service
Accounts,OU=Users,DC=example,DC=com" -P "secret" -T
CK Tests
host_name ldap.example.com set
ldap_bind: Can't contact LDAP server (-1)
additional info: (unknown error code)
Could not bind to the LDAP server
With the current library there really seems no way around this.
Note: If you, dear reader, come up with a solution, let me know or create a pull request in nagios-plugins or monitoring-plugins.
In order to monitor LDAPS servers with check_ldap, you must use the FQDN hostname in either -H or -U, so that the configured LDAPS certificate matches the requested hostname - as mentioned at the beginning of this post.
No comments yet.
AWS Android Ansible Apache Apple Atlassian BSD Backup Bash Bluecoat CMS Chef Cloud Coding Consul Containers CouchDB DB DNS Database Databases Docker ELK Elasticsearch Filebeat FreeBSD Galera Git GlusterFS Grafana Graphics HAProxy HTML Hacks Hardware Icinga Influx Internet Java KVM Kibana Kodi Kubernetes LVM LXC Linux Logstash Mac Macintosh Mail MariaDB Minio MongoDB Monitoring Multimedia MySQL NFS Nagios Network Nginx OSSEC OTRS Office PGSQL PHP Perl Personal PostgreSQL Postgres PowerDNS Proxmox Proxy Python Rancher Rant Redis Roundcube SSL Samba Seafile Security Shell SmartOS Solaris Surveillance Systemd TLS Tomcat Ubuntu Unix VMWare VMware Varnish Virtualization Windows Wireless Wordpress Wyse ZFS Zoneminder