# Client Certificates in Mongrel

**URL:** <https://www.ruby-forum.com/t/client-certificates-in-mongrel/91859>\
**Category:** Rails\
**Created:** [April 12, 2007, 10:06pm UTC](https://www.ruby-forum.com/t/client-certificates-in-mongrel/91859 "2007-04-12T22:06:11Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![fredknowles](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/8baadc/32.png) [@fredknowles](https://www.ruby-forum.com/u/fredknowles)\
**Post date:** [April 12, 2007, 10:06pm UTC](https://www.ruby-forum.com/t/client-certificates-in-mongrel/91859/1 "2007-04-12T22:06:11Z")

</div>

I’m running Apache 2.2.4 w/SSL and required client authentication  
proxying to a Mongrel cluster. I can’t seem to figure out how to get  
the client\_certificate information out of my ruby App.

If I place \<%= debug(request.env) %\> into a view, the certificate  
information does not seem to be included in the headers. I’ve done alot  
of research on this and I’m just stumped.

Is there a directive to forward the Cert information via the proxy. I  
tried to set the %{SSL\_CLIENT\_CERT} via the RequestHeader set directive  
but that hasn’t exactly worked out for me.

---

<div class="post-metadata">

**Author:** ![fredknowles](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/8baadc/32.png) [@fredknowles](https://www.ruby-forum.com/u/fredknowles)\
**Post date:** [April 13, 2007, 1:55am UTC](https://www.ruby-forum.com/t/client-certificates-in-mongrel/91859/2 "2007-04-13T01:55:28Z")

</div>

I think the cert is just used by Apache for the SSL handshake… it’s  
not passed along as a header or anything (that would be a big header).

What I’ve done is to have Apache (in the SSL conf) add certain headers  
to the request if the cert is verified:

```
 RequestHeader set X_FORWARDED_PROTO "https"
 RequestHeader set X_SSL_VERIFIED "true"

```

and then check for these headers in the rails code.

HTH.

b

---

<div class="post-metadata">

**Author:** ![fredknowles](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/8baadc/32.png) [@fredknowles](https://www.ruby-forum.com/u/fredknowles)\
**Post date:** [April 13, 2007, 5:00am UTC](https://www.ruby-forum.com/t/client-certificates-in-mongrel/91859/3 "2007-04-13T05:00:14Z")

</div>

What I’d really like is the DN from the certificate so that I can  
filter information from within the Mongrel webspace and build a  
credential set from a corporate authorization webservice.

I can retrieve all the cert information from within a cgi script but  
I’d like to at the very least pass the ${SSL\_CLIENT\_CERT\_DN} via  
“RequestHeader set %DN\_orwhatever”- Is figuring out how to use Rewrite  
RemoteUser my best option? I may just have to resign myself to that.

You’d think that with the descriptive info contained in the cert you’d  
be able to use it within the app particularly if the servers you are  
forwarding to are trusted(located on the same physical server therefore  
sharing the same server cert etc.)

Am I fundamentally going about this the wrong way? Or does no one else  
do this.

Ben M. wrote:

> I think the cert is just used by Apache for the SSL handshake… it’s  
> not passed along as a header or anything (that would be a big header).
> 
> What I’ve done is to have Apache (in the SSL conf) add certain headers  
> to the request if the cert is verified:
> 
> ```
> RequestHeader set X_FORWARDED_PROTO "https"
> RequestHeader set X_SSL_VERIFIED "true"
> 
> ```
> 
> and then check for these headers in the rails code.
> 
> HTH.
> 
> b

---

<div class="post-metadata">

**Author:** ![fredknowles](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/8baadc/32.png) [@fredknowles](https://www.ruby-forum.com/u/fredknowles)\
**Post date:** [April 13, 2007, 6:12am UTC](https://www.ruby-forum.com/t/client-certificates-in-mongrel/91859/4 "2007-04-13T06:12:43Z")

</div>

Well, you’re pushing the boundaries of my knowledge here… maybe try  
dumping various ssl env vars[1] into the logs and see what you come up  
with?

That or maybe there’s an SSL wizard lurking out there?

b

[1] [mod\_ssl - Apache HTTP Server Version 2.2](http://httpd.apache.org/docs/2.2/mod/mod_ssl.html)

---

<div class="post-metadata">

**Author:** ![fredknowles](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/8baadc/32.png) [@fredknowles](https://www.ruby-forum.com/u/fredknowles)\
**Post date:** [April 24, 2007, 5:17pm UTC](https://www.ruby-forum.com/t/client-certificates-in-mongrel/91859/5 "2007-04-24T17:17:18Z")

</div>

Yeah me…I finally got it to work. I think I’ve gone through enough  
research, that I could write a book on how to lock down pretty much  
anything at this point.

I am now able to retrieve my DistinquishedName as the  
HTTP\_X\_FORWARDED\_USER environment variable in my proxied Mongrel  
instances. I wil now grab user credentials from our internal  
authorization service via webservices using that info.

I removed +FakeBasicAuth from the SSLOptions list which was apparently  
overriding the REMOTE\_USER and performed a Rewrite with the remote\_user  
mentioned in previous posts and forwarded that to the request header.

Here is my setup for creating a secure mongrel environment, if it can  
help anyone else save the effort that I went through:

\<VirtualHost\_default\_:443\>

\<Proxy balancer://mongrel\_cluster\>  
BalancerMember [http://127.0.0.1:8000](http://127.0.0.1:8000)  
BalancerMember [http://127.0.0.1:8001](http://127.0.0.1:8001)  
BalancerMember [http://127.0.0.1:8002](http://127.0.0.1:8002)

#General Set-up  
ServerName secure\_server.chirontech.com  
ServerAdmin fwkaufmATchirontechDOTcom  
ErrorLog /usr/local/apache2/logs/error\_log  
TransferLog /usr/local/apache2/logs/access\_log  
CustomLog /usr/local/apache2/logs/custom\_access\_log combined

#Protect Proxied-Redirects  
#Set an environment variable in the request header that informs  
#mongrel/Ruby that it is behind an https proxy:  
RequestHeader set X\_FORWARDED\_PROTO ‘https’  
SSLUserName SSL\_CLIENT\_S\_DN\_CN

ProxyPass / balancer://mongrel\_cluster/  
ProxyPassReverse / balancer://mongrelcluster/  
ProxyPreserveHost On

#Rewrite the REMOTE\_USER env variable into the request header  
RewriteEngine On  
RewriteCond %{LA-U:REMOTE\_USER} (.+)  
RewriteRule . -[E=RU:%1]  
RequestHeader add X-FORWARDED-User %{RU}e

SSLEngine on  
SSLCipherSuite  
ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSL2v2:+EXP:+eNULL

#Server Certificate  
SSLCertificateFile  
/usr/local/apache2/conf/certs/ssl.crt/mysecure\_server.crt

#Server Key  
SSLCertificateKeyFile  
/usr/local/apache2/conf/certs/ssl.key/mysecure\_server.key

#Server Certificate Chain:  
SSLCertificateChainFile /usr/local/apache2/conf/certs/ssl.crt/ca.crt

#Certificate Authority(CA)  
SSLCACertificateFile /usr/local/apache2/conf/certs/ssl.crt/ca\_root.crt

#Require Client Authentication via PKI  
SSLVerifyClient require  
SSLVerifyDepth 4

#AccessControl: currently allow only my sid through  
#Will use to restrict foreign partners from entering  
  
SSLRequire %{SSL\_CLIENT\_S\_DN\_\_CN}=~m/^.\*(fwkaufm)

#Export environment variables and certificate data  
SSLOptions +StdEnvVars +ExportCertData

#Define CustomLog  
CustomLog /usr/local/apache2/logs/ssl.request\_log   
“%t %h %{SSL\_PROTOCOL}x %{SSL\_CIPHER}x "%r" %b”

---

<div class="post-metadata">

**Author:** ![fredknowles](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/8baadc/32.png) [@fredknowles](https://www.ruby-forum.com/u/fredknowles)\
**Post date:** [February 29, 2008, 5:31am UTC](https://www.ruby-forum.com/t/client-certificates-in-mongrel/91859/6 "2008-02-29T05:31:35Z")

</div>

I am working on a similar situation. I need to get the value stored  
in  
SSL\_CLIENT\_S\_DN\_CN . We have been doing PKI authentication for  
sometime  
in PHP by getting the value of $\_SERVER[“SSL\_CLIENT\_S\_DN\_CN”] .

Now that I am trying some stuff in Rails I can’t seem to get anywhere.  
I try to do what you do above and I get a “Bad Request” when I have  
SSLUserName SSL\_CLIENT\_S\_DN\_CN in the httpd-ssl.conf file. I am able  
to  
get up and running when I comment it out.

Here is my config:

SSLRandomSeed startup builtin  
SSLRandomSeed connect builtin  
SSLRandomSeed connect file:/dev/urandom 512

Listen 443

AddType application/x-x509-ca-cert .crt  
AddType application/x-pkcs7-crl .crl

SSLPassPhraseDialog builtin

SSLSessionCache “shmcb:/var/run/ssl\_scache(512000)”  
SSLSessionCacheTimeout 28800

SSLMutex “file:/var/run/ssl\_mutex”

\<VirtualHost \*:443\>  
\<Proxy balancer://mongrel\_cluster\>  
BalancerMember [http://127.0.0.1:3000](http://127.0.0.1:3000)

# General setup for the virtual host

ServerName xxxxxxxxxxxxxx  
ServerAdmin xxxxxxxxxxxxxxx  
ErrorLog “/var/log/httpd-error.log”  
TransferLog “/var/log/httpd-access.log”

RequestHeader set X\_FORWARDED\_PROTO ‘https’  
SSLUserName SSL\_CLIENT\_S\_DN\_CN

ProxyPass / balancer://mongrel\_cluster/  
ProxyPassReverse / balancer://mongrel\_cluster/  
ProxyPreserveHost ON

#Rewrite the REMOTE\_USER env variable into the request header  
RewriteEngine On  
RewriteCond %{LA-U:REMOTE\_USER} (.+)  
RewriteRule . -[E=RU:%1]  
RequestHeader add X-FORWARDED-User %{RU}e

SSLEngine on  
SSLCipherSuite  
ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL

SSLCertificateFile “/usr/local/etc/apache22/ssl/xxxxxx.crt”  
SSLCertificateKeyFile “/usr/local/etc/apache22/ssl/privkey.pem”  
SSLCertificateChainFile “/usr/local/etc/apache22/ssl/chain.crt”

SSLCACertificatePath “/usr/local/etc/apache22/ssl.crt”  
SSLVerifyClient require  
SSLVerifyDepth 10

SSLOptions +StdEnvVars +ExportCertData

I pretty much cut and pasted what you had above.  
And in an controller I am just doing:

\<%= request.env['SSL\_CLIENT\_S\_DN\_CN'] %\>

also tried

\<%= request.env['HTTP-X-FORWARDED-SSL\_CLIENT\_S\_DN\_CN'] %\>

All I get is blank.

Any advice would be MUCH appreciated

On Apr 24 2007, 9:17 am, Fred K. \<rails-mailing-l…@andreas-
