SSL certificate monitoring with Bash


In order to see in the monitoring tool if and when an SSL certificate is due to expire a script was created to determine the expiration date. In comparison to other checks, this script is not limited to checking certificates via HTTPS.

This article provides a description of how the expiration date of an SSL certificate is obtained.

openssl s_client -servername "${HOST}" -connect "${HOST}":"${PORT}" 2>&- | openssl x509 -enddate -noout

In order to establish a connection to an SSL host, an SSL client is required to begin with. Here, the s_client by OpenSSL is used, which can also handle TLS. The s_client is generally used to diagnose and debug SSL/TLS certificates.


The parameter “servername” makes it possible to verify that the correct certificate is used, if a server has multiple SSL certificates via VHosts. This is done via SNI (server name indication).


The connection to the host via the hostname and port is established here.

openssl x509 -enddate -noout

Now, the x509 certificate is read out and the expiration date, which specifies that the certificate is no longer valid after the XY date, is output using the “enddate” and “noout” parameters. The remaining output is prevented by “noout”.

Alarm, alarm!

The objective was to be able to determine independently how and when Nagios / Icinga triggers an alarm. Error code status 2 is required in order for Nagios / Icinga to trigger an alarm. Error codes:

  • 1 – Warning
  • 2 – Critical

0 means OK, of course. Parameters to adjust the warning values and critical values are assigned. Standard values are:

  • Warning=30 (days)
  • Critical=5 (days)

The expiration date is compared with the actual date. This makes it possible to determine how many days remain until the certificate expires.

The monitoring script is available on GitHub.

Integration into monitoring

We implement the script as an Icinga plugin.

Commands are defined in the “/etc/icinga/icinga.cfg” configfile, or a description is provided where they are defined.

The excerpt from the Icinga configuration is shown below:

define command {
    command_name check _ssl
    command_line /bin/bash $USER1$/ -H $ARG1$ -p $ARG2$ -P $ARG3$ -w $ARG4$ -c $ARG5$

The $ARG$ variables are then provided via a service definition, which is included in /etc/icinga/objects/services_icinga.cfg by default.

The SSL check service for a host is defined as follows:

define service {
        use                             template-service
        host_name                       Hostname (e.g.
        service_description             check_ssl
        max_check_attempts              5
        check_interval                  360
        retry_interval                  1
        check_command                   check _ssl!''!'443'!'no_tls'!'30'!'5'

In the check_command line, the $ARG$ variables are separated by exclamation marks and are also assigned in this order afterwards. This means:

  • = $ARG1
  • 443 = $ARG2$
  • no_tls = $ARG3$
  • 30 = $ARG4$
  • 5 = $ARG5$