Using Apache for pass-through authentication and DAV-SVN

The goal: How do you configure Apache to authenticate user and grant him an access to web pages based on their Unix permissions on a filesystem? Is that possible?

The problem we are facing here is that Apache daemon runs under single account and therefore can not access protected areas on NFS (or even local filesystem).

IIS can solve this using so called pass-through authentication, but with plan Apache you have no luck. But still – if you want to use Apache you have 2 options:

1. Apache accessing NFS via Kerberos

Quite nice option for NFS based filesystems is to use Kerberos authentication in Apache (via modules mod_auth_kerb, or more modern mod_auth_gssapi) to store user’s Kerberos credentials on webserver (typically in /tmp).

Web server can use this user credentials to make authenticated mount (if you have configured automounter) to the NFS server. You are effectively using this impersonate authenticated user identity behind user Apache daemon is running under.

Example:

Apache is running as user ‘apache’. Remote user ‘ondrejv’ authenticates on your web page, storing his credentials in /tmp/krb5cc_apache. This file is owned by user ‘apache’ but stores Ondrej’s credentials. Webserver then tries to access NFS share, rpc.gssd grabs the Kerberos cache, but since it contains Ondrej’s credentials, kernel creates GSS context with remote NFS server using Ondrej account.

This approach is nice, but does not work well with multiple simultaneous users trying to access different shares – given certain system user (apache), kernel establishes a certain GSS context for certain remote authenticated user. This context is then valid for some time so that subsequent authentication is effectively ignored.

2. Accessing NFS shares using Apache-ITK

Another interesting option is to use Apache-ITK, because since version 2.4, there is a promising parameter:

AssignUserIDExpr %{reqenv:REMOTE_USER}

which allows Apache to spawn a helper process under dynamically specified user. Unfortunately you can not use REMOTE_USER here directly (as mentioned above), because at the time apache spawns the helper process, user is not yet authenticated :-(.

To deal with this problem, we have to have two Apache servers running. First one (facing the LAN/Internet) doing authentication and forwarding REMOTE_USER identity hidden in specific HTTP header to second Apache worker server.

3. Adding DAV_SVN into the loop

Theoretically we have it solved. The only problem is with SVN as certain SVN operations can be only done with authenticated user – but since the worker server is not doing any authentication, we are out of luck…

… well, not exactly, we can use Basic anonymous authentication here to ‘forward’ user identity from the frontend server and authenticate the worker server, too – just to make SVN happy.

The complete configuration would then look like this, Frontend server:

<VirtualHost *:443>
 <Location />
 AuthType Kerberos
 AuthName "SVN Login"
 KrbVerifyKDC off
 KrbAuthRealms MYDOMAIN.COM
 KrbServiceName HTTP
 require valid-user

# Construct fake authentication header for the worker ITK behind us
# Put the username and dummy password
 AuthBasicFake %{REMOTE_USER} password

 RewriteEngine On
# We have to pass username in the HTTP headers so that ITK behind us knows which username to use
# unfortunately it can't use %{REMOTE_USER} directly 
 RequestHeader set Proxy-User %{REMOTE_USER}s
# strip Kerberos realm string
 RequestHeader edit Proxy-User @MYDOMAIN.COM ""
 ProxyPass "http://localhost/"
 ProxyPassReverse http://localhost/

 </Location>
</VirtualHost>

We are constructing fake authentication header here so that worker ITK can be authenticated as well and also defining Proxy-User header so that ITK knows which username to use for the helper fork process.

The ITK is (for security reasons) only listening on localhost. HTTPS is therefore not needed here:

<VirtualHost localhost:80>

AssignUserIDExpr %{HTTP:Proxy-user}

# As mentioned, we can use ITK to serve static HTML pages, too
# but since ITK runs as root, make sure no_root_squash is there for NFS
# ...no worries, filesystem permissions are still followed
 <Directory />
  Options Indexes FollowSymLinks
  AllowOverride None
  Order allow,deny
  Allow from all
 </Directory>
 
# DAV SVN is using anonymous authentication, this seems to be the only way
# how to make dav_svn believe we are authenticated
 <Location /my_svn_project>
  DAV svn
  AuthName "anonymous"
  AuthType Basic
  AuthBasicProvider anon
  Anonymous "*"
  require valid-user

  SVNParentPath /var/svnroot
  SVNListParentPath On
 </Location>
</VirtualHost>

Small disadvantage is that root account still needs to be able to browse the filesystem (so no_root_squash export option is needed on the NFS server). This is because ITK does not mask the core_map_to_storage(). This limitation only affect Apache’s ability to serve static HTML pages, not dav_svn / php / cgi.

Enjoy!

Using Apache for pass-through authentication and DAV-SVN

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s