packages-http icon indicating copy to clipboard operation
packages-http copied to clipboard

SSL Certificate renewal

Open JanWielemaker opened this issue 8 years ago • 4 comments

Just setup a server using LetsEncrypt! Thanks to https://github.com/triska/letswicrypt that wasn't too hard. LetsEncrypt! certificates expire quickly though. Setting up automatic renewal of the certificates themselves isn't too hard, but how to update a (long) running server?

Ideally it would check the modification times of the certifications, but it can't because the LetsEncrypt! certificates are only readable by root and the server long lost the privileges to read them. I see two ways out:

  • Encrypt the private key and only read the password as root. If the key itself and the certificate chain are world readable (which is fine AFAIK as long as the private key is encrypted), it should be possible to update the SSL context used by the server without restart.
  • On startup read the expiration date from the certificate and commit suicide at some scheduled time the day before.

JanWielemaker avatar Dec 13 '16 18:12 JanWielemaker

I have added instructions to LetSWICrypt that describe how to renew the certificate without root permissions, please have a look. Simply set up a cron job (as a regular user) that renews the certificate if necessary, and restart your server to load the new certificate. This leads to a short downtime every 2 months or so.

Note also that you can use sni_hook/1 to get zero downtime already now (assuming client-side SNI of course): You can fetch the most recent certificate regularly, and supply it in the hook for each request.

In 7.5., I may work on exchanging certificate and key for a running SSL server.

triska avatar Dec 14 '16 23:12 triska

The new ssl_add_certificate_key/3 predicate proposed in https://github.com/SWI-Prolog/packages-ssl/pull/86 lets you update the certificate of an already created context.

Pending comments from OpenSSL developers whether this is an officially supported way to update the certificate: https://github.com/openssl/openssl/issues/2147.

If this works as intended, then we only need a hook that provides access to the SSL context of an HTTPS server. Given the context, we can easily update the certificates. Such a hook is necessary in any case, to add further certificates etc., as discussed in #77.

triska avatar Dec 26 '16 18:12 triska

All of this is solved in https://github.com/SWI-Prolog/packages-ssl/pull/87, please try it out!

triska avatar Dec 28 '16 20:12 triska

This is possible as of SWI-Prolog 7.3.34, and documented in the new section:

Exchanging certificates

You can use the predicates of library(ssl) to detect when it is time to renew a certificate, or rely on Let's Ecrypt to renew it automatically, and then simply use the updated certificate to negotiate new connections.

Remarkably, this can all be implemented in a thread-safe way in SWI-Prolog, although the underlying OpenSSL library is not thread-safe for this use case!

triska avatar Jan 08 '17 21:01 triska