The certificate nobody was watching: TLS as an availability problem
Ask a security team about TLS and you will hear about protocol versions, cipher suites and downgrade attacks. Ask an operations team and you will hear about the Sunday morning a certificate expired.
Both are TLS problems. Only one of them happens regularly.
The failure mode that fires#
An expired certificate is not a degradation. Browsers refuse the connection outright, API clients throw, and the service is down for everyone at once. There is no partial availability and no graceful path. The failure is total and instantaneous, at a moment determined months earlier by somebody who has probably changed teams.
It is also, uniquely among outages, known in advance to the second. The expiry date is printed in the certificate. Nothing else in operations gives you that much warning and gets ignored so reliably.
The reason it gets ignored is ownership. A certificate is issued during a project, by whoever was setting the thing up, and then belongs to nobody. Automated renewal solves it where it is deployed, and there is always something outside that: an internal service on a corporate CA, a partner's mutual-TLS endpoint, a load balancer somebody configured by hand, a certificate pinned into a mobile app.
Why "the padlock is green" is not a check#
The browser tells you the certificate is valid for the name you typed, from a CA your machine trusts, right now. Three conditions, all of which can be true while something is wrong:
- It expires in nine days. The padlock looks identical on day 90 and day 1.
- It is valid for
www.example.comand your API is onapi.example.com. Fine in the browser you tested; broken for the client you did not. - The chain is incomplete. Browsers often repair this by fetching the intermediate.
curl, Java clients and mobile stacks frequently do not, so it works for you and fails in production for somebody else. - The endpoint still accepts TLS 1.0. Nothing visible to a user, and it is what a compliance questionnaire will ask about.
Every one of those passes the eye test.
The configuration drifts even when nothing changes#
This is the part that surprises people. A TLS configuration that was excellent when it was written gets worse without anybody touching it, because the standard moves underneath it.
Cipher suites considered fine become deprecated. Protocol versions get formally retired. A configuration copied from a good blog post in 2019 is not a good configuration now, and nothing in the deployment will mention it. The service keeps serving.
So the check has to be periodic, not a one-time review. It is closer to a smoke test than to an audit.
What is worth checking, in order#
- Expiry, with enough warning to act. Thirty days is a reasonable floor; renewals need approvals sometimes.
- Name validity for the name clients use, including every alternative name, not just the one you tested.
- Chain completeness, because the browser hides this failure and other clients do not.
- Protocol versions offered, since old ones stay enabled for years after anybody needed them.
That is a short list, and it is nearly the whole value. TLS is unusual among security controls in having a small, checkable, high-consequence surface.
Where it fits in a pipeline#
TLS is checked against a running endpoint, so it does not belong in a code scan. It belongs wherever you check things about deployed services, on a schedule rather than on a commit.
Draugr's tls control probes each host a component declares and reports expiry, name validity,
chain and protocol support natively, without shelling out to another tool. It is a small enough
surface to do directly, and doing it directly means one less binary on the machine.
The TLS assessment guide covers the mechanics, and HTTP security headers is the other half of what is worth checking about a live host.