I maintain a bunch of SSL certificates, mostly signed by my own site authority. Too many not to automate, but not enough to warrant heavy machinery. Here's how I do it.
Each certificate needs a config to describe what's in it. I create each of these and name it with a .cnf suffix. Here's an example:
[ req ] prompt = no distinguished_name = server_distinguished_name [ server_distinguished_name ] commonName = server.usefulinc.com stateOrProvinceName = England countryName = GB emailAddress = firstname.lastname@example.org organizationName = Useful Information Company organizationalUnitName = Hosting [ req_extensions ] subjectAltNameemail@example.com issuerAltName=issuer:copy nsCertType = server [ x509_extensions ] subjectAltNamefirstname.lastname@example.org issuerAltName=issuer:copy nsCertType = server
Let's say this config is server.cnf. I then just type make server.pem to generate the corresponding certificate and key, signed by my local certificate authority. As I don't want to attend the startup of every service, I ensure the key is password-less.
Here are the makefile steps I use to generate and sign keys.
.SUFFIXES: .pem .cnf .cnf.pem: OPENSSL_CONF=$< openssl req -newkey rsa:1024 -keyout tempkey.pem -keyform PEM -out tempreq.pem -outform PEM openssl rsa <tempkey.pem > `basename $< .cnf`_key.pem chmod 400 `basename $< .cnf`_key.pem OPENSSL_CONF=./usefulCA/openssl.cnf openssl ca -in tempreq.pem -out `basename $< .cnf`_crt.pem rm -f tempkey.pem tempreq.pem cat `basename $< .cnf`_key.pem `basename $< .cnf`_crt.pem > $@ chmod 400 $@ ln -sf $@ `openssl x509 -noout -hash < $@`.0
The resultant files are:
Some notes on these steps: my site-local certificate authority is in the directory usefulCA, along with an OpenSSL config which describes my preferences. This config was created by copying and making appropriate adjustments to the default /etc/ssl/openssl.cnf which ships with Debian.
For generating certificate signing requests to ship to a commercial certificate authority, it's a bit simpler. I save the config files with a .reqcnf suffix instead, and use this rule:
.SUFFIXES: .pem .cnf .reqcnf .csr .reqcnf.csr: OPENSSL_CONF=$< openssl req -newkey rsa:1024 -keyout `basename $< .reqcnf`.key -keyform PEM -out `basename $< .reqcnf`.csr -outform PEM
And finally, a rule I use to sign incoming certificate requests from other systems:
.csr.pem: OPENSSL_CONF=./usefulCA/openssl.cnf openssl ca -in $< -out `basename $< .csr`_crt.pem
I offer these without warranty in the hope they might be useful to somebody. They're not much more than a transcription of a how-to into a makefile, but it's just enough technology to ensure creating certificates isn't a big nuisance.
Why do I bother with a site-local CA, rather than just self-sign? It lets me bypass the annoyance of SSL warnings on clients once I've installed my own CA certificate, and gives me a coarse grained level of access control: for instance, only clients with certificates signed by my CA are allowed to access the site's LDAP server.
My personal next step with this is to integrate the certificate production process with my emerging Puppet recipes for managing local infrastructure.