#!/usr/bin/python from __future__ import print_function from optparse import OptionParser from ssl import SSLContext, PROTOCOL_TLSv1_2, CERT_REQUIRED, cert_time_to_seconds, SSLError from socket import socket, AF_INET6 from datetime import datetime, timedelta VERBOSE=False def check_cert(host, port, ca, warn, crit): context = SSLContext(PROTOCOL_TLSv1_2) context.verify_mode = CERT_REQUIRED context.load_verify_locations(ca) connection = context.wrap_socket(socket(AF_INET6), server_hostname=host) try: connection.connect((host, port)) except SSLError: print("CRIT (invalid certificate) %s:%d" % (host, port)) return 2 expiretimestamp = cert_time_to_seconds(connection.getpeercert()['notAfter']) delta = datetime.utcfromtimestamp(expiretimestamp) - datetime.utcnow() if delta < crit: print("CRIT (expires in %s) %s:%d" % (delta, host, port)) return 2 elif delta < warn: print("WARN (expires in %s) %s:%d" % (delta, host, port)) return 1 def main(): global VERBOSE parser = OptionParser() parser.add_option("-n", "--name", action="append", type="string", dest="hosts", help="hostname:port to check for expired certificates") parser.add_option("-w", "--warning-days", action="store", type=int, dest="warn", default=15, help="minimum remaining validity in days before a warning is issued") parser.add_option("-c", "--critical-days", action="store", type=int, dest="crit", default=5, help="minimum remaining validity in days before a warning is issued") parser.add_option("-v", action="store_true", dest="verbose", default=False) parser.add_option("-q", action="store_false", dest="verbose") parser.add_option("--ca", action="store", type="string", dest="ca", default="/etc/ssl/certs/ca-certificates.crt", help="ca certificate bundle") opts, _args = parser.parse_args() VERBOSE = opts.verbose if not opts.hosts: parser.error("needs at least one host") try: hosts = [ (i[0], int(i[1])) for i in [ j.split(':', 1) for j in opts.hosts ] ] except (ValueError, IndexError): parser.error("names need to be in DNSNAME:PORT format") for host, port in hosts: check_cert(host, port, opts.ca, timedelta(opts.warn), timedelta(opts.crit)) if __name__ == "__main__": main()