Refactor Certificate Expiry Sensor (#32066)
* Cert Expiry refactor * Unused parameter * Reduce delay * Deprecate 'name' config * Use config entry unique_id * Fix logic bugs found with tests * Rewrite tests to use config flow core interfaces, validate created sensors * Update strings * Minor consistency fix * Review fixes, complete test coverage * Move error handling to helper * Subclass exceptions * Better tests * Use first object reference * Fix docstring
This commit is contained in:
parent
eb90cefd84
commit
df3f7687d4
11 changed files with 652 additions and 236 deletions
|
@ -1,12 +1,19 @@
|
|||
"""Helper functions for the Cert Expiry platform."""
|
||||
from datetime import datetime
|
||||
import socket
|
||||
import ssl
|
||||
|
||||
from .const import TIMEOUT
|
||||
from .errors import (
|
||||
ConnectionRefused,
|
||||
ConnectionTimeout,
|
||||
ResolveFailed,
|
||||
ValidationFailure,
|
||||
)
|
||||
|
||||
|
||||
def get_cert(host, port):
|
||||
"""Get the ssl certificate for the host and port combination."""
|
||||
"""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:
|
||||
|
@ -14,3 +21,24 @@ def get_cert(host, port):
|
|||
# pylint disable: https://github.com/PyCQA/pylint/issues/3166
|
||||
cert = ssock.getpeercert() # pylint: disable=no-member
|
||||
return cert
|
||||
|
||||
|
||||
async def get_cert_time_to_expiry(hass, hostname, port):
|
||||
"""Return the certificate's time to expiry in days."""
|
||||
try:
|
||||
cert = await hass.async_add_executor_job(get_cert, hostname, port)
|
||||
except socket.gaierror:
|
||||
raise ResolveFailed(f"Cannot resolve hostname: {hostname}")
|
||||
except socket.timeout:
|
||||
raise ConnectionTimeout(f"Connection timeout with server: {hostname}:{port}")
|
||||
except ConnectionRefusedError:
|
||||
raise ConnectionRefused(f"Connection refused by server: {hostname}:{port}")
|
||||
except ssl.CertificateError as err:
|
||||
raise ValidationFailure(err.verify_message)
|
||||
except ssl.SSLError as err:
|
||||
raise ValidationFailure(err.args[0])
|
||||
|
||||
ts_seconds = ssl.cert_time_to_seconds(cert["notAfter"])
|
||||
timestamp = datetime.fromtimestamp(ts_seconds)
|
||||
expiry = timestamp - datetime.today()
|
||||
return expiry.days
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue