Forum: Ruby on Rails Client Certificates in Mongrel

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Fred K. (Guest)
on 2007-04-13 00:06
  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.
Ben M. (Guest)
on 2007-04-13 03:55
(Received via mailing list)
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
Fred K. (Guest)
on 2007-04-13 07:00
  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
Ben M. (Guest)
on 2007-04-13 08:12
(Received via mailing list)
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] http://httpd.apache.org/docs/2.2/mod/mod_ssl.html
Fred K. (Guest)
on 2007-04-24 19:17
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
   BalancerMember http://127.0.0.1:8001
   BalancerMember http://127.0.0.1:8002
</Proxy>

#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
<Location/>
   SSLRequire %{SSL_CLIENT_S_DN__CN}=~m/^.*(fwkaufm)
</Location>

#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"

</VirtualHost>
(Guest)
on 2008-02-29 06:31
(Received via mailing list)
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
</Proxy>

#   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

</VirtualHost>


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

<p><%= request.env['SSL_CLIENT_S_DN_CN'] %></p>
also tried
<p><%= request.env['HTTP-X-FORWARDED-SSL_CLIENT_S_DN_CN'] %></p>

All I get is blank.

Any advice would be MUCH appreciated


On Apr 24 2007, 9:17 am, Fred K. <rails-mailing-l...@andreas-
This topic is locked and can not be replied to.