core/homeassistant/components/cert_expiry/helper.py

55 lines
1.6 KiB
Python
Raw Normal View History

"""Helper functions for the Cert Expiry platform."""
import socket
import ssl
from homeassistant.core import HomeAssistant
from homeassistant.util import dt
from .const import TIMEOUT
from .errors import (
ConnectionRefused,
ConnectionTimeout,
ResolveFailed,
ValidationFailure,
)
def get_cert(
host: str,
port: int,
):
"""Get the certificate for the host and port combination."""
ctx = ssl.create_default_context()
address = (host, port)
with socket.create_connection(address, timeout=TIMEOUT) as sock:
with ctx.wrap_socket(sock, server_hostname=address[0]) as ssock:
cert = ssock.getpeercert()
return cert
async def get_cert_expiry_timestamp(
hass: HomeAssistant,
hostname: str,
port: int,
):
"""Return the certificate's expiration timestamp."""
try:
cert = await hass.async_add_executor_job(get_cert, hostname, port)
except socket.gaierror as err:
raise ResolveFailed(f"Cannot resolve hostname: {hostname}") from err
except socket.timeout as err:
raise ConnectionTimeout(
f"Connection timeout with server: {hostname}:{port}"
) from err
except ConnectionRefusedError as err:
raise ConnectionRefused(
f"Connection refused by server: {hostname}:{port}"
) from err
except ssl.CertificateError as err:
raise ValidationFailure(err.verify_message) from err
except ssl.SSLError as err:
raise ValidationFailure(err.args[0]) from err
ts_seconds = ssl.cert_time_to_seconds(cert["notAfter"])
return dt.utc_from_timestamp(ts_seconds)