This is the barest possible NGINX configuration and Docker infrastructure I could create that would enable developing a Web site that is protected using client TLS using the DoD public key infrastructure (PKI).
In other words, you can build CAC-protected web sites using NGINX as the SSL termination point, starting from this baseline.
You should be on Linux, with the normal command line toolchain (shell, coreutils, etc.), along with curl, openssl and zip.
Of course, you'll need Docker installed as well to actually build the Docker image and launch new containers.
To build, just run make
.
This will:
- Download the base Docker image (alpine),
- Generate a new self-signed SSL cert,
- Download the DoD root certs and wrap them into a single file (to serve as the trusted set of certificates that can sign certificates presented by the CAC-holding client during TLS session negotiation),
- Install the new client CA and the new self-signed cert into the Docker image,
- Install nginx and a simple config into the Docker image, along with a sample index.html.
By default the new Docker image is called "nginx-cac".
From there you can run it by using make run
.
This will start a new container based on the image built, expose port 443 (inside the container) to a random port on the host.
Use docker ps
to ensure the new container is actually running. If so, Docker
will tell you which port on the host corresponds to port 443 in the guest.
In my case I had Firefox already configured to be able to authenticate against CAC-enabled websites, using PCSC Lite, the CACKey middleware, and by installing the DoD root certs and intermediate CA certs into the NSS keystore.
With "real" CAC sites already working, testing for me was a matter of going to
https://localhost:$PORT/
(replacing $PORT
with the actual port on the host
mapped to the guest's port 443).
I believe at this point it should already ask for the CAC PIN (as part of SSL mutual auth) and then show an error page that the site is untrusted.
After confirming a security exception for the NGINX server's self-signed certificate (I made it a temporary exception but permanent should work as well), Firefox reloaded the page and this time you should see "It works!".
If you look into the Developer Tools you should also see that NGINX has sent back your Subject Name information as a server response header.
I've also tested exporting the created Docker image (using
docker save nginx-cac:latest | gzip > nginx-cac.tar.gz
on the Linux host and using docker load
on a Win10 machine to import the
image).
The container ran fine on Windows and I was also able to test with Firefox, Chrome, and Microsoft Edge (with success on all 3).
As with Linux, you need to make sure you've setup your smartcard infrastructure (in my case I used OpenSC with Firefox) and that you've installed the DoD root and intermediate certificates into each browser.
Don't forget to shutdown the Docker container when you're done (Use docker ps
to find the short name of the running container and then docker stop $short-name
from there).
Because doing this all within DoD is so much harder than doing it in my off time. :(