How can I tell Apache to force client authentication but to authorized based on a listed of trusted certificates rather than a CA?

Posted on

How can I tell Apache to force client authentication but to authorized based on a listed of trusted certificates rather than a CA? – Managing your servers can streamline the performance of your team by allowing them to complete complex tasks faster. Plus, it can enable them to detect problems early on before they get out of hand and compromise your business. As a result, the risk of experiencing operational setbacks is drastically lower.

But the only way to make the most of your server management is to perform it correctly. And to help you do so, this article will share nine tips on improving your server management and fix some problem about apache-2.2, ssl, authentication, , .

I am trying to create an Apache SSL server to be used in pre-production testing and that even in production would be accessed by less than 5 or so users. Because of the small user base, I felt that the easiest way to manage certificates would just be to self-sign them and then explicitly tell Apache to only trust the small number of certificates we create. From what I can tell, it seems like Apache needs a CA, though I’m hoping there’s a way around that.

Also, as far as development goes I tend to know my stuff but I am pretty much a newb at being a sysadmin so the simpler the better in terms of solutions.

As a side note, I also saw this post: here which I think is similar to what I’m asking but not quite a solution I’m looking for. Ideally, I could just use openSSL to generate self-signed certs on the fly and add copies of them to a directory so when they’re used to access the server Apache will let the connection be created.

Solution :

There are two things you need to do.

First, you need to generate certificates for the browsers that you are going to have connected.

Then, you need to set Apache to require these certs for some folder.

The apache portion is simple – just add this to your /etc/apache2/sites-enabled/your_apache_file.conf:

<Location /path/to/folder>
SSLVerifyClient require
SSLVerifyDepth 1

Now assuming you’ve set up your apache SSL like this:

SSLEngine on
SSLCertificateFile /etc/apache2/ssl/server.crt
SSLCertificateKeyFile /etc/apache2/ssl/server.key
SSLCACertificateFile /etc/apache2/ssl/ca.crt

SSLVerifyClient optional
SSLOptions +StdEnvVars +ExportCertData

You also need to set yourself up as a CA.

Here is a chunk of Python code we use for generating client certs – this should give you a good idea of what you need to do from here:

commonname = "name_of_client_machine"

serial_file = open('/usr/local/my/web/certs/','r')
serial =

cert_folder = '/usr/local/my/web/certs/clients/%s_%s' % (serial,commonname)


    os.makedirs(cert_folder, 0755)

except OSError:

commands.getstatusoutput("sed s/hostname/%s/ /usr/local/my/web/certs/client.tpl > %s/client.tpl" % (commonname,cert_folder))

commands.getstatusoutput("openssl genrsa -des3 -passout pass:mypassword -out %s/web_client.key 4096" % cert_folder)

commands.getstatusoutput("openssl req -new -key %(cert_folder)s/web_client.key -out %(cert_folder)s/web_client.csr -config %(cert_folder)s/client.tpl -passin pass:mypassword" % ({'cert_folder':cert_folder}))

commands.getstatusoutput("openssl x509 -req -days 3650 -in %(cert_folder)s/web_client.csr -CA /usr/local/my/web/certs/ca.crt -CAkey /usr/local/my/web/certs/ca.key -out %(cert_folder)s/web_client.crt -passin pass:mypassword"  % ({'cert_folder':cert_folder}))

commands.getstatusoutput("openssl pkcs12 -export -clcerts -in %(cert_folder)s/web_client.crt -inkey %(cert_folder)s/web_client.key -out %(cert_folder)s/web_client.P12 -passin pass:mypassword -passout pass:mypassword" % ({'cert_folder':cert_folder}))

Now you take the .p12 file and you import it into the client browser. You will be asked for the password (which above was just ‘mypassword’), and then it will be installed and ready to go.

After great struggle, we have finally found a solution. Not entirely ideal, but now that we have it in place it seems to be working well.

In Apache, we first had to enable mod_ssl, require client auth, and then set verify depth to 1. Then we had to set the server cert and key to something generated and signed by our CA (I’ll get to that in a minute) and set the SSLCACertificateFile to our CA’s cert. In so far as creating your CA, this guide was pretty thorough and I found it to be very accurate. Other than slightly modifying a few directory paths so that it worked with Ubuntu ie using /etc/ssl it worked fine. We created a CA, then generated a CA cert. We then generated a server key and server cert request, and signed the request with the CA. We then set Apache to use the new server cert and key. At that point, you were able to do server auth but not client auth. To do the later portion, we just built off of some of the examples already in the above link. The process for creating/signing cert-key combinations is generic ie you could use the combo on either a server or a client. So we just repeated the process to create a client cert (and could do it again and again to create more). Once we had that we converted the two files in a .pk12

# openssl pkcs12 -export -in certs/client.crt -inkey private/client.key -out ~/clientcred.p12

And finally we imported the cred into firefox for use. We also added our new CA to firefox’s internal list of trusted CA’s. Hope this helps anybody else who is trying something similar.

Leave a Reply

Your email address will not be published.