Skip to content
Snippets Groups Projects
test_ssl.py 3.31 KiB
#!/usr/bin/env python3

"""
Criticality: Normal
Checks that TLS certificates are valid; if invalid, the user will have to add an exception in his browser
"""

import datetime
from pathlib import Path
import requests
import ssl
import subprocess
import sys

import OpenSSL

sys.path.append(str(Path(__file__).parents[1].resolve()))

# pylint: disable=wrong-import-position
import utils as u  # noqa: E402


def main():
    print("Check TLS settings:")

    if subprocess.call(["which", "nginx"], stdout=subprocess.DEVNULL) != 0:
        u.info("nginx not found, skipping test")
        exit(2)

    conf = u.load_conf()

    conf_servers = (
        ("MS_SERVER_NAME", "mediaserver"),
        ("CM_SERVER_NAME", "mirismanager"),
        ("MONITOR_SERVER_NAME", "monitor"),
    )

    all_ok = True
    failure = False

    with open("/etc/hosts", "r") as fo:
        hosts = fo.read()

    for setting, default in conf_servers:
        name = conf.get(setting)
        if name == default:
            # vhost is using default value, the service is surely not installed
            continue
        if name not in hosts:
            # the domain is not in the hosts file, the service is surely not installed
            continue

        # check if custom port is used
        v_split = name.split(":")
        if len(v_split) > 1:
            server_name = v_split[0]
            port = int(v_split[1])
        else:
            server_name = name
            port = 443

        conn = ssl.create_connection((server_name, port))
        context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
        sock = context.wrap_socket(conn, server_hostname=server_name)
        cert = ssl.DER_cert_to_PEM_cert(sock.getpeercert(True))
        x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
        not_after = x509.get_notAfter().decode("ascii")

        expires = datetime.datetime.strptime(not_after, "%Y%m%d%H%M%SZ")
        remaining = expires - datetime.datetime.utcnow()

        if remaining < datetime.timedelta(days=0):
            u.error("{}: expired since {}".format(server_name, str(remaining)))
            # if mediaserver (the only cert that is mandatory)
            if setting == conf_servers[0]:
                failure = True
        elif remaining < datetime.timedelta(days=7):
            u.error("{}: expire in {}".format(server_name, str(remaining)))
            # if mediaserver (the only cert that is mandatory)
            if setting == conf_servers[0]:
                failure = True
        elif remaining < datetime.timedelta(days=30):
            u.warning("{}: expire in {}".format(server_name, str(remaining)))
            # if mediaserver (the only cert that is mandatory)
            if setting == conf_servers[0]:
                all_ok = False
        else:
            u.success("{}: expire in {}".format(server_name, str(remaining)))

        try:
            url = "https://{}".format(name)
            requests.get(url)
            u.success("{}: trusted certificate".format(name))
        except requests.exceptions.SSLError:
            u.warning("{}: untrusted certificate".format(name))
            # if mediaserver (the only cert that is mandatory)
            if setting == conf_servers[0]:
                all_ok = False

    if failure:
        exit(1)
    if not all_ok:
        exit(3)


if __name__ == "__main__":
    main()