Initial commit: Basic CLI and checks
Certo supports polling one or several hostnames. Output can be human-readable or JSON.
This commit is contained in:
44
certo/checks/hostname.py
Normal file
44
certo/checks/hostname.py
Normal file
@@ -0,0 +1,44 @@
|
||||
import datetime
|
||||
from collections import namedtuple
|
||||
|
||||
from dateutil.parser import parse as dtparse
|
||||
|
||||
import socket
|
||||
import ssl
|
||||
|
||||
CertCheckResult = namedtuple(
|
||||
"CertCheckResult", ["hostname", "check_successful", "expiration_date", "debug"]
|
||||
)
|
||||
|
||||
|
||||
def get_cert(hostname, timeout):
|
||||
ctx = ssl.create_default_context()
|
||||
with ctx.wrap_socket(socket.socket(), server_hostname=hostname) as s:
|
||||
s.settimeout(timeout)
|
||||
|
||||
s.connect((hostname, 443))
|
||||
return s.getpeercert()
|
||||
|
||||
|
||||
def check_host_certificate_expiration(hostname, days_to_expiration, timeout=5):
|
||||
try:
|
||||
cert = get_cert(hostname, timeout)
|
||||
except ssl.SSLCertVerificationError as e:
|
||||
return CertCheckResult(hostname, False, None, e.strerror)
|
||||
|
||||
expdate = dtparse(cert.get("notAfter"))
|
||||
curdate = datetime.datetime.now(tz=expdate.tzinfo)
|
||||
|
||||
if expdate - curdate < datetime.timedelta(days=days_to_expiration):
|
||||
return CertCheckResult(
|
||||
hostname,
|
||||
False,
|
||||
expdate,
|
||||
f"Certificate expires in {(expdate - curdate).days} days - expected more than {days_to_expiration}",
|
||||
)
|
||||
return CertCheckResult(
|
||||
hostname,
|
||||
True,
|
||||
expdate,
|
||||
f"Certificate expires in {(expdate - curdate).days} days",
|
||||
)
|
||||
Reference in New Issue
Block a user