--- /dev/null
+#!/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()