mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Correct socket use in cert_expiry platform (#25011)
* Make sure we use same family for ssl socket and connection getaddrinfo result could be different from what connection was made with. It also blocks potential use of happy eye balls algorithm This also fixes lingering sockets until python garbage collection. * Add availability value if unable to get expiry * Fix lint issue
This commit is contained in:
parent
31d7b702a6
commit
c2f1c4b981
@ -55,6 +55,7 @@ class SSLCertificate(Entity):
|
|||||||
self.server_port = server_port
|
self.server_port = server_port
|
||||||
self._name = sensor_name
|
self._name = sensor_name
|
||||||
self._state = None
|
self._state = None
|
||||||
|
self._available = False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
@ -76,34 +77,39 @@ class SSLCertificate(Entity):
|
|||||||
"""Icon to use in the frontend, if any."""
|
"""Icon to use in the frontend, if any."""
|
||||||
return 'mdi:certificate'
|
return 'mdi:certificate'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def available(self):
|
||||||
|
"""Icon to use in the frontend, if any."""
|
||||||
|
return self._available
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
"""Fetch the certificate information."""
|
"""Fetch the certificate information."""
|
||||||
try:
|
|
||||||
ctx = ssl.create_default_context()
|
ctx = ssl.create_default_context()
|
||||||
host_info = socket.getaddrinfo(self.server_name, self.server_port)
|
try:
|
||||||
family = host_info[0][0]
|
address = (self.server_name, self.server_port)
|
||||||
sock = ctx.wrap_socket(
|
with socket.create_connection(
|
||||||
socket.socket(family=family), server_hostname=self.server_name)
|
address, timeout=TIMEOUT) as sock:
|
||||||
sock.settimeout(TIMEOUT)
|
with ctx.wrap_socket(
|
||||||
sock.connect((self.server_name, self.server_port))
|
sock, server_hostname=address[0]) as ssock:
|
||||||
|
cert = ssock.getpeercert()
|
||||||
|
|
||||||
except socket.gaierror:
|
except socket.gaierror:
|
||||||
_LOGGER.error("Cannot resolve hostname: %s", self.server_name)
|
_LOGGER.error("Cannot resolve hostname: %s", self.server_name)
|
||||||
|
self._available = False
|
||||||
return
|
return
|
||||||
except socket.timeout:
|
except socket.timeout:
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
"Connection timeout with server: %s", self.server_name)
|
"Connection timeout with server: %s", self.server_name)
|
||||||
|
self._available = False
|
||||||
return
|
return
|
||||||
except OSError:
|
except OSError:
|
||||||
_LOGGER.error("Cannot connect to %s", self.server_name)
|
_LOGGER.error("Cannot fetch certificate from %s",
|
||||||
return
|
self.server_name, exc_info=1)
|
||||||
|
self._available = False
|
||||||
try:
|
|
||||||
cert = sock.getpeercert()
|
|
||||||
except OSError:
|
|
||||||
_LOGGER.error("Cannot fetch certificate from %s", self.server_name)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
ts_seconds = ssl.cert_time_to_seconds(cert['notAfter'])
|
ts_seconds = ssl.cert_time_to_seconds(cert['notAfter'])
|
||||||
timestamp = datetime.fromtimestamp(ts_seconds)
|
timestamp = datetime.fromtimestamp(ts_seconds)
|
||||||
expiry = timestamp - datetime.today()
|
expiry = timestamp - datetime.today()
|
||||||
|
self._available = True
|
||||||
self._state = expiry.days
|
self._state = expiry.days
|
||||||
|
Loading…
x
Reference in New Issue
Block a user