Looking to hire Laravel developers? Try LaraJobs

laravel-ssl-keeper maintained by labrodev

Description
TLS certificate expiry reader for Laravel — fetches and parses the peer certificate of any host.
Author
Last update
2026/07/22 12:29 (dev-main)
License
Downloads
0

Comments
comments powered by Disqus

Laravel SSL Keeper

TLS certificate expiry reader for Laravel — fetches and parses the peer certificate of any host. Connects over TLS, captures the presented leaf certificate, and returns its "not after" expiry date as a Carbon instance. The package stores nothing and keeps no state: one contract, one call, one date.

Installation

composer require labrodev/laravel-ssl-keeper

Publish the config file:

php artisan vendor:publish --tag=ssl-keeper-config

Optionally override the defaults via environment variables:

SSL_KEEPER_TIMEOUT=10
SSL_KEEPER_PORT=443

Reading a certificate's expiry date

The service provider binds the SslExpiryReader contract to the concrete reader, so type-hint the contract and let the container inject it:

use Labrodev\SslKeeper\Contracts\SslExpiryReader;
use Labrodev\SslKeeper\Exceptions\SslCertificateUnparsable;
use Labrodev\SslKeeper\Exceptions\SslConnectionFailed;
use Labrodev\SslKeeper\Exceptions\SslNoCertificate;

class DomainCertificateCheck
{
    public function __construct(
        private readonly SslExpiryReader $sslExpiryReader,
    ) {}

    public function __invoke(string $host): void
    {
        try {
            $expiryDate = $this->sslExpiryReader->expiryDate($host);
        } catch (SslConnectionFailed|SslNoCertificate|SslCertificateUnparsable $exception) {
            // The message is user-presentable: "Unable to connect to example.com:443 (...)."
            report($exception);

            return;
        }

        $daysLeft = now()->diffInDays($expiryDate, false);
    }
}

Peer verification is deliberately disabled

The TLS handshake runs with verify_peer and verify_peer_name turned off. That is the point of the package: it reads the expiry date even from an expired certificate, a self-signed certificate, or an otherwise broken chain — exactly the certificates a monitoring tool most needs to look at.

Consequently, this reader must never be used as a trust decision. It tells you when a certificate expires, not whether the host should be trusted.

Exceptions

  • Labrodev\SslKeeper\Exceptions\SslConnectionFailed — the TLS connection could not be established; the message carries host, port, and the socket error.
  • Labrodev\SslKeeper\Exceptions\SslNoCertificate — the handshake succeeded but no peer certificate was presented.
  • Labrodev\SslKeeper\Exceptions\SslCertificateUnparsable — the certificate could not be parsed, or parsed without a usable expiry timestamp.

All three are built through ::make() and carry the hostname in a user-presentable message.

Testing

The raw socket work is isolated in Labrodev\SslKeeper\Services\TlsCertificateFetcher, so consuming apps can fake the network entirely — bind a fake fetcher in the container and every code path above it becomes testable without touching a real host.

composer test      # pest
composer phpstan   # larastan, level 7
composer pint      # laravel preset
composer check     # all of the above

License

MIT. See LICENSE.md.