Files @ b3456703e541
Branch filter:

Location: C3L-NOC/tls-expiry-tracker/backend/web.py

x
feat: replace web with more generic SSL verificator and handlers
#!/usr/bin/env python3
import ssl
from rich.console import Console
from cryptography import x509
import socket

import tls_utils
from tls_utils import TLSDetails

class SSLHandler:
    def __init__(self, host: str, port: int, context: ssl.SSLContext):
        self.host = host
        self.port = port
        self.context = context

    def connect(self, verification: bool) -> int:
        if verification:
            with self.context.wrap_socket(socket.socket(), server_hostname=self.host) as s:
                s.connect((self.host, self.port))
                cert = s.getpeercert()
                return tls_utils.get_validity_days(cert)[1]
        else:
            pem_cert = ssl.get_server_certificate((self.host, self.port), timeout=5)
            cert = x509.load_pem_x509_certificate(pem_cert.encode())
            not_after = cert.not_valid_after.timestamp()
            return tls_utils.get_expiry_timestamps(not_after)[1]

class SSLVerificator:
    def __init__(self, context: ssl.SSLContext):
        self.context = context

    def connect(self, domain: str, port: int) -> TLSDetails:
        handler = SSLHandler(domain, port, self.context)
        try:
            expiry = handler.connect(True)
            return TLSDetails(domain_name=domain, expires_in_days=expiry)
        except ssl.SSLCertVerificationError as e:
            if e.verify_code == tls_utils.EXPIRED:
                expiry = handler.connect(False)
                return TLSDetails(domain_name=domain, expires_in_days=expiry)
            elif e.verify_code == tls_utils.REVOKED:
                return TLSDetails(domain_name=domain, error_message="was revoked.")
            elif e.verify_code == tls_utils.SELF_SIGNED:
                return TLSDetails(domain_name=domain, error_message="is self-signed.")
            elif e.verify_code == tls_utils.ROOT_NOT_TRUSTED:
                return TLSDetails(domain_name=domain, error_message="invalid: root not trusted.")
            else:
                return TLSDetails(domain_name=domain, error_message="failed verification: " + e.verify_message + ".")
        except ssl.SSLError as e:
            return TLSDetails(domain_name=domain, error_message="could not establish a secure connection: " + e.reason + ".")
        except Exception as e:
            return TLSDetails(domain_name=domain, error_message="could not connect: " + str(e) + ".")