[docs]defCertLimitSSL(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()returncert
[docs]defCertLimitSTARTTLS(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()returncert
[docs]defcheckOnDom(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:ifport==587:cert=CertLimitSTARTTLS(hostname)else:cert=CertLimitSSL(hostname,port)remainingDays=(datetime.strptime(cert.get_notAfter().decode(),"%Y%m%d%H%M%SZ")-now).dayscertDetails['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 namecertDetails['issuer']=[e[1]foreinissuerife[0]==b'O'][0].decode()certDetails['subject']=dict(cert.get_subject().get_components())exceptTimeoutError:certDetails['notAfter']=_('Timeout from host !')returncertDetailsexceptsocket.gaierror:certDetails['notAfter']=_('Could not resolve hostname !')returncertDetailsexceptsocket.timeout:certDetails['notAfter']=_('Timeout from host !')returncertDetailsexceptssl.CertificateError:certDetails['notAfter']=_('Certificate is not valid !')returncertDetailsexceptssl.SSLError:certDetails['notAfter']=_('Can not handle SSL on this port !')returncertDetailsexceptConnectionRefusedError:certDetails['notAfter']=_('Host refuse the connection !')returncertDetailsifremainingDays<=7:certDetails['restTime']='< 7'elifremainingDays<=14:certDetails['status']='warning'certDetails['restTime']='< 14'elifremainingDays<=28:certDetails['status']='info'certDetails['restTime']='< 28'else:certDetails['status']='success'returncertDetails