Build your own certificate authority

DateReadtime 3 minutes Series Part 1 of Step CA tools Tags
ca / ssl / tls

Recently, I built my own CA using step and step ca by smallstep. They have created tools for secure automated certificate management.

Installation

On my VPS, I installed both the step cli and the step-ca cli tools. On the laptop, I just installed the step cli tool.

Instructions and packages

Setup

$ step ca init
✔ What would you like to name your new PKI? (e.g. Smallstep): Example CA
✔ What DNS names or IP addresses would you like to add to your new CA? (e.g. ca.smallstep.com[,1.1.1.1,etc.]): ca.example.com
✔ What address will your new CA listen at? (e.g. :443): :8443
✔ What would you like to name the first provisioner for your new CA? (e.g. you@smallstep.com): you@example.com
✔ What do you want your password to be? [leave empty and we'll generate one]:

Generating root certificate...
all done!

Generating intermediate certificate...

Generating user and host SSH certificate signing keys...
all done!

✔ Root certificate: /home/paul/.step/certs/root_ca.crt
✔ Root private key: /home/paul/.step/secrets/root_ca_key
✔ Root fingerprint: f86a0243f05130bcd159be795ac107fcffde748c9b29bf01a05c3dc41a865ccc
✔ Intermediate certificate: /home/paul/.step/certs/intermediate_ca.crt
✔ Intermediate private key: /home/paul/.step/secrets/intermediate_ca_key
✔ Database folder: /home/paul/.step/db
✔ Templates folder: /home/paul/.step/templates
✔ Default configuration: /home/paul/.step/config/defaults.json
✔ Certificate Authority configuration: /home/paul/.step/config/ca.json

Your PKI is ready to go. To generate certificates for individual services see 'step help ca'.

FEEDBACK 😍 🍻
    The step utility is not instrumented for usage statistics. It does not
    phone home. But your feedback is extremely valuable. Any information you
    can provide regarding how you’re using `step` helps. Please send us a
    sentence or two, good or bad: feedback@smallstep.com or join
    https://gitter.im/smallstep/community.

Running the CA

After ensuring your firewall will allow incoming connections to your server on the port configured above, you are ready to start making certs. Run the CA server on the remote machine:

$ step-ca $(step path)/config/ca.json
Please enter the password to decrypt /home/paul/.step/secrets/intermediate_ca_key:
2020/02/23 20:18:59 Serving HTTPS on :8443 ...

Configuration

Connecting laptop's step with remote step-ca is as easy as running a bootstrap command.

Query for the root cert's fingerprint on server (you can also get the fingerprint from the output of the init command):

step certificate fingerprint $(step path)/certs/root_ca.crt

Run the bootstrap command on the laptop (after replacing a couple variables):

$ step ca bootstrap --fingerprint $FINGERPRINT --ca-url $CA_URL
The root certificate has been saved in /Users/paul/.step/certs/root_ca.crt.
Your configuration has been saved in /Users/paul/.step/config/defaults.json.

Check that everything is connected successfully:

$ step ca health
ok

Certificate creation

$ step ca certificate localhost srv.crt srv.key
✔ Provisioner: you@example.com (JWK) [kid: S3ayxHbapfYPGIxr7W1PM1DRbAYE5Is4FfE1Cle-9xU]
✔ Please enter the password to decrypt the provisioner key:
✔ CA: https://ca.example.com:8443
✔ Certificate: srv.crt
✔ Private Key: srv.key

Example Program

The smallstep readme provides a small go program to test your new certs:

package main

import (
    "net/http"
    "log"
)

func HiHandler(w http.ResponseWriter, req *http.Request) {
    w.Header().Set("Content-Type", "text/plain")
    w.Write([]byte("Hello, world!\n"))
}

func main() {
    http.HandleFunc("/hi", HiHandler)
    err := http.ListenAndServeTLS(":9443", "srv.crt", "srv.key", nil)
    if err != nil {
        log.Fatal(err)
    }
}

To run the program:

go run srv.go

In another terminal, test the cert.

Failing request:

$ curl https://localhost:9443/hi
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

Successful request:

$ curl --cacert root.crt https://localhost:9443/hi
Hello, world!

Trusting your new Certificate Authority

To configure Firefox to trust the new CA, simply search the preferences for "View Certificates" from there you can manage both adding and removing your new CA.

Conclusion

It's pretty easy to setup your own CA using the tools built by smallstep. By following their instructions you can get trusted certificates for your internal personal projects in a couple hours.

Bonus

Renewing certificates:

$ step ca renew srv.crt srv.key
✔ Would you like to overwrite srv.crt [y/n]: y
Your certificate has been saved in srv.crt.

Check expiration and conditionally renew:

$ step ca renew srv.crt srv.key --expires-in 1h
certificate not renewed: expires in 13h58m44s

For more options on certificate renewals:

step ca renew --help