Build your own certificate authority
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.
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