Perlbal Reproxy and HTTP Auth

I use Perlbal in one of the systems to reproxy requests to an internal URL. Reproxying to URL is a powerful feature that works like this.

  1. An HTTP request comes to Perlbal.
  2. Perlbal reverse-proxies it to one of its backend servers.
  3. Backend server does some work (in my case, does extensive verification of URL) but instead of returning entire response (status, headers, body), it returns X-REPROXY-URL header which includes a list of URLs.
  4. Seamlessly to end user, perlbal attempts to fetch content from one of these URLs, and returns that new content to the user.

The other day I found out that Perlbal can’t reproxy to URLs that require HTTP basic authentication. Here is a part of Perlbal that parses X-REPROXY-URL header and you can clearly see from regex, it treats URLs as (host, port, path) tuples (this is from ClientProxy.pm).

    # construct reproxy_uri list
    if (defined $urls) {
        my @uris = split /\s+/, $urls;
        $self->{currently_reproxying} = undef;
        $self->{reproxy_uris} = [];
        foreach my $uri (@uris) {
            next unless $uri =~ m!^http://(.+?)(?::(\d+))?(/.*)?$!;
            push @{$self->{reproxy_uris}}, [ $1, $2 || 80, $3 || '/' ];
        }
    }

And my backend Apaches do require http auth. What to do?

RTFM to the rescue! Apache provides a very cool feature - Satisfy (all|any) command. Essentially, it means that for a Directory or Location I can specify both http auth and IP based access control, and using Satisfy Any I can allow access if at least one of these conditions are met (default is Satisfy All).

Here is what it looks like in http config:

<Location /foo>
  # http auth
  AuthType basic
  AuthName "protected"
  AuthUserFile /etc/apache2/users
  Require valid-user

  order allow,deny
  # this is subnet where perlbal is running
  # backends see perlbal's reproxy requests from this subnet
  allow from 192.168.4 127.0.0.1
  satisfy any
</Location>

Alternatively, I would need to create a fake URI outside of http auth location and rewrite it with mod_rewrite, or possibly use a symlink - way less transparent.

Categories: software-engineering |