add mailman-check
[lets-encrypt-tiny.git] / certcheck
1 #!/usr/bin/python3
2 ## Usage:
3 ##   ./certcheck -d DAYS <file/folder> <file/folder> ...
4 ## Recursively crawl all given folders for files ending in '.crt', and check all of them and all given files for their
5 ## expiry date. If that is less than DAYS in the future, print that information.
6
7 import argparse, subprocess, re, os, datetime
8
9 def check_dir(dirname, days):
10     for name in os.listdir(dirname):
11         name = os.path.join(dirname, name)
12         if os.path.isdir(name):
13             check_dir(name, days)
14         elif name.endswith('.crt'):
15             check_file(name, days)
16
17 def check_file(filename, days):
18     valid_not_after = subprocess.check_output(["openssl", "x509", "-enddate", "-in", filename, "-out", "/dev/null"]).decode('utf-8')
19     match = re.match("notAfter=([a-zA-Z0-9: ]+)", valid_not_after)
20     assert match is not None, "Unexpected output from openssl: valid_not_after"
21     enddate = match.group(1)
22     enddate = datetime.datetime.strptime(enddate, '%b %d %X %Y %Z')
23     delta = enddate - datetime.datetime.now()
24     if delta < datetime.timedelta(days=days):
25         print("{} expires at {}, which is in {} days".format(filename, enddate, delta.days))
26
27 if __name__ == "__main__":
28     parser = argparse.ArgumentParser(description='Check for soon-to-expire (and already expired) certificates')
29     parser.add_argument("-d", "--days", metavar='N',
30                         dest="days", type=int, default=14,
31                         help="Warn about certificates valid for less than N (default 7)")
32     parser.add_argument("certs",  metavar='CERTS', nargs='+',
33                         help="These certificate files are checked. Directories are searched recursively for files called '*.crt'.")
34     args = parser.parse_args()
35     
36     for name in args.certs:
37         if os.path.isdir(name):
38             check_dir(name, args.days)
39         else:
40             check_file(name, args.days)
41
42