Create your own certificate authority with openssl - part two
In the previous post we set up certificate authority (CA), installed a CA certificate in our browser and went through the process of signing and using some server certificates. In this we'll create some client certificates to identify ourselves with our servers. We'll then explore using these in a few different contexts; installing them in our browser, using them with curl and also with socat. As with the previous post, you can see it all tied together in this related github repo.
This post assumes you have the files generated in the previous post.
File name | Use |
---|---|
test-ca.key | private key for the CA |
test-ca.pem | root certificate (CA) |
test-server.key | private key for the server certificate |
test-server-*-csr.pem | certificate signing requests for server |
test-server-static-cert.pem | static server certificate |
Create a client certificate
Compared to creating a server certificate, which has lots of options, creating a client
certificate is pretty easy. First we create the private key. Note that if you want the
user to have to provide a password to use this client cert you just need to create a
passworded key and then use passin
and passout
when converting to PKCS later.
> openssl genrsa -out test-client.key 2048
Then we create our certificate signing request. Our subject can be pretty empty for a client cert.
> openssl req -new \
-subj "/C=GB" \
-key test-client.key \
-out test-client.csr
Then we create our signed client certificate.
> openssl x509 \
-req -in test-client.csr \
-passin pass:capassword \
-CA test-ca.pem -CAkey test-ca.key -CAcreateserial \
-out test-client.crt \
-days 1825 -sha256
In order to use this client certificate in a browser we need to convert it to PKCS.
> openssl pkcs12 -export -clcerts \
-in test-client.crt -inkey test-client.key -out test-client.p12
The steps to install it in the browser depend on the browser you're using. For Firefox you scroll right to the bottom of the Privacy & Security tab of Preferences. Here click on View Certificates then Your Certificates and finally Import your .p12 file.
Using the certificate with curl and socat is much simpler. We just need a combined PEM including the key, certificate and CA certificate.
> cat test-client.key test-client.crt test-ca.pem > test-client.pem
Then this can then be used with curl
> curl --cacert test-ca.pem --cert test-client.pem http://dev.test
or with socat
> socat \
tcp-listen:8096,fork,bind=127.0.0.1 \
openssl-connect:dev.test:443,cert=test-client.pem,cafile=test-ca.pem
Validating the client certificate
So far we've created a client certificate and seen how we can use it to talk to a server. In order to be useful though, this needs to be validated by the server.
Let us extend the nginx.vhost.conf
from the previous post. The relevant
options are
ssl_client_certificate
or
ssl_trusted_certificate
and
ssl_verify_client
.
nginx.vhost.conf
server {
listen 443 ssl;
server_name dev.test;
ssl_client_certificate /etc/nginx/ssl/certs/test-ca.pem;
ssl_verify_client on;
ssl_certificate /etc/nginx/ssl/certs/server-crt.pem;
ssl_certificate_key /etc/nginx/ssl/private/server.key;
location / {
return 200 'Static vhost test\n';
add_header Content-Type text/plain;
}
}
And here is the docker command to run it.
> docker run \
--rm -p 443:443 \
-v $(pwd)/nginx.vhost.conf:/etc/nginx/conf.d/default.conf:ro \
-v $(pwd)/test-server.key:/etc/nginx/ssl/private/server.key:ro \
-v $(pwd)/test-server-static-cert.pem:/etc/nginx/ssl/certs/server-crt.pem:ro \
-v $(pwd)/test-ca.pem:/etc/nginx/ssl/certs/test-ca.pem:ro
nginx
Now, if you still have all the configuration from the previous post, we should be able to test it out.
> curl --cacert test-ca.pem --cert test-client.pem http://dev.test
Static vhost test
or via socat
> curl localhost:8096
Static vhost test
And we're all done!