from .monitor_cert_expiry_types import CertExpiry def _whole(v: object) -> bool: return isinstance(v, int) and not isinstance(v, bool) def cert_expiry(not_after: int, now: int, warn_days: int, critical_days: int) -> CertExpiry: """RFC 5280 makes validity inclusive of notAfter, so a certificate is expired only after that second, not at it. Thresholds compare whole days left with the day counts: fewer than N days (secondsLeft < N * 86400) is exactly floor(secondsLeft / 86400) < N, with no multiplication to overflow.""" if not _whole(not_after) or not _whole(now): raise ValueError("notAfter and now must be whole seconds, received %r and %r" % (not_after, now)) if not _whole(critical_days) or critical_days < 0: raise ValueError("criticalDays must be a whole number 0 or more, received %r" % (critical_days,)) if not _whole(warn_days) or warn_days < critical_days: raise ValueError("warnDays must be a whole number at least criticalDays (%d), received %r" % (critical_days, warn_days)) if now > not_after: return CertExpiry(state="expired", seconds_left=0, days_left=0) seconds_left = not_after - now days_left = seconds_left // 86400 if days_left < critical_days: state = "critical" elif days_left < warn_days: state = "warning" else: state = "ok" return CertExpiry(state=state, seconds_left=seconds_left, days_left=days_left)