It seems pretty self explanatory why SSL certificates need to expire. Everyone knows that they expire. Why is it SOOOO hard to remember to renew your certificate? We've been bit twice in the past three months with certificates that have expired on us. We do the mad scramble to get the renewed and then forget about them again.
Rather than continue down this never ending path, I decided to write a quick script that could be run nightly on our Raspberry Pi to use a JSON feed of all the SSL sites that we have, check the SSL certificate expiry date and then notify me if one of the sites is expiring in the next 30 days.
Below is a redacted version of the code. It needs some error handling added for sure.
#!/usr/bin/python import datetime import socket import ssl from urlparse import urlparse import urllib2, json import email.message import smtplib def sendEmail( subject, body ): try: msg = email.message.Message() msg['Subject'] = subject + " - SSL monitoring" msg['From'] = 'email@example.com' msg['To'] = 'firstname.lastname@example.org' msg.add_header('Content-Type','text/html') msg.set_payload(body) s = smtplib.SMTP('retail.smtp.com', 2525) s.login('USERNAME', 'PASSWORD') s.sendmail(msg['From'], [msg['To']], msg.as_string()) except: print("smtp error") return; #This was modified from https://serverlesscode.com/post/ssl-expiration-alerts-with-lambda/ def ssl_expiry_datetime(hostname): ssl_date_fmt = r'%b %d %H:%M:%S %Y %Z' context = ssl.create_default_context() conn = context.wrap_socket( socket.socket(socket.AF_INET), server_hostname=hostname, ) # 3 second timeout because Lambda has runtime limitations conn.settimeout(3.0) conn.connect((hostname, 443)) ssl_info = conn.getpeercert() # parse the string from the certificate into a Python datetime object return datetime.datetime.strptime(ssl_info['notAfter'], ssl_date_fmt) url = "http://URL_OF_JSON_FEED" response = urllib2.urlopen(url) data = json.loads(response.read()) now = datetime.datetime.now() for di in data: o = urlparse(di) expirationDate = ssl_expiry_datetime(o.netloc) delta = expirationDate - now if delta.days < 30: sendEmail(di, "SSL cert expires in " + str(delta.days) + " days")
I added this script as a cron job to our Raspberry Pi and it has been running successfully ever since. I should also add in slack notifications. Something for the future. :)