Using PHP to Monitor SSL Certificate Expiration
Let's Encrypt Overview
Let's Encrypt offers short validity periods (three months) and automatically issues certificates via the ACME protocol. Its mission to encrypt all web traffic, combined with support from well-known institutions and the rapid adoption of HTTP/2.0, has made it extremely popular.
The Lack of SSL Certificate Monitoring
Traditional manual certificate applications often have longer validity periods, causing expiration issues to be overlooked. Companies such as Alibaba Cloud Apsara Community, Sina SAE, and Qiniu have all experienced production environment certificate expiration incidents. You can see the search records on v2ex for more details. SSL certificate monitoring should not be missing; everything except citizens should be monitored.
How to Use PHP to Monitor SSL Certificate Expiration
By using the functions stream_context_create, stream_context_get_params, and openssl_x509_parse, we can retrieve extensive information about SSL certificate resources, including the expiration time. There is a gist that retrieves Baidu's certificate information.
You can write a detection page that throws an exception if the certificate is about to expire. Then, use mature monitoring services like Alibaba Cloud Monitoring to add this page. Set the alert condition so that if the status code is >= 400, an error is immediately triggered, capable of pushing notifications via SMS, email, or DingTalk.
Here is a code example of my blog monitoring script. The URL is https://tea.codes/ssl-monitor.php.
<?php
$g = stream_context_create ([
"ssl" => ["capture_peer_cert" => true],
'http' => [
'method' => 'GET',
'user_agent' => 'shouwang.io ssl detector',
'timeout' => 10
]
]);
$r = fopen("https://tea.codes/", "rb", false, $g);
$cont = stream_context_get_params($r);
$cert = openssl_x509_parse($cont["options"]["ssl"]["peer_certificate"]);
if(empty($cert['validTo_time_t'])) {
throw new \Exception("Can't get cert expire time");
}
$fortyEightHours = strtotime("+48 hours");
if($cert['validTo_time_t'] <= $fortyEightHours) {
throw new \Exception("Cert will expire in 48 hours");
} else {
echo "Cert would expired at ", date("Y-m-d H:i:s", $cert['validTo_time_t']);
}
In addition, if you are using Let's Encrypt services, you should also configure automatic certificate renewal.
Third-Party Services
There are also some third-party SSL monitoring services, but they are slightly less mature than the monitoring functions provided by cloud service providers. This code was originally intended for a hobby project: Shouwang.io monitoring. Due to being busy with my main job, I decided to share this code segment.
I hope major cloud service providers will launch their own certificate monitoring services soon.