Source code for aj.plugins.check_certificates.api

import ssl
import socket
import smtplib
from datetime import datetime
from OpenSSL import crypto

now = datetime.now()

[docs]def CertLimitSSL(hostname, port): """ Get the SSL certificate from a host. :param hostname: Hostname :type hostname: string :param port: Port :type port: integer :return: OpenSSL cert :rtype: OpenSSL cert """ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) s = ctx.wrap_socket(socket.socket(), server_hostname=hostname) s.settimeout(10) s.connect((hostname, port)) cert = crypto.load_certificate(crypto.FILETYPE_ASN1, s.getpeercert(binary_form=True)) s.close() return cert
[docs]def CertLimitSTARTTLS(hostname): """ Get the SSL certificate from host with STARTTLS connection on port 587. :param hostname: Hostname :type hostname: string :return: OpenSSL cert :rtype: OpenSSL cert """ connection = smtplib.SMTP(hostname, 587) connection.starttls() cert = crypto.load_certificate(crypto.FILETYPE_ASN1, connection.sock.getpeercert(binary_form=True)) connection.quit() return cert
[docs]def checkOnDom(hostname, port='443'): """ Store all details from a certificate into a dict and add a status attribute to display a bootstrap class for the time remaining before renew : - renew the next 7 days : danger - renew the next 14 days: warning - renew the next 28 days : info - or success :param hostname: Hostname :type hostname: string :param port: Port to test, default 443 :type port: string :return: Dict with all details from the certificate :rtype: dict """ port = int(port) certDetails = { 'status': 'danger', 'hostname': hostname, 'port':port, 'url':hostname, 'notAfter': None, 'restTime': '', 'issuer': None, 'subject': None, 'notBefore': None } try: if port == 587: cert = CertLimitSTARTTLS(hostname) else: cert = CertLimitSSL(hostname, port) remainingDays = (datetime.strptime(cert.get_notAfter().decode(),"%Y%m%d%H%M%SZ")-now).days certDetails['notAfter'] = str(datetime.strptime(cert.get_notAfter().decode(),"%Y%m%d%H%M%SZ")) certDetails['notBefore'] = str(datetime.strptime(cert.get_notBefore().decode(),"%Y%m%d%H%M%SZ")) issuer = cert.get_issuer().get_components() # Issuer be like [(b'C', b'US'), (b'O', b"Let's Encrypt"), (b'CN', b'R3')] # Extract Organization name certDetails['issuer'] = [e[1] for e in issuer if e[0]==b'O'][0].decode() certDetails['subject'] = dict(cert.get_subject().get_components()) except TimeoutError: certDetails['notAfter'] = _('Timeout from host !') return certDetails except socket.gaierror: certDetails['notAfter'] = _('Could not resolve hostname !') return certDetails except socket.timeout: certDetails['notAfter'] = _('Timeout from host !') return certDetails except ssl.CertificateError: certDetails['notAfter'] = _('Certificate is not valid !') return certDetails except ssl.SSLError: certDetails['notAfter'] = _('Can not handle SSL on this port !') return certDetails except ConnectionRefusedError: certDetails['notAfter'] = _('Host refuse the connection !') return certDetails if remainingDays <= 7: certDetails['restTime'] = '< 7' elif remainingDays <= 14: certDetails['status'] = 'warning' certDetails['restTime'] = '< 14' elif remainingDays <= 28: certDetails['status'] = 'info' certDetails['restTime'] = '< 28' else: certDetails['status'] = 'success' return certDetails

Comments

comments powered by Disqus