Setting header based on client certificate

apache-2.2authenticationreverse-proxy

I have Apache running as a reverse proxy for an internal server. Users hitting the proxy are required to use client certificates. On the internal server, there is a web application that can use an HTTP header for authenticating users. I would like to have the proxy provide that header based on the client certificate.

The header value is the user's id. Ideally I would have a text file mapping user id to certificate. Near as I can tell, I need RewriteMap but for headers.

# Somehow lookup USERID given SSL_CLIENT_S_DN
RequestHeader set X-User-ID %{USERID}

I'd like to avoid a whole bunch of SetEnvIfs requiring server restarts to change, e.g.:

SetEnvIf SSL_CLIENT_S_DN [User 1's SSL_CLIENT_S_DN] USERID=12
SetEnvIf SSL_CLIENT_S_DN [User 2's SSL_CLIENT_S_DN] USERID=34
SetEnvIf SSL_CLIENT_S_DN [User 3's SSL_CLIENT_S_DN] USERID=56
...

Is there a good way I can avoid the users from needing to essentially authenticate twice?

Best Answer

I think I understand what you need, but please correct me if I'm wrong. This requires a 3 stage approach.

You use a RewriteCond with a RewriteMap to map the SSL_CLIENT_S_DN to a USERID, a RewriteRule to set an environment variable and then a RequestHeader directive to set a header based on the environment variable. This should cause the header to be passed onto the internal server normally.

Something like:

RewriteEngine On
# Define a RewriteMap for DN to user id
RewriteMap dntouserid "txt:/path/to/dntouserid.txt"
# Test if we have something in the map for a the current DN
RewriteCond  ${dntouserid:%{SSL:SSL_CLIENT_S_DN}} (.+)
# Set environment variable based on that mapping. %1 comes from the RewriteCond
RewriteRule ^ - [E=MYUSER:%1]
# Set header to that environment variable
RequestHeader set X-User-ID %{MYUSER}e

And then your map contains lines like:

DN_OF_USER1 12
DN_OF_USER2 34
DN_OF_USER3 56

If the DN contains spaces you will have to use an external program to do the map rather than a plain text file (it might work for other map types, but I've not tried myself).

Related Topic