A look at cfssl
• Mark Eschbach
OpenSSL is a great library with many great utilities. One knock against it though are the tools for maintaining a PKI. The tools feel raw and unfinished. I have been searching for a new tool. A while back someone recommened cfssl. Looks like it’s a decent tool.
Building
Release 1.3.3 does not have prebuilt binaries, which was a bit interesting. This means I had to build it from source
(screams in the background). cfssl uses the older style dependecy setup. go get -u
looks to grab prebuilt binaries
from somewhere, so that was a bit interesting and looks like I might be able to avoid building myself.
Generating a new CA
A new root certificate requires a CSR JSON file like the following:
{
"CN" : "test",
"name" : [
{
"C": "US",
"L": "Davis",
"O": "Mark Eschbach",
"OU": "PKI",
"ST": "California"
}
]
}
If the above is titled root.json
the examples show something like cfssl genkey -initca root.json | cfssljson -bare ca
.
By default this generates a new root which is good for 5 years. Curiously enough the Issuer
(and subject because
they are the same in the root) only contain the CN
property. Although looking at the documentation there is a
selfsign
subcommand.
selfsign
produces a series of warnings regarding how insecure the keys are. The first argument is a hostname and a
second is the CSR in JSON format like above.
Back to the original method. cfssljson
seems to convert the output of the key into a certificate. cfssl genkey
looks to be the configuration of interest. There is an optional configuration file which may allow me to tweak
additional parameters, such as including additional elements in the certificate.
Given an example of a valid test configuration I don’t think this is what I am looking for. When in doubt look in docs.
After reviewing the source for the csr
there is a member variable named ca
in JSON which contains the field expiry
which is passed to the func ParseDuration(s string) (Duration, error)
of time
.
The largest unit currently supported is hours. This means 10 * 24 * 265 = 85440h
for the field value. A full example
as follows for a reasonable length PKI certificate is as follows:
{
"hosts": [
"ca.example.com"
],
"key" : {
"algo" : "rsa",
"size" : 2048
},
"names" : [
{
"C": "US",
"L": "Davis",
"O": "Example Inc",
"OU": "PKI",
"ST": "California"
}
],
"ca" : {
"expiry" : "85440h"
}
}
Not bad for making it easier. Let us see what the pains are generating a signed key from this one.
Signing
One has to generate a CSR from the JSON in order to sign. This can be accomplished via
cfssl genky intermediate.json |cfssljson -bare intermediate-ca
. This will produce a new CSR. Unfortunately no matter
what options I try this does not result in a certificate which allows for intermediate CAs.