]> git.siccegge.de Git - tools.git/blob - tls-check
d16e80ab158e7a691f4fd7d0357e79972b192209
[tools.git] / tls-check
1 #!/usr/bin/python
2
3 from __future__ import print_function
4 from optparse import OptionParser
5 from ssl import SSLContext, PROTOCOL_TLSv1_2, CERT_REQUIRED, cert_time_to_seconds, SSLError
6 from socket import socket, AF_INET6
7 from datetime import datetime, timedelta
8
9 VERBOSE=False
10
11 def check_cert(host, port, ca, warn, crit):
12 context = SSLContext(PROTOCOL_TLSv1_2)
13 context.verify_mode = CERT_REQUIRED
14 context.load_verify_locations(ca)
15 connection = context.wrap_socket(socket(AF_INET6),
16 server_hostname=host)
17 try:
18 connection.connect((host, port))
19 except SSLError:
20 print("CRIT (invalid certificate) %s:%d" % (host, port))
21 return 2
22
23 expiretimestamp = cert_time_to_seconds(connection.getpeercert()['notAfter'])
24 delta = datetime.utcfromtimestamp(expiretimestamp) - datetime.utcnow()
25
26 if delta < crit:
27 print("CRIT (expires in %s) %s:%d" % (delta, host, port))
28 return 2
29 elif delta < warn:
30 print("WARN (expires in %s) %s:%d" % (delta, host, port))
31 return 1
32
33
34 def main():
35 global VERBOSE
36 parser = OptionParser()
37 parser.add_option("-n", "--name",
38 action="append", type="string", dest="hosts",
39 help="hostname:port to check for expired certificates")
40 parser.add_option("-w", "--warning-days",
41 action="store", type=int, dest="warn", default=15,
42 help="minimum remaining validity in days before a warning is issued")
43 parser.add_option("-c", "--critical-days",
44 action="store", type=int, dest="crit", default=5,
45 help="minimum remaining validity in days before a warning is issued")
46 parser.add_option("-v", action="store_true", dest="verbose", default=False)
47 parser.add_option("-q", action="store_false", dest="verbose")
48 parser.add_option("--ca", action="store", type="string", dest="ca",
49 default="/etc/ssl/certs/ca-certificates.crt",
50 help="ca certificate bundle")
51
52
53 opts, _args = parser.parse_args()
54
55 VERBOSE = opts.verbose
56 if not opts.hosts:
57 parser.error("needs at least one host")
58
59 try:
60 hosts = [ (i[0], int(i[1])) for i in [ j.split(':', 1) for j in opts.hosts ] ]
61 except (ValueError, IndexError):
62 parser.error("names need to be in DNSNAME:PORT format")
63
64 for host, port in hosts:
65 check_cert(host, port, opts.ca, timedelta(opts.warn), timedelta(opts.crit))
66
67 if __name__ == "__main__":
68 main()