Automated certificate management using a CFSSL CA.
BSD-2-CLAUSE License
certmgr is a tool for managing certificates using CFSSL. It does the following:
It operates on certificate specs, which are JSON files containing the information needed to generate a certificate.
At regular intervals, certmgr
will check that the parameters set in a certificate spec match the PKI material on disk. certmgr
will take actions as needed in ensuring and regenerating PKI material as needed. If there's an error, a material refresh will happen at a later time.
When run without any subcommands, certmgr will start monitoring
certificates. The configuration and specifications can be validated
using the check
subcommand.
If you want to further understand the package logic, take a look at the godocs.
Note: certmgr
requires Go 1.11 or later due to cfssl dependency.
When appropriately configured, certmgr
will start a web server that
has the following endpoints:
/
just contains certmgr start time and current address./metrics
is the Prometheus endpoint (see the Metrics section).Prometheus is used to collect some useful certmgr
metrics. You can find them in the godoc.
The configuration file must be a YAML file; it is expected to be in
/etc/certmgr/certmgr.yaml
. The location can be changed using the
-f
flag.
An example certmgr.yaml
file is:
dir: /etc/certmgr.d
default_remote: ca.example.net:8888
svcmgr: systemd
before: 72h
interval: 30m
metrics_port: 8080
metrics_address: localhost
This contains all of the currently available parameters:
dir
: this specifies the directory containing the certificate specssvcmgr
: this specifies the service manager to use for restartingsystemd
(using systemctl
),sysv
(using service
), circus
(using circusctl
), openrc
(using rc-service
),dummy
(no restart/reload behavior), or command
(see the command svcmgr sectionbefore
: optional: this is the default duration before a certificate expiry that certmgr starts attempting tointerval
: optional: this is the default for how often certmgr
will check certificate expirationsinterval_splay
: optional: this is used to vary the interval period. A random time between 0interval
if specified. This defaults to 0.initial_splay
: if specified, a random sleep period between 0 and this value is usedmetrics_address
: specifies the address for the Prometheus HTTPmetrics_port
: specifies the port for the Prometheus HTTP endpoint.take_actions_only_if_running
: boolean, if true, only fire a spec's action if the service is actually running.A spec is used to manage PKI material for a consuming app. A spec does not have to request a certificate/key, and does not have to request a CA; it must request at least one of those two modes, however.
Said another way; you can use this to maintain a CA on disk. You can use this to maintain certificate/key pair signed by the given authority; you can do both modes if you wish, but one must be specified by the spec.
An example spec that writes both a CA and certificate key pair defined in JSON:
{
"service": "nginx",
"action": "restart",
"request": {
"CN": "www.example.net",
"hosts": [
"example.net",
"www.example.net"
],
"key": {
"algo": "ecdsa",
"size": 521
},
"names": [
{
"C": "US",
"ST": "CA",
"L": "San Francisco",
"O": "Example, LLC"
}
]
},
"private_key": {
"path": "/etc/ssl/private/www.key",
"owner": "www-data",
"group": "www-data",
"mode": "0600"
},
"certificate": {
"path": "/home/kyle/tmp/certmgr/certs/test1.pem",
"owner": "www-data",
"group": "www-data"
},
"ca": {
"path": "/etc/myservice/ca.pem",
"owner": "www-data",
"group": "www-data"
},
"authority": {
"remote": "ca.example.net:8888",
"auth_key": "012345678012345678",
"label": "www_ca",
"profile": "three-month",
"root_ca": "/etc/cfssl/api_server_ca.pem"
}
}
And this is an example that writes just the CA to disk:
{
"service": "nginx",
"action": "restart",
"authority": {
"remote": "ca.example.net:8888",
"auth_key": "012345678012345678",
"label": "www_ca",
"profile": "three-month",
"file": {
"path": "/etc/myservice/ca.pem",
"owner": "www-data",
"group": "www-data"
},
"root_ca": "/etc/cfssl/api_server_ca.pem"
}
}
A certificate spec has the following fields:
service
: this is optional, and names the service that the action
action
: this is optional, and may be one of "restart", "reload",svcmgr
: this is optional, and defaults to whatever the globalrequest
: a CFSSL certificate request (see below). If this is specified, a certificate
and private_key
field is required.private_key
and certificate
: file specifications (see below) forrequest
- if you wish to manage a certificate/key pair.authority
: contains the CFSSL CA configuration (see below).before
: optional: this is the default duration before a certificate expiry that certmgr starts attempting tointerval
: optional: this is the default for how often certmgr
will check certificate expirationsinterval_splay
: optional: this is used to vary the interval period. A random time between 0interval
if specified. This defaults to the managers default, which defaults to 0initial_splay
: if specified, a random sleep period between 0 and this value is usedtake_actions_only_if_running
: boolean, if true, only fire a spec's action if the service is actually running.key_usages
: optional: An array of strings defining what this key should be used for. Certmgr will consider a cert invalidNote: certmgr
will throw a warning if svcmgr
is dummy
AND action
is "nop" or undefined. This is because such a setup will not properly restart or reload a service upon certificate renewal, which will likely cause your service to crash. Running certmgr
with the --strict
flag will not even load a certificate spec with a dummy svcmgr
and undefined/nop action
configuration.
File specifications contain the following fields:
path
: this is required, and is the path to store the file.owner
: this is optional; if it's not provided, the current user isgroup
: this is optional; if it's not provided, the primary groupmode
: this is optional; if it's not provided, "0644" will beCFSSL certificate requests have the following fields:
CN
: this contains the common name for the certificate.hosts
: this is a list of SANs and/or IP addresses for thekey
: this is optional; it should contain an "algo" of either "rsa"names
: contains PKIX name information, including the "C"The CA specification contains the following fields:
remote
: the CA to use. If not provided, the default remote fromauth_key
: the authentication key used to request a certificate.auth_key_file
: optional, if defined read the auth_key from this. Ifauth_key
and auth_key_file
is defined, auth_key
is used.label
: the CA to use for the certificate.profile
: the CA profile that should be used.file
: if this is included, the CA certificate will be saved here. Itroot_ca
: optionally, a path to a certificate to trust as CA for thecommand svcmgr
and how to use itIf the svcmgr is set to command
, then action
is interpreted as a
shell snippet to invoke via bash -c
. Bash is preferred since
it allows parse checks to run. If Bash isn't available, parse checks
are skipped and sh -c
is used. If sh
can't be found, then this svcmgr
is disabled. The command svcmgr
is useful in Marathon environments.
Environment variables are set as follows:
In addition to the certificate manager, there are a few utilities functions specified:
check
: validates the configuration file and all the certificate-d /path/to/that/spec
clean
: removes all of the certificates and private keys specified-d /path/to/that/spec
to accomplish it.ensure
: attempts to load all certificate specs, and ensure that-d /path/to/that/spec
to accomplish this.genconfig
: generates a default configuration file and ensures theversion
: prints certificate manager's version, the version of GoThe certmgr
spec is included as SPEC.rst
.
To contribute, fork this repo and make your changes. Then, make a PR to this repo. A PR requires at least one approval from a repo admin and successful CI build.
Unit tests can be written locally. This should be straightforward in a Linux environment.
To run them in a non-Linux environment, have Docker up and run make test
. This will spin up a container with your local build. From here you can go test -v ./...
your files. This unconventional setup is because cfssl, the underlying logic of certmgr
, uses cgo.