Host SSL Cert Checker

Just copied and modified a cert check script from https://gist.github.com/gdamjan/55a8b9eec6cf7b771f92021d93b87b2c

The script will validate the cert of hosts and fail the run if the expiry date of any certs < 30 days.

# -*- encoding: utf-8 -*-
# requires a recent enough python with idna support in socket
# pyopenssl, cryptography and idna
# all credits to https://gist.github.com/gdamjan/55a8b9eec6cf7b771f92021d93b87b2c

from OpenSSL import SSL
from cryptography import x509
from cryptography.x509.oid import NameOID
import idna

from socket import socket
from collections import namedtuple
from datetime import datetime

HostInfo = namedtuple(field_names='cert hostname peername', typename='HostInfo')

HOSTS = [
    ('xx.yy.com', 443),

    ('dev.xx.kk.com', 443),
    ('xx.kk.com', 443),
]


def verify_cert(cert, hostname):
    # verify notAfter/notBefore, CA trusted, servername/sni/hostname
    cert.has_expired()
    # service_identity.pyopenssl.verify_hostname(client_ssl, hostname)
    # issuer


def get_certificate(hostname, port):
    hostname_idna = idna.encode(hostname)
    sock = socket()

    sock.connect((hostname, port))
    peername = sock.getpeername()
    ctx = SSL.Context(SSL.SSLv23_METHOD)  # most compatible
    ctx.check_hostname = False
    ctx.verify_mode = SSL.VERIFY_NONE

    sock_ssl = SSL.Connection(ctx, sock)
    sock_ssl.set_connect_state()
    sock_ssl.set_tlsext_host_name(hostname_idna)
    sock_ssl.do_handshake()
    cert = sock_ssl.get_peer_certificate()
    crypto_cert = cert.to_cryptography()
    sock_ssl.close()
    sock.close()

    return HostInfo(cert=crypto_cert, peername=peername, hostname=hostname)


def get_alt_names(cert):
    try:
        ext = cert.extensions.get_extension_for_class(x509.SubjectAlternativeName)
        return ext.value.get_values_for_type(x509.DNSName)
    except x509.ExtensionNotFound:
        return None


def get_common_name(cert):
    try:
        names = cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME)
        return names[0].value
    except x509.ExtensionNotFound:
        return None


def get_issuer(cert):
    try:
        names = cert.issuer.get_attributes_for_oid(NameOID.COMMON_NAME)
        return names[0].value
    except x509.ExtensionNotFound:
        return None


def find_expiring_cert(hostinfo):
    print('########################')
    basic_info = '''{hostname} - {peername} | commonName: {commonname} | SAN: {SAN} | issuer: {issuer} | notBefore: {notbefore} | notAfter:  {notafter}
    '''.format(
        hostname=hostinfo.hostname,
        peername=hostinfo.peername,
        commonname=get_common_name(hostinfo.cert),
        SAN=get_alt_names(hostinfo.cert),
        issuer=get_issuer(hostinfo.cert),
        notbefore=hostinfo.cert.not_valid_before,
        notafter=hostinfo.cert.not_valid_after
    )
    print(basic_info)
    time_between_insertion = hostinfo.cert.not_valid_after - datetime.now()
    print('Expiring after: ' + str(time_between_insertion.days)) + ' days'
    print('########################')
    print('')
    found = False
    if int(time_between_insertion.days) < 30:
        found = True

    return found


def check_it_out(hostname, port):
    hostinfo = get_certificate(hostname, port)
    find_expiring_cert(hostinfo)


def test_ssl_check():
    found = False
    for host in HOSTS:
        if find_expiring_cert(get_certificate(host[0], host[1])):
            found = True

    assert found is False, 'Found cert which is expiring in 30 days!!!'