On a healthcare application I work on, the connections to France’s national health services rely on client certificates: patient identity verification (INSi), secure messaging (MSSanté) and practitioner login. The health sector’s certificate authority issues them for three years. That’s long enough for whoever did the last renewal to have forgotten everything, and short enough for the deadline to land while the product is still in use.
A rare procedure is always a first time
Renewing one of these certificates takes a professional smart card in a reader, a web portal, a private key to generate, a format to get right, a place to store the result, and then a deploy. Each step is easy. Chaining them together once every three years, with an expiry date looming, is exactly the kind of work where people make mistakes.
The identity service is a good example. It rejects any certificate that doesn’t carry one specific name, and nothing warns you when you request it: you find out when calls start failing in production. A rule like that lives in the head of whoever got burned by it, until they forget.
So I replaced the procedure with one command per certificate. It generates the key, requests the renewal with the technical administrator’s card, retrieves the certificate and checks that it matches the key, the right organization and the right authority. It refuses a name that isn’t the expected one, then writes the result into the application’s encrypted secrets. If it fails halfway, you run it again and it picks up where it stopped. The previous certificate stays valid and is kept, and a second command puts it back if the new one misbehaves.
A check that can’t fail proves nothing
Writing the certificate to the right place doesn’t mean it will be accepted. Before deploying, a check command sends the real identity service a lookup for a fictitious patient. “No identity found” is the answer you want, because it proves the server accepted the certificate and processed the request, whereas a rejected certificate gets dropped during the TLS handshake.
For secure messaging, the same check passed with a self-signed certificate. A successful connection could not verify the issuer. The command therefore sticks to local checks (key, certificate chain) and says so. A check that always passes is worse than no check at all, because it reassures you.
Knowing it broke before users do
A daily alert already flagged certificates thirty and then seven days before expiry. What was missing was the certificate that is still valid but rejected by the server: the background job that fetches messages wrote it to its logs after retrying, and nobody reads the logs of a job running in the background. That failure now surfaces as an error, and the expiry alert gives the command to run instead of pointing to a document.
The last point is about governance more than technology. Some of these certificates had been issued in the name of the company that builds the software rather than the organization that runs it. The renewal was the occasion to move them to their actual owner, so the software keeps working on the day someone else maintains it.
Two questions to ask
Every multi-year deadline (certificates, domain names, API keys, accreditations) is an outage with a known date. For each one, you only need to know who can renew it without digging around, and how you confirm the renewal worked before a user finds out.