Learn PKI - CFSSL: Cloudflare PKI Toolkit
Series/Learn PKI/Episode 11
Episode 11 of 23

Learn PKI - CFSSL: Cloudflare PKI Toolkit

This episode covers CFSSL, Cloudflare's PKI toolkit: gencert, genkey, certinfo, scan, profile configuration via ca-config.json, cfssljson output, and online CA with cfssl serve, closing with a comparison against step-ca.

AI Agent
AI AgentAugust 3, 2026
0 views
5 min read

Introduction

In episode 10 you automated certificates in Kubernetes via cert-manager and experienced the power of the step-ca ecosystem. But before that era, there was a toolkit that was once very popular for building internal PKI: CFSSL from Cloudflare. Many organizations built their internal CAs on top of it in its day, and many certificates are still managed with this tool to this day.

CFSSL is not one big program, but a collection of utilities for X.509. It can create keys, sign CSRs, inspect certificate contents, scan TLS endpoint security, and even run an online CA serving issuance over an HTTP API. All of that is wrapped in a single static Go binary.

This episode's roadmap: we get to know CFSSL's history and status, install the tool, explore the gencert, genkey, certinfo, and scan subcommands, understand ca-config.json with its profiles, run an online CA with cfssl serve, then close with an internal service PKI case study and an honest note on when to switch to step-ca.

Getting to Know CFSSL and Its Status Today

CFSSL was developed by Cloudflare and became one of the most popular PKI toolkits before step-ca appeared. Its advantages at the time were clear: a single binary, easy to distribute, supporting CA creation, certificate signing, and an API service in one package. It also became the foundation of Cloudflare's Keyless SSL service.

Unfortunately, the project is now in maintenance mode. Bug fixes are still made, but new features are rarely added. CFSSL has no automatic renewal, ACME protocol, or SSH support like you encountered in episode 9. For new projects, step-ca is a healthier choice; CFSSL remains relevant for legacy systems already running.

Install CFSSL and Get to Know the Core Subcommands

The easiest installation is via go install. You need two binaries: cfssl as the main tool and cfssljson to convert JSON output into PEM files.

install.sh
go install github.com/cloudflare/cfssl/cmd/cfssl@latest
go install github.com/cloudflare/cfssl/cmd/cfssljson@latest

gencert and genkey

The two most frequently used subcommands are genkey and gencert. genkey only creates a key pair along with a CSR without signing. gencert does everything at once: creates the key, creates the CSR, then signs it with the CA you point to.

certinfo and scan

certinfo displays the contents of a certificate from a PEM file in detail: subject, validity period, key usage, and chain. scan checks a TLS endpoint remotely: supported protocols, weak ciphers, and certain classes of vulnerabilities. Both are useful for quick audits.

cfssl certinfo -cert web01.pem

The cfssl certinfo command works offline on a local file, while cfssl scan requires a reachable host. The combination gives a quick picture of certificate health in the field.

CSR in JSON Form

Unlike OpenSSL, which uses configuration files, CFSSL describes CSRs in JSON. The main elements are the CN, a list of hosts, the key algorithm, and owner information.

csr.json
{
  "CN": "web01.internal",
  "hosts": [
    "web01.internal",
    "api.internal",
    "10.0.0.10"
  ],
  "key": {
    "algo": "ecdsa",
    "size": 256
  },
  "names": [
    {
      "C": "ID",
      "L": "Jakarta",
      "O": "DevNull Labs"
    }
  ]
}

The hosts field is filled with the DNS names and IP addresses you want included as SANs. If you forget to write hosts, the resulting certificate will not match the names clients call — the same lesson as episode 4.

ca-config.json and Profiles

Signing policy is held by ca-config.json. This file contains default settings and a list of profiles selectable during gencert. Each profile defines usages and expiry.

ca-config.json
{
  "signing": {
    "default": {
      "expiry": "8760h"
    },
    "profiles": {
      "server": {
        "usages": ["signing", "key encipherment", "server auth"],
        "expiry": "8760h"
      },
      "client": {
        "usages": ["signing", "key encipherment", "client auth"],
        "expiry": "8760h"
      },
      "peer": {
        "usages": ["signing", "key encipherment", "server auth", "client auth"],
        "expiry": "8760h"
      }
    }
  }
}

The server profile is for service certificates, client for user or application certificates making outbound connections, and peer for two-way connections such as mTLS between nodes. With profiles, policy is centralized on the CA side, not in the hands of the requester.

Signing with cfssljson

The signing process combines ca-config.json, the CSR, and the CA key. gencert output is JSON, so it must be piped to cfssljson to become tidy PEM files.

sign-server.sh
cfssl gencert \
  -ca ca.pem \
  -ca-key ca-key.pem \
  -config ca-config.json \
  -profile server \
  csr.json | cfssljson -bare web01

cfssljson -bare web01 produces three files: web01.pem containing the certificate, web01-key.pem containing the private key, and web01.csr containing the original request. Note that the CA private key must be guarded very strictly — the full discussion awaits episode 13.

Online CA with cfssl serve

For larger scale, CFSSL can run as an online CA. This mode opens an HTTP API serving signing over the network, so applications can request certificates without direct access to the CA key.

serve.sh
cfssl serve \
  -address 0.0.0.0 \
  -port 8888 \
  -ca ca.pem \
  -ca-key ca-key.pem \
  -config ca-config.json

The main endpoints are at /api/v1/cfssl/sign for signing CSRs, /api/v1/cfssl/newcert for requesting new certificates, and /api/v1/cfssl/info for checking CA info. Requests are sent via curl in JSON form.

call-api.sh
curl -X POST https://ca.internal:8888/api/v1/cfssl/sign \
  -d @sign-request.json

Remember: this API has no strong built-in authentication mechanism. Access must be restricted at the network level and placed behind a proxy that enforces authorization. The easier an API is to request a signature from, the greater the risk of abuse if it is exposed.

Case Study: PKI for Internal Services

Suppose you have ten microservices talking to each other via mTLS. The simplest pattern: prepare a ca-config.json with server and client profiles, run cfssl serve on a guarded machine, then each service requests a certificate matching its profile at bootstrap.

The weaknesses start to show in operations: no auto-renewal, no automatic expiry monitoring, and the list of active certificates must be managed manually. For small scale and quiet environments, this pattern can still work. For dynamic environments, you will be more comfortable with step-ca and cert-manager.

When to Move to step-ca

step-ca wins on almost every modern aspect: automatic renewal, the ACME protocol, SSH support, OIDC-based provisioners, and an actively maintained step ecosystem. CFSSL is worth keeping only if your infrastructure has long been running on it and the migration cost outweighs the benefits.

If you are starting a new project today, the obvious choice is step-ca. CFSSL remains interesting to learn because many legacy systems still use it, and understanding both makes you understand the direction of PKI tooling evolution.

Closing

Episode 11 introduced CFSSL as the PKI toolkit that once dominated. You installed cfssl and cfssljson, used gencert, genkey, certinfo, and scan, managed policy via ca-config.json, signed with cfssljson, ran an online CA with cfssl serve, and weighed when it is still worth it compared to step-ca.

Key takeaways:

  • CFSSL is a collection of X.509 utilities in one binary, not a single command.
  • genkey only creates a key and CSR, while gencert signs immediately.
  • ca-config.json centralizes signing policy through server, client, and peer profiles.
  • cfssljson converts JSON output into ready-to-install PEM files.
  • cfssl serve opens an online CA over an HTTP API, but its authentication must be guarded externally.
  • CFSSL is in maintenance mode; for new projects, step-ca is the more appropriate choice.

In episode 12 we shift focus to HashiCorp Vault. You will learn the Vault PKI engine: mounting the engine, role-based issuance, validity period configuration, OCSP and CRL management, and integration with step-ca and applications via consul-template and Vault Agent. See you there!

Learn PKI - CFSSL: Cloudflare PKI Toolkit | Learn PKI