How to use cfssl to create self signed certificates

There are man articles on CloudFlare’s PKI toolkit, but no single article had all the tasks detailed for the pattern I use, so I thought I’d put them here.

Installation on Linux

Unfortunately, at the time of writing, the latest packaged version (1.2) contains a bug that makes it impossible to create certificates with hosts, so the software must be installed with Go.

$ sudo apt install golang
$ go get -u github.com/cloudflare/cfssl/cmd/cfssl
$ sudo cp ~/go/bin/cfssl /usr/local/bin/cfssl
$ go get -u github.com/cloudflare/cfssl/cmd/cfssljson
$ sudo cp ~/go/bin/cfssljson /usr/local/bin/cfssljson

The Pattern

The root of all the certificates is a certificate authority (or “CA”) from which all other certificates are signed. Typically this is used to create one or more intermediate certificate authorities. These intermediates are used to sign certificates for clients, servers and peers (a host that can act as both a client and a server).

The Certificate Authority

To create a self signed certificate authority for a company called “Custom Widgets” based in London, England, Great Britain, create the following config file “ca.json”.

{
"CN": "Custom Widgets Root CA",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "GB",
"L": "London",
"O": "Custom Widgets",
"OU": "Custom Widgets Root CA",
"ST": "England"
}
]
}
$ cfssl gencert -initca ca.json | cfssljson -bare ca

Profiles

The next steps require a profile config file. The profile describes general details about the certificate. For example it’s duration, and usages.

{
"signing": {
"default": {
"expiry": "8760h"
},
"profiles": {
"intermediate_ca": {
"usages": [
"signing",
"digital signature",
"key encipherment",
"cert sign",
"crl sign",
"server auth",
"client auth"
],
"expiry": "8760h",
"ca_constraint": {
"is_ca": true,
"max_path_len": 0,
"max_path_len_zero": true
}
},
"peer": {
"usages": [
"signing",
"digital signature",
"key encipherment",
"client auth",
"server auth"
],
"expiry": "8760h"
},
"server": {
"usages": [
"signing",
"digital signing",
"key encipherment",
"server auth"
],
"expiry": "8760h"
},
"client": {
"usages": [
"signing",
"digital signature",
"key encipherment",
"client auth"
],
"expiry": "8760h"
}
}
}
}

The Intermediate CA

To create an intermediate certificate authority create the following config file “intermediate-ca.json”.

{
"CN": "Custom Widgets Intermediate CA",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "GB",
"L": "London",
"O": "Custom Widgets",
"OU": "Custom Widgets Intermediate CA",
"ST": "England"
}
],
"ca": {
"expiry": "42720h"
}
}
$ cfssl gencert -initca intermediate-ca.json | cfssljson -bare intermediate_ca
$ cfssl sign -ca ca.pem -ca-key ca-key.pem -config cfssl.json -profile intermediate_ca intermediate_ca.csr | cfssljson -bare intermediate_ca

Host Certificates

Here is an example host certificate config file “host1.json”.

{
"CN": "host.custom-widgets.com",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "GB",
"L": "London",
"O": "Custom Widgets",
"OU": "Custom Widgets Hosts",
"ST": "England"
}
],
"hosts": [
"host1.custom-widgets.com",
"localhost"
]
}
$ cfssl gencert -ca intermediate_ca.pem -ca-key intermediate_ca-key.pem -config cfssl.json -profile=peer host-1.json | cfssljson -bare host-1-peer
$ cfssl gencert -ca intermediate_ca.pem -ca-key intermediate_ca-key.pem -config cfssl.json -profile=server host-1.json | cfssljson -bare host-1-server
$ cfssl gencert -ca intermediate_ca.pem -ca-key intermediate_ca-key.pem -config cfssl.json -profile=client host-1.json | cfssljson -bare host-1-client

Installing The Certificates

Typically the public certificates are stored somewhere public, while the private keys are “locked away”; in particular the CA’s. We’re creating certificates for a development environment, but it simplifies things to put the certificates in expected places.

Update: 2019–11–08

I’ve created a makefile to automate this process here.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store