Perform handshakes asynchronously

This commit is contained in:
2022-10-11 06:55:34 +10:30
parent 8046f04e33
commit 10ff26b17f
4 changed files with 45 additions and 14 deletions

View File

@@ -1,4 +1,6 @@
import asyncio
import datetime
import logging
from collections import namedtuple
from dateutil.parser import parse as dtparse
@@ -11,18 +13,38 @@ CertCheckResult = namedtuple(
)
def get_cert(hostname, timeout):
# Unit of time slept asynchronously to simulate async socket handling
AWAIT_IOTA = 0.001
async def get_cert(hostname, timeout):
ctx = ssl.create_default_context()
with ctx.wrap_socket(socket.socket(), server_hostname=hostname) as s:
with ctx.wrap_socket(
socket.socket(), server_hostname=hostname, do_handshake_on_connect=False
) as s:
s.settimeout(timeout)
# @todo simulate async connect
s.connect((hostname, 443))
s.setblocking(False)
# Cannot await the handshake: simulate it with asyncio sleep
while "Handshake not finished":
try:
s.do_handshake()
break
except ssl.SSLWantReadError:
await asyncio.sleep(AWAIT_IOTA)
except ssl.SSLWantWriteError:
await asyncio.sleep(AWAIT_IOTA)
return s.getpeercert()
def check_host_certificate_expiration(hostname, days_to_expiration, timeout=5):
async def check_host_certificate_expiration(hostname, days_to_expiration, timeout=5):
logging.info(f"Getting CERT from {hostname}")
try:
cert = get_cert(hostname, timeout)
cert = await get_cert(hostname, timeout)
except ssl.SSLCertVerificationError as e:
return CertCheckResult(hostname, False, None, e.strerror)