Last active
July 8, 2017 19:27
-
-
Save quantum5/f780bc39de84fb3f27fa058c2666e0ec to your computer and use it in GitHub Desktop.
Certificate Expiration Warning Cron Program
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import subprocess | |
import requests | |
import argparse | |
import time | |
import sys | |
import os | |
import re | |
from datetime import datetime, timedelta | |
from textwrap import dedent | |
def find_cn(value): | |
result = re.search('/CN=([^/]+)', value) | |
if result: | |
return result.group(1) | |
def openssl_datetime(value): | |
return datetime.strptime(value, '%b %d %H:%M:%S %Y %Z') | |
def main(): | |
parser = argparse.ArgumentParser() | |
parser.add_argument('host', help='hostname and port to check') | |
parser.add_argument('-s', '--sni', help='SNI name to use') | |
parser.add_argument('-t', '--threshold', help='days before expiry to warn', | |
default=14, type=int) | |
parser.add_argument('-q', '--quiet', help='quiet mode', action='store_true') | |
parser.add_argument('mailgun_domain', nargs='?', help='mailgun domain name to send warning') | |
parser.add_argument('mailgun_api', nargs='?', help='mailgun API key to send warning') | |
parser.add_argument('sender', nargs='?', help='address to send warning from') | |
parser.add_argument('recipients', nargs='*', help='address(es) to send warning to') | |
parser.add_argument('-m', '--subject', help='email subject to use') | |
args = parser.parse_args() | |
with open(os.devnull, 'w+') as null: | |
cmdline = ['openssl', 's_client', '-connect', args.host] | |
if args.sni: | |
cmdline += ['-servername', args.sni] | |
s_client = subprocess.Popen( | |
cmdline, stdin=null, stdout=subprocess.PIPE, stderr=null, | |
) | |
result = subprocess.check_output( | |
['openssl', 'x509', '-noout', '-dates', '-subject', '-issuer'], | |
stdin=s_client.stdout, stderr=null, | |
) | |
expires = None | |
issued = None | |
issuer = None | |
cn = None | |
for line in result.split('\n'): | |
key, _, value = line.partition('=') | |
if key == 'notBefore': | |
issued = openssl_datetime(value) | |
elif key == 'notAfter': | |
expires = openssl_datetime(value) | |
elif key == 'subject': | |
cn = find_cn(value) | |
elif key == 'issuer': | |
issuer = find_cn(value) | |
delta = expires - datetime.utcnow() | |
if not args.quiet: | |
print 'Checked certificate for:', args.host | |
print 'Certificate x509 name:', cn | |
print 'Certificate issued on:', issued | |
print 'Certificate issued by:', issuer | |
print 'Certificate expires on:', expires | |
print 'Certificate expires in:', delta | |
if (args.mailgun_domain and args.mailgun_api and args.sender and args.recipients | |
and delta <= timedelta(days=args.threshold)): | |
subject = args.subject or 'Certificate expiration warning for %s' % args.host | |
text = dedent('''\ | |
Your certificate for {host} expires in {delta}. | |
Certificate information: | |
* Host name: {host} | |
* Common name: {cn} | |
* Issued on: {issued} | |
* Expires on: {expires} | |
* Issuer: {issuer} | |
Remember to renew the certificate and reload it into the application! | |
''').format(host=args.host, delta=delta, cn=cn, expires=expires, | |
issued=issued, issuer=issuer).rstrip() | |
requests.post( | |
'https://api.mailgun.net/v3/%s/messages' % args.mailgun_domain, | |
auth=('api', args.mailgun_api), | |
data={'from': args.sender, | |
'to': args.recipients, | |
'subject': subject, | |
'text': text}) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment