Quick and easy Certificate Authority (CA) with a Certificate Revocation List (CRL) to automate generating Certificates (CRTs) for servers, clients, and users.
You will most likely wish to mount your CA directory externally, in which case, you will want to run as follows:
docker run -it -v /path/to/ca/:/opt/ --rm jnovack/my-cert-authority
Or more appropriately, up your Docker game with volume containers:
docker volume create --name ca-project.example
docker run -it --rm \
--mount source=ca-project.example,target=/opt/
jnovack/my-cert-authority
When running the container with an empty volume mounted, you will be
prompted to enter in the defaults for the openssl.cnf
file.
Running jnovack/my-cert-authority
without options will run in
interactive mode where you will create a Certificate Authority (CA),
followed by prompts for client certificates (CRTs).
Subsequent running of the container will prompt you for additional client certificates to create.
-q
- No output (can be combined with Actions)-a
- Print the Certificate Authority signing certificate-l
- Print the Certificate Revocation List certificate
-g commonName
- Generate a client certificate-r commonName
- Revoke a client certificate-p commonName
- Print client public certificate-k commonName
- Print client private key-u commonName
- Print uuencoded p12 certificate-i commonName
- Print client certificate information-e certificateType
- Client Certificate Type (server, user, client)
WARNING: It is not recommented to mix actions. No error-checking is performed.
Environment variables can override any field on a client certificate.
C
= countryST
= state or province nameL
= locality or city nameO
= organizationOU
= department or organizational unitEMAIL
= email addressed assigned to
WARNING: If you are using anything other than the default
policy = policy_optional
, changing the wrong environment variable can
prevent your certificate from being generated.
You can use the non-interactive flag (-n
) to generate and revoke
client certificates without user input.
-n
- Perform actions non-interactively
Once you complete the initial CA setup, you can quickly and easily
generate client certificates with a simple command-line. Generating
a certificate with -n
will accept all the defaults only overriding
where you set environment variables.
docker run -it --rm \
--mount source=ca-project.example,target=/opt/ jnovack/my-cert-authority
docker run -it --rm \
--mount source=ca-project.example,target=/opt/ jnovack/my-cert-authority \
-n -t client -g user.project.example
docker run -it --rm \
--mount source=ca-project.example,target=/opt/ jnovack/my-cert-authority \
-n -r user.project.example
docker run -it --rm \
--mount source=ca-project.example,target=/opt/ jnovack/my-cert-authority \
-cp user.project.example -k user.project.example
The PKCS12 file gets exported with uuencode
, you will need to uudecode
it
on your host machine to generate the file.
docker run -it --rm \
--mount source=ca-project.example,target=/opt/ jnovack/my-cert-authority \
-u user.project.example | uudecode
For security reasons, MacOSX does not let you import a .p12
file that does
not have a password.
You can verify the structure and state of the password of the .p12
file
from the command-line.
# with password
openssl pkcs12 -in user.p12 -nodes -clcerts -password pass:<password>
# without password
openssl pkcs12 -in user.p12 -nodes -clcerts -password pass:
If there is no password, you will be required to add one.
/opt
|-- root/
|-- ca/
| |-- private/
| | \-- ca.key (Certificate Authority Private Key)
| |
| |-- ca.crt (Certificate Authority Certficate)
| |-- ca.crl (Certificate Revocation List)
| |-- ca.serial (Next Certificate Serial Number)
| |-- crl.serial (Current CRL serial number)
| \-- database (Log of Certificate Authority activity)
|
|-- certs/
| \-- SERIAL.pem (Client Certificate + Text)
|
|-- private/
| |-- COMMONNAME.key (Client Private Key)
| |-- COMMONNAME.p12 (Client PKCS12 File)
| \-- COMMONNAME.pem (Client Key+Certificate)
|
|-- public/ (Public Sharable Directory)
| |-- certs/ (Client Certificates)
| | \-- COMMONNAME.crt (Client Certificate)
| |
| |-- ca.crt (Certificate Authority Certficate)
| \-- ca.crl (Certificate Revocation List)
|
\-- openssl.cnf (OpenSSL Configuration File)
The public/
directory is intended to be fully sharable. There are a
number of ways to accomplish this.
-
Periodically copy out the
public/
directory to another container or folder. -
Mount in a second volume specifically to
/opt/public/
so that certificates are available.
This is not for production. Repeat, this is NOT for production.
- You never, ever, ever want to store a CA key unencrypted.
- You never, ever, ever want to have a password-less CA key.
- You never, ever, ever want to leave a CA key lying around.
This is intended to be a quick-and-dirty CA management tool for development or home use. This container violates the above rules as a trade-off for a barrier-of-entry to development requiring certificates.
There is NO security on the CA key (no password, no encryption), and volumes and containers are just extensions of your file system.
I am constantly developing or testing some software that requires a CA and signed client certificates, and in order to minimize my setup time, I use this. I have no expectation that this is secure.
Sure, there's plenty of things I COULD do to make this secure, but then it will not be "quick and easy".
I could make an encrypted CA private key, but then I would not have the ability to go "non-interactive", as every cert would require you to enter in the password.
I could make an encrypted CA private key and then generate an intermediate CA with an unencrypted key. But then I would need to mash the root and intermediate certificates together in the downstream applications. You've worked with Intermediate CAs before, you know how annoying they are.
Eventually I will expand the project to include one or both of those options, but that is not today.