Expiration Validator¶
This is the validator that catches the most common certificate incident there is: a certificate that has expired, or is about to.
It reports how long until the certificate's notAfter date, and it flags the situations you care about: the cert is already expired, isn't valid yet, is approaching expiration, or was issued for longer than your lifetime policy allows.
Enabled by default
You don't have to turn this one on. expiration is one of the three default validators, along with hostname and root_certificate.
Try it¶
Let's run it against a host:
from certmonitor import CertMonitor
with CertMonitor("example.com") as monitor:
monitor.get_cert_info()
print(monitor.validate()["expiration"])
A healthy certificate comes back valid, with the days remaining:
These examples show selected fields from illustrative scans. validate() also adds status and code, described in the result contract.
{
"is_valid": true,
"days_to_expiry": 56,
"expires_on": "2026-08-08T22:14:02+00:00",
"lifetime_days": 365,
"lifetime_limit_days": 398,
"warnings": []
}
An expired one flips is_valid to false and adds a reason you can drop straight into an alert:
{
"is_valid": false,
"days_to_expiry": -4080,
"expires_on": "2015-04-12T23:59:59+00:00",
"warnings": ["Certificate is expired and has been expired for (-4080 days)"],
"reason": "Certificate expired 4080 days ago (expired on 2015-04-12).",
"lifetime_days": 3,
"lifetime_limit_days": 1187
}
A valid certificate can still warn you
is_valid only turns false when the certificate is expired or not yet valid. A certificate can be perfectly valid and still carry a warning: it expires within the warning threshold (time to renew), including when less than one day remains, or its total lifetime exceeds the limit. So watch the warnings list, and status, not just is_valid.
Arguments¶
Pass via validator_args={"expiration": {...}}. The arguments and their defaults are documented in the reference below.
Thresholds accept fractional days and require 0 <= critical_days <= warning_days.
The lifetime policy defaults to "public": the CA/Browser Forum limit that applied on the certificate's issue date. That is 825 days from March 2018, 398 from September 2020, 200 from March 2026, 100 from March 2027, and 47 from March 2029, so a certificate is judged by the rule it was issued under, and the limit used is reported in lifetime_limit_days. The check warns rather than fails. Pass a number for a private PKI policy, or None to skip the check:
When notBefore is missing from the certificate data, the validity-start and lifetime checks are skipped and lifetime_days is omitted.
Reference¶
certmonitor.validators.expiration.ExpirationValidator ¶
Bases: BaseCertValidator
A validator for checking the expiration date of an SSL certificate.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
The name of the validator. |
validate ¶
validate(cert: dict[str, Any], host: str, port: int, *, warning_days: float = 7, critical_days: float = 1, max_lifetime_days: float | str | None = PUBLIC_TLS_POLICY) -> ExpirationResult
Validates the validity window of the provided SSL certificate and its total lifetime.
The certificate fails when it is expired or not yet valid. Approaching
expiry and an over-long total lifetime are reported as warnings, so
is_valid stays True while status becomes warn.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cert
|
dict
|
The SSL certificate. |
required |
host
|
str
|
The hostname (not used in this validator). |
required |
port
|
int
|
The port number (not used in this validator). |
required |
warning_days
|
float
|
Warn when this many days or fewer remain. Defaults to 7. |
7
|
critical_days
|
float
|
Use a critical warning within this many days. Defaults to 1. |
1
|
max_lifetime_days
|
float | str
|
Warn when the total lifetime from
notBefore to notAfter exceeds this many days. Defaults to |
PUBLIC_TLS_POLICY
|
Returns:
| Name | Type | Description |
|---|---|---|
dict |
ExpirationResult
|
A dictionary containing the validation results, including whether the certificate is valid, the number of days until expiry, the expiration date, the total lifetime in days and the limit it was compared with (when notBefore is available), and any warnings. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If thresholds do not satisfy 0 <= critical_days <= warning_days,
or max_lifetime_days is neither |
Examples:
Example output (success): This example shows a certificate that is valid and has 120 days until expiration, so no warnings are present.
```json
{
"is_valid": true,
"days_to_expiry": 120,
"expires_on": "2025-09-01T23:59:59+00:00",
"lifetime_days": 365,
"lifetime_limit_days": 398,
"warnings": []
}
```
Example output (failure): This example shows a certificate that expired 10 days ago, so validation fails and a warning is included.
```json
{
"is_valid": false,
"days_to_expiry": -10,
"expires_on": "2025-04-30T23:59:59+00:00",
"lifetime_days": 365,
"lifetime_limit_days": 398,
"warnings": [
"Certificate is expired and has been expired for (-10 days)"
],
"reason": "Certificate expired 10 days ago (expired on 2025-04-30)."
}
```
Source code in certmonitor/validators/expiration.py
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | |