spatie/ssl-certificate
A PHP package from Spatie that makes it easy to query SSL certificate properties. Fetch a certificate from a hostname, file, or string, then check validity, expiration dates, issuer, and key details.
daysUntilExpirationDate(), isValidUntil(Carbon $date) and isExpired() give you the primitives for a "90/30/7-day" alerting ladder. PM decision enabled: do we ship proactive expiry warnings (reducing support tickets and outage risk) or stay reactive?getDomains(), getAdditionalDomains() and wildcard-aware isValid($domain) let you answer "does our certificate actually cover www., api. and the new regional subdomain we just launched?" This directly informs decisions about launching new subdomains and consolidating vs. splitting certificates.getSignatureAlgorithm(), getPublicKeyAlgorithm(), getPublicKeySize(), usesSha1Hash() and isSelfSigned() turn "are we on SHA-1 / 1024-bit keys anywhere?" from an audit project into a scheduled report. This supports roadmap decisions on deprecating legacy integrations and preparing for CA/Browser Forum rule changes.SslCertificate::createForHostName() lets you verify the counterparty's certificate properties (issuer, validity window, key strength). Useful input for build-vs-buy and vendor-risk scoring, and for a pre-flight check in onboarding flows.toArray()/createFromArray(), getFingerprint(), getFingerprintSha256() and getSerialNumber() give you a snapshot you can store and diff over time — a cheap audit trail for "when did this certificate change?" questions from security or compliance.openssl_x509_parse glue and one-off shell scripts. Decision enabled: build the internal certificate dashboard on top of 200 lines of our own code plus this package, rather than buying a certificate-lifecycle SaaS seat per domain.Important scoping decision this package does not make for you: the README's own "Important notice" states it does not verify that a certificate is signed by a trusted authority. Treat it as a certificate property reader, not a TLS validator. Any roadmap item framed as "we validate TLS" cannot be satisfied by this package alone — pair it with actual handshake validation (curl/Guzzle, openssl s_client, or a scanning vendor) if trust is the requirement.
Adopt when:
createForHostName() is blocking I/O against a remote host.Look elsewhere when:
For executives (one paragraph): We can cut a recurring class of customer-visible outages — expired or mis-scoped TLS certificates — and answer security questions about our certificate estate, for the cost of a small MIT-licensed dependency rather than a per-domain SaaS contract. It gives us expiry dates, covered domains, issuer, key algorithm and size, and fingerprints as plain PHP objects, so we can add proactive expiry alerting and a crypto-posture report to the existing ops dashboard in days, not a quarter. It is a visibility tool, not a security control: it explicitly does not verify that a certificate is signed by a trusted authority, so we should position it as monitoring and inventory, and keep real TLS validation in the HTTP layer or a scanning vendor. Net: low cost, low lock-in, clear scope, no overclaiming.
For engineering (the practical case):
Spatie\SslCertificate\SslCertificate — named constructors (createForHostName, createFromFile, createFromString, createFromArray) plus a fluent downloader (usingPort, fromIpAddress incl. IPv6, withSocketContextOptions, usingSni, withFullChain, withVerifyPeer/withVerifyPeerName) and typed accessors returning Carbon instances or scalars.openssl_x509_parse code, handles wildcard matching edge cases (a wildcard does not cover the root domain), and is covered by a Pest test suite on GitHub Actions.createForHostName() performs blocking network I/O — wrap it in queued jobs with explicit timeouts, cache results, and never call it in a request path.toArray() snapshots; (2) alert thresholds at 30/14/7 days via isValidUntil(); (3) a "certificate health" panel reading the snapshots; (4) a one-off SHA-1 / small-key / self-signed sweep using usesSha1Hash(), getPublicKeySize(), isSelfSigned(). Step 4 is the highest-value, lowest-effort item — start there.CouldNotDownloadCertificate, invalid hostnames (InvalidUrl), invalid IPs (InvalidIpAddress), expired certs where you want the data (createForHostName($host, $timeout, false)), and certificates served differently behind a CDN. Log and surface these — a silent scan failure is worse than no scan.How can I help you explore Laravel packages today?