Building an Internal PKI with Open Source Tools

This is the first in a series on creating an internal-use PKI using open source software and tools. This post will cover background and software/tool selection. Further posts will focus on specific topics within the broader scope, such as design considerations and architecture, software configuration, and automation. Thanks for reading, hopefully it will be useful to you down the road.


A couple of months back I was tasked with creating a brand new internal PKI for {{dayjob}}, from the Root CA on down. The impetus for the project was another project where TLS connections between servers had been mandated, and there was not a scalable solution in place. After a brief consultation, I went off on my merry way with the goal of creating a secure, reliable PKI that was compatible with all of the systems we use across the enterprise, including, but not limited to:

  • MacOS, Windows (multiple varieties), and Linux (mostly Ubuntu)
  • Safari, Chrome, Firefox, Edge, and IE browsers
  • JavaScript, Ruby, Python, and other language stacks
  • A number of other random edge cases

The choice of software and tools would also have to meet the following general requirements:

  • Be free or low cost
  • Be cross-platform. Like, all of the platforms. All of them.
  • Be relatively easy to implement (i.e. I can do it myself, without too much of a learning curve)
  • Be relatively easy to maintain
  • Allow me to see certificates that have been issued before, and revoke them

So basically, I'm asking for perfection, the Holy Grail, long life, and happiness, all for free. And rainbow unicorn farts. I'm sure this will be no problem. ¯\_(ツ)_/¯

Available PKI tools

There's a number of choices out there for PKI software/tools. Arguably the most common PKI in enterprise use is Microsoft's Active Directory Certificate Services (AD CS). It is baked into Active Directory, and provides tight integration into the enterprise compute environment, if you're using Windows, and you're maintaining an AD domain/forest. A recent(ish) entrant into the enterprise PKI game is CloudFlare's CFSSL tool, which was released in mid-2014. A third option is EJBCA, which is an open source PKI project written in Java. Since it's Java-based, it does get marks for being cross-platform. But from the docs it looked overly complicated to implement, and since it's Java-based, it loses points because I don't like Java. Finally, there's the OpenCA Project. While it is open-source and free to use, it is not available for Windows hosts, and hasn't had a significant update to its stable branch since August 2013, and no bug fixes since May of 2014. Not what I'd call a good choice for long-term viability.

Cut to the chase man…

I ended up going with CloudFlare's CFSSL with a PostgreSQL backend. Both are actively maintained and developed open-source projects, and have the features I ultimately needed in order to put the entire thing in place.

But Craine, you could have used AD CS. It's built into AD, and doesn't cost extra.

Well, yes dear reader, you make a point. AD CS is built in. But my reasons for not using it range from "AD CS is a tool of the Devil to make us insane", to "We don't use AD", to "I just don't like Microsoft products". Take your pick and hate me in the comments later.

CFSSL is open-source and is written in Go, so it hits the first bullet of free (as in licensing costs). It can be compiled for the Linux, Darwin (MacOS), and Windows operating systems, across the x86. x64, and ARM platform architectures, Hitting that second bullet of cross-platform-iness. It can also be compiled as a static binary with no external dependencies, so distribution is made easy, and is scriptable/automatable. It can be run as an Upstart service on Ubuntu, and has database drivers (PostgreSQL and MySQL) already in place for data persistence. Finally, It is easily configurable through JSON files, making setup a breeze.

I chose PostgreSQL over MySQL mostly due to the fact that we are already using Postgre elsewhere and I like to standardize on a platform and share code where ever possible. Clustering/HA also seemed like it would be easier to set up on Postgre than on MySQL.

For automation, I am using Chef, since that's what we already use for configuration management. It provides all of the capabilities and features that I needed to automate all the things. Even if it is written in Ruby.

Up next

The next post in the series will go over design choices, PKI architecture, and other planning type topics. Stay tuned...

comments powered by Disqus