Domain SSL expiration list? #362
Replies: 3 comments 1 reply
-
We could definitely do that. I whipped up the following quick code to fetch the SSL certificate information: /**
* Returns select TLS certificate information which are relevant to our use case.
*
* @param string $url The URL of the site to fetch the SSL certificate from.
* @param int $timeout The timeout, in seconds, for the fetch operation.
*
* @return null|object
*/
#[\JetBrains\PhpStorm\ObjectShape([
'commonName' => 'string|null',
'hash' => 'string|null',
'type' => 'string|null',
'issuerCommonName' => 'string|null',
'issuerOrganisation' => 'string|null',
'validFrom' => 'DateTime|null',
'validTo' => 'DateTime|null',
])]
function getCertificateInformation(string $url, int $timeout = 3): ?object
{
// Make sure the PHP OpenSSL extension is installed.
if (!function_exists('openssl_x509_parse'))
{
return null;
}
// Get the hostname and port from the URL
$hostname = parse_url($url, PHP_URL_HOST);
$scheme = parse_url($url, PHP_URL_SCHEME) ?: 'https';
$port = (int) (parse_url($url, PHP_URL_PORT) ?: 443);
// If the hostname is empty, the scheme is not HTTPS, or the port is out-of-range we have nothing to do.
if (empty($hostname) || $scheme !== 'https' || $port <= 0 || $port >= 65536)
{
return null;
}
// Open the raw SSL socket stream to fetch the remote server's certificate.
$socketResource = stream_socket_client(
sprintf('ssl://%s:%d', $hostname, $port),
$errorNumber,
$errorString,
$timeout,
STREAM_CLIENT_CONNECT,
stream_context_create(
[
"ssl" => [
"capture_peer_cert" => true,
],
]
)
);
if (!is_resource($socketResource))
{
return null;
}
// Get the certificate and close the stream
$cert = stream_context_get_params($socketResource);
fclose($socketResource);
// Make sure we have indeed captured the peer certificate
if (
!is_array($cert)
|| !isset($cert['options'])
|| !is_array($cert['options'])
|| !isset($cert['options']['ssl'])
|| !is_array($cert['options']['ssl'])
|| !isset($cert['options']['ssl']['peer_certificate'])
)
{
return null;
}
// Parse the raw binary certificate using the PHP OpenSSL extension.
$certificateInformation = openssl_x509_parse($cert['options']['ssl']['peer_certificate']);
if ($certificateInformation === false)
{
return null;
}
// Decode the validity from / to time
try
{
$validFrom = new DateTime('@' . $certificateInformation['validFrom_time_t'] ?? '0');
}
catch (Exception $e)
{
$validFrom = null;
}
try
{
$validTo = new DateTime('@' . $certificateInformation['validTo_time_t'] ?? '0');
}
catch (Exception $e)
{
$validTo = null;
}
// Return the information which is relevant to us
return (object) [
'commonName' => $certificateInformation['subject']['CN'] ?? null,
'hash' => $certificateInformation['hash'] ?? null,
'type' => $certificateInformation['signatureTypeSN'] ?? null,
'issuerCommonName' => $certificateInformation['issuer']['CN'] ?? null,
'issuerOrganisation' => $certificateInformation['issuer']['O'] ?? null,
'validFrom' => $validFrom,
'validTo' => $validTo,
];
} We could run this periodically (once or twice a day would suffice) and set up date limits for reminding you about certificate expiration. I would put two limits, one at one month and one at 3 days before expiration, with the ability to override them per site. Why override the limits per site? Well, some sites may be set up to auto-update their SSL certificates, e.g. using Let's Encrypt, CloudFlare etc. I would not want to be reminded a month earlier the certificate expires; I know, it's not a big deal. I would like, however, to be reminded 2–3 days in advance because the auto-renewal is supposed to run 5 days before the certificate expires, therefore if I am 2–3 days from expiration with no updated certificate I can safely assume the proverbial poop has hit the fan. |
Beta Was this translation helpful? Give feedback.
-
Wow, this really looks great! Why not do a check 15 days and one 3 days before the expiration instead? (instead of a month and 3 days earlier) In case there are domains with critical problems (and it has happened to me on some client domains in the past) I have a more "fresh" and recent reminder on that domain rather than a month before. (absurdly in a month it might slip your mind again if you're under an absurd workload like these Christmas days :D) I also consider that the SSLs generated by Let's Encrypt have only 90 days of life: probably a 15 day reminder could be more effective in case you want to stay "alert" to decide any action on a domain that has been some problematic. Mine is just a consideration on a real situation that I experienced just recently, what do you think? |
Beta Was this translation helpful? Give feedback.
-
Tracking with #397 |
Beta Was this translation helpful? Give feedback.
-
Can you consider the possibility of having a page where we can see the sites with their SSL certificates in order of expiry? Or maybe add a sortable column to the main page?
Although it is not strictly related to the site but to the server, but in certain contexts, when you have problems with SSL, this becomes the most important parameter of all in managing multiple sites.
Beta Was this translation helpful? Give feedback.
All reactions