After reading how CloudFlare handles their PKI and that LetsEncrypt will use it I wanted to give CFSSL a shot.
Reading the project’s documentation doesn’t really help in building your own CA, but searching the Internet I found Fernando Barillas’ blog explaining how to create your own root certificate and how to create intermediate certificates from this .
I took it a step further I wrote a script generating new certificates for several services with different intermediates and possibly different configurations (e.g. depending on your distro and services certain cyphers (e.g. using ECC ) may not be supported).
I also streamlined generating service specific key, cert and chain files. 😀
Have a look at the full Gist or just the most interesting part:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash
#
# Author: Riyad Preukschas <riyad@informatik.uni-bremen.de>
# License: MIT
#
# Generates root, internediate CA and service keys.
function generate_root_ca() {
local root_ca="$1"
echo "Generating root CA into ${root_ca}/"
[[ ! -d "${root_ca}" ]] && mkdir "${root_ca}"
cfssl genkey -initca "${root_ca}_csr.json" | cfssljson -bare "${root_ca}/root"
}
function generate_intermediate_ca() {
local root_ca="$1"
local intermediate_ca="$2"
echo "Generating intermediate CA into ${intermediate_ca}/ (for root CA ${root_ca}/)"
[[ ! -d "${intermediate_ca}" ]] && mkdir "${intermediate_ca}"
cfssl gencert -ca "${root_ca}/root.pem" -ca-key "${root_ca}/root-key.pem" -config="config.json" -profile="intermediate" "${intermediate_ca}_csr.json" | cfssljson -bare "${intermediate_ca}/intermediate"
}
function generate_service_keys() {
local root_ca="$1"
local intermediate_ca="$2"
local service_type="$3"
local key_name="$4"
local dist_dir="${intermediate_ca}/dist"
echo "Generating ${service_type} key pair into ${intermediate_ca}/"
[[ ! -d "${dist_dir}" ]] && mkdir "${dist_dir}"
cfssl gencert -ca "${intermediate_ca}/intermediate.pem" -ca-key "${intermediate_ca}/intermediate-key.pem" -config="config.json" -profile="server" "${key_name}_csr.json" | cfssljson -bare "${intermediate_ca}/${key_name}"
cp "${intermediate_ca}/${key_name}.pem" "${dist_dir}/"
cp "${intermediate_ca}/${key_name}-key.pem" "${dist_dir}/"
case "${service_type}" in
dovecot)
cat "${intermediate_ca}/intermediate.pem" "${root_ca}/root.pem" > "${dist_dir}/${key_name}-cachain.pem"
;;
nginx)
cat "${intermediate_ca}/${key_name}.pem" "${intermediate_ca}/intermediate.pem" "${root_ca}/root.pem" > "${dist_dir}/${key_name}.pem"
;;
postfix)
cat "${intermediate_ca}/intermediate.pem" "${root_ca}/root.pem" > "${dist_dir}/${key_name}-cachain.pem"
;;
esac
}
# Foo root CA
ROOT_CA="foo-root-ca"
#generate_root_ca "${ROOT_CA}"
# Some intermediate CA
generate_intermediate_ca "${ROOT_CA}" "some-intermediate-ca"
generate_service_keys "${ROOT_CA}" "some-intermediate-ca" "nginx" "foo-some-web"
# Another intermediate CA
generate_intermediate_ca "${ROOT_CA}" "another-intermediate-ca"
generate_service_keys "${ROOT_CA}" "some-intermediate-ca" "dovecot" "foo-another-imap"
generate_service_keys "${ROOT_CA}" "some-intermediate-ca" "postfix" "foo-another-smtp"
View the code on Gist .
You’ll still have to deploy them yourself.
Update 2016-10-04:
Fixed some issues with this Gist.
Fixed a bug where intermediate CA certificates weren’t marked as CAs any more
Updated the example CSRs and the script so it can now be run without errors
Update 2017-10-08:
Cleaned up `renew-certs.sh` by extracting functions for generating root CA, intermediate CA and service keys.