Table des matières

Surveiller la date d'expiration de vos certificats avec Zabbix

Voilà comment surveiller la date d'expiration des certificats SSL de vos machines avec Zabbix.

Installation des dépendances

yum install perl-DateManip perl-TimeDate

Mise en pale du script de surveillance

Copiez ce script dans le répertoire de scripts Zabbix (défini en tant que ExternalScripts dans la configuration du serveur ou du proxy):

cert_expire.pl
#!/usr/bin/perl -w
# Check peer certificate validity for Zabbix
# Require perl module : IO::Socket, Net::SSLeay, Date::Parse
# Require unix programs : openssl, echo, sendmail
#
# Based on sslexpire from Emmanuel Lacour <elacour@home-dn.net>
#
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2, or (at your option) any
# later version.
#
# This file is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this file; see the file COPYING.  If not, write to the Free
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301, USA.
#
 
 
use strict;
use IO::Socket;
use Net::SSLeay;
use Getopt::Long;
use Date::Parse;
 
Net::SSLeay::SSLeay_add_ssl_algorithms();
Net::SSLeay::randomize();
 
# Default values
my $opensslpath = "/usr/bin/openssl";
my $host = '127.0.0.1';
my $port = '443';
 
my %opts;
GetOptions (\%opts,
    'host|h=s',
    'port|p=s',
    'help',
);
 
if ($opts{'host'}) {
    $host = $opts{'host'};
}
if ($opts{'port'}){
    $port = $opts{'port'};
}
 
if ($opts{'help'}) {
    &usage;
}
 
# Print program usage
sub usage {
    print "Usage: sslexpire [OPTION]...
-h, --host=HOST        check this host
-p, --port=TCPPORT     check this port on the previous host
    --help             print this help, then exit
";
    exit;
}
 
# This will return the expiration date
sub getExpire {
 
    my ($l_host,$l_port) = @_;
    my ($l_expdate,$l_comment);
 
    # Connect to $l_host:$l_port
    my $socket = IO::Socket::INET->new(
        Proto => "tcp",
        PeerAddr => $l_host,
        PeerPort => $l_port
        );
    # If we connected successfully
    if ($socket) {
        # Intiate ssl
        my $l_ctx = Net::SSLeay::CTX_new();
        my $l_ssl = Net::SSLeay::new($l_ctx);
 
        Net::SSLeay::set_fd($l_ssl, fileno($socket));
        my $res = Net::SSLeay::connect($l_ssl);
 
        # Get peer certificate
        my $l_x509 = Net::SSLeay::get_peer_certificate($l_ssl);
        if ($l_x509) {
            my $l_string = Net::SSLeay::PEM_get_string_X509($l_x509);
            # Get the expiration date, using openssl
            $l_expdate = `echo "$l_string" | $opensslpath x509 -enddate -noout 2>&1`;
            $l_expdate =~ s/.*=//;
            chomp($l_expdate);
        }
        else {
            $l_expdate = 1;
        }
 
        # Close and cleanup
        Net::SSLeay::free($l_ssl);
        Net::SSLeay::CTX_free($l_ctx);
        close $socket;
    }
    else {
            $l_expdate = 1;
    }
    return $l_expdate;
}
 
 
# Print remaining days before expiration
sub report {
    # Convert date into epoch using date command
    my ($l_expdate) = @_;
 
    if ($l_expdate ne "1") {
        # The current date
        my $l_today =  time;
        my $l_epochdate = str2time($l_expdate);
 
        # Calculate diff between expiration date and today
        my $l_diff = ($l_epochdate - $l_today)/(3600*24);
 
        # Report if needed
        printf "%.0f\n", $l_diff;
    }
    else {
        print "Unable to read certificate!\n";
        exit (1);
    }
}
 
# Get expiration date
my $expdate = getExpire($host,$port);
 
# Report
report("$expdate");

Ce script (qui n'est qu'une adaptation du script sslexpire.pl disponible ici: http://sslexpire.home-dn.net/) prend 2 paramètres optionnels:

Le script se connecte sur le couple hôte/port donné, récupère le certificat SSL, analyse la date d'expiration, et n'affiche en sortie standard que le nombre de jours restants.

Mise en place du modèle Zabbix

Il ne reste plus qu'à définir un modèle qui surveillera ça pour nous:

Template_App_SSLExpire.xml
<?xml version="1.0" encoding="UTF-8"?>
<zabbix_export>
    <version>2.0</version>
    <date>2012-06-13T22:13:26Z</date>
    <groups>
        <group>
            <name>Templates</name>
        </group>
    </groups>
    <templates>
        <template>
            <template>Template_App_SSLExpire</template>
            <name>Template_App_SSLExpire</name>
            <groups>
                <group>
                    <name>Templates</name>
                </group>
            </groups>
            <applications/>
            <items>
                <item>
                    <name>Expiration du certificat</name>
                    <type>10</type>
                    <snmp_community></snmp_community>
                    <multiplier>0</multiplier>
                    <snmp_oid></snmp_oid>
                    <key>cert_expire.pl[&quot;-h&quot;,&quot;{HOST.CONN}&quot;]</key>
                    <delay>3600</delay>
                    <history>60</history>
                    <trends>1825</trends>
                    <status>0</status>
                    <value_type>3</value_type>
                    <allowed_hosts></allowed_hosts>
                    <units>jours</units>
                    <delta>0</delta>
                    <snmpv3_securityname></snmpv3_securityname>
                    <snmpv3_securitylevel>0</snmpv3_securitylevel>
                    <snmpv3_authpassphrase></snmpv3_authpassphrase>
                    <snmpv3_privpassphrase></snmpv3_privpassphrase>
                    <formula>1</formula>
                    <delay_flex></delay_flex>
                    <params></params>
                    <ipmi_sensor></ipmi_sensor>
                    <data_type>0</data_type>
                    <authtype>0</authtype>
                    <username></username>
                    <password></password>
                    <publickey></publickey>
                    <privatekey></privatekey>
                    <port></port>
                    <description></description>
                    <inventory_link>0</inventory_link>
                    <applications/>
                    <valuemap/>
                </item>
            </items>
            <discovery_rules/>
            <macros>
                <macro>
                    <macro>{$SSL_WARNING_EXPIRE}</macro>
                    <value>90</value>
                </macro>
            </macros>
            <templates/>
            <screens/>
        </template>
    </templates>
    <triggers>
        <trigger>
            <expression>{Template_App_SSLExpire:cert_expire.pl[&quot;-h&quot;,&quot;{HOST.CONN}&quot;].last(0)}&lt;{$SSL_WARN_EXPIRE}  &amp; {$SSL_WARN_EXPIRE}#0</expression>
            <name>Le certificat expire dans {ITEM.LASTVALUE1} jours</name>
            <url></url>
            <status>0</status>
            <priority>3</priority>
            <description></description>
            <type>0</type>
            <dependencies/>
        </trigger>
    </triggers>
</zabbix_export>