Locksmith is a simple Golang application, which when supplied a config.yml
file will start a RESTful API via an HTTP server that will allow the management of Public Key Infrastructure.
$ ./locksmith [-config file]
A sample config.yml
can be found in this repository at configs/config.yml.example
Running Locksmith will do the following:
- Create a PKI Base Directory
- Start an HTTP Server
- Respond to requests, generating & serving authorities/certificates/keys/requests/revocations.
The API is served at the HTTP endpoint base path as defined in the configuration YAML.
You can find the API documentation in the docs/apis/ folder.
You can run Locksmith on almost any system due to it being a simple Golang binary. There are also resources to build a container easily, or you could alternatively pull it from Quay.
You can pull the pre-built application from the GitHub Releases page of this repository.
Since Locksmith is a binary that takes minimal execution time configuration it's perfect for use with SystemD as a persistent service that can start at system boot.
You can find an example SystemD service file located at init/locksmith.service. You can install it on a system with the following:
# Get the service file
sudo wget -O /etc/systemd/system/locksmith.service https://raw.githubusercontent.com/kenmoini/locksmith/main/init/locksmith.service
# Reload SystemD
sudo systemctl daemon-reload
# Enable/start the service - configuration required at /etc/locksmith/config.yml and Locksmith binary in $PATH
sudo systemctl enable locksmith
sudo systemctl start locksmith
Locksmith comes with a Containerfile
that can be built with Docker or Podman with the following command:
# Build the container
podman build -f Containerfile -t locksmith .
# Create the config
mkdir container-config
cp configs/config.yml.example container-config/config.yml
# Run the container
podman run -p 8080:8080 -v container-config/:/etc/locksmith locksmith
If you prefer to just use a pre-built container you can pull it from Quay via the following:
# Optional, pre-pull the image
podman pull quay.io/kenmoini/locksmith
# Create the config
mkdir container-config
cp configs/config.yml.example container-config/config.yml
# Run the container
podman run -p 8080:8080 -v container-config/:/etc/locksmith quay.io/kenmoini/locksmith
In case you'd like to run the Container-as-a-Service for the features containerization provides, you can utilize the resources named init/caas-*
The Podman container runtime is used by default - you can change it if you'd like in the init/caas-locksmith-vars.sh file.
The CaaS launcher also provides the ability for assigning resource limits, static networking, and other functions easily - modify for your needs prior to deploying.
# Get the Container-as-a-Service service files
sudo wget -O /etc/systemd/system/locksmith.service https://raw.githubusercontent.com/kenmoini/locksmith/main/init/caas-locksmith.service
sudo wget -O /etc/locksmith/caas-start.sh https://raw.githubusercontent.com/kenmoini/locksmith/main/init/caas-locksmith-start.sh
sudo wget -O /etc/locksmith/caas-stop.sh https://raw.githubusercontent.com/kenmoini/locksmith/main/init/caas-locksmith-stop.sh
sudo wget -O /etc/locksmith/caas-vars.sh https://raw.githubusercontent.com/kenmoini/locksmith/main/init/caas-locksmith-vars.sh
# Reload SystemD
sudo systemctl daemon-reload
# Enable/start the service - configuration required at /etc/locksmith/config.yml
sudo systemctl enable locksmith
sudo systemctl start locksmith
Since this is just a Golang application, as long as you have Golang v1.15+ then the following commands will do the job:
# Create the config
cp configs/config.yml.example config.yml
# Build the application (Golang 1.15+)
make build
# Run the application
./locksmith
Of course since this is easily containerized and a tasty Golang binary, it's very easy to deploy on Kubernetes and can scale with little effort.
In the deploy/kubernetes directory you can find a set of manifests to deploy onto a standard Kubernetes + Nginx Ingress + CertManager cluster.
# Apply the manifests
kubectl apply -f deploy/kubernetes/
-
Does this include any sort of authentication, rate limiting, etc?
No, that's the job of an API Gateway - this is more of a microservice so manage and secure accordingly.
-
Has this been architected for multi-tenancy?
Multiple root certificates and trusted signers? Yeah, sure.
Multiple customers/entities/non-trusted orgs? That's a horrible idea, so: no. This is a small binary service that is deployed first-class via containers, authenticated at an API Gateway, easily scaled out in a Kubernetes cluster. So your multi-tenancy would be better set at the PaaS layer with different namespaces/PVs/SAs/etc.
For the purposes of checking the generation of PKI via Locksmith/Golang against a standard OpenSSL generated PKI there are a set of resources to generate and compare the chains.
This can easily be done by running the following command:
./scripts/generate_test_pki.openssl.sh
With the default settings it will create a PKI chain with a Root CA, Intermediate CA, and Server Certificate with CRL in the .test_pki_root
directory.
The OpenSSL configuration files used to generate this PKI can be found in the /openssl_extras/
directory.
There is also a quick and easy way to generate a comparable chain via Locksmith by running the following:
./scripts/generate_test_pki.locksmith.sh
NOTE: This requires Locksmith to be available in the local directory - you can build it from source by running make build
Running that script will start Locksmith with the configs/config.yml.example
configuration, listening on port 8080. It will then run the required cURL requests locally to generate the PKI Chain that is available in the ./.generated
directory.
Another script can make your life easier when comparing PKI Chains to ensure the Subject, Issuer, Capabilities, and so on are aligned closely.
./scripts/generate_test_pki.compare.sh
This script will compare the two different PKI chains that were generated in the previous two steps.
You can run all three testing scripts with the following command:
./scripts/generate_test_pki.bundle.sh