Sunday, February 14, 2016

Generate a certificate signing request (CSR) as a 1 liner

As I run my own (secure) web and mail server I frequently have to get certificates. You could run with a selfsigned certificate, but that is not ideal; desktop browsers are very noisy about them, and mobile browsers are outright hostile. Installing certificates on a mobile phone are no fun (though, hat of for CAdroid).

Now that Letsencrypt is live, I wanted to try it out. However, Letsencrypt does not make it easy for you to keep using the same private key. This is necessary as the Android's http client pins your certificates (the one I needed anyway). Luckily Letsencrypt allows you to use a CSR that is generated outside of their tools.

Letsencrypt certificates are only valid for a short time (90 days) so automation is key. Unfortunately, openssl does not make it easy to fully automate creating CSRs, especially when you need 'Alternative Names', a requirement from Letsencrypt.

Luckily I found a solution from Andrew Leahy. Here it is:

openssl req -new -nodes -sha256 -key private-key.pem \ -subj "/C=US/ST=CA/O=Acme, Inc./OU=Acme Example/CN=example.com" \ -reqexts SAN \ -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:example.com,DNS:www.example.com")) \ -out domain.csr

This will generate a CSR in file domain.csr with set country (C), state (ST), organization (O), organization unit (OU) and most importantly the common name (CN) and in addition two alternative names example.com and www.example.com. Thanks Andrew!