httpd-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Devin Bougie <Devin.Bou...@cornell.edu>
Subject Re: [users@httpd] accessing REMOTE_USER through an Apache proxy
Date Fri, 30 Oct 2009 16:30:42 GMT
Hi André,

Thank you very much for another thorough explanation.  This certainly  
does help clear up my confusion.  With the latest posted  
configuration, I am able to see the REMOTE_USER HTTP header from the  
backend GlassFish Web Application (using HttpServletRequest.getHeader 
("REMOTE_USER")).  As you explain, HttpServletRequest.getRemoteUser  
and getUserPrincipal both return null because they are looking for the  
REMOTE_USER cgi-bin environment variable.

For what it's worth, here is an excerpt from the CGI script I was  
testing with.  When calling the script directly, $REMOTE_USER is set  
but $HTTP_REMOTE_USER is not.  When accessing the script through the  
proxy (using the latest posted configuration), $HTTP_REMOTE_USER is  
set but $REMOTE_USER is not.
------
# test for $REMOTE_USER
if [ -z "$REMOTE_USER" ]; then
         echo '$REMOTE_USER not set.'
else echo "REMOTE_USER is $REMOTE_USER"
fi

# test for $HTTP_REMOTE_USER
if [ -z "$HTTP_REMOTE_USER" ]; then
         echo '$HTTP_REMOTE_USER not set.'
else echo "HTTP_REMOTE_USER is $HTTP_REMOTE_USER"
fi

echo ''
echo 'Environment is:'
printenv
------

I believe being able to access the REMOTE_USER HTTP header achieves  
our goal.  Thank you very much for all of your time and help.

Sincerely,
Devin

> I still have some lingering doubt about whether there is not a  
> confusion somewhere between
> - the Apache process's environment values (what it gets in its own  
> environment when it starts up)
> - the Apache "internal environment variables" (set internally by  
> Apache, for Apache only, during one request), which when using the  
> mod_jk connector to forward requests to Tomcat via AJP, become known  
> as "request attributes" (a better name, in my opinion, less confusing)
> - HTTP request headers and their content
> - cgi-bin environment values (set by Apache in the environment of a  
> child process just prior to running the cgi program in it).
>
> All these things above are distinct animals.  Apache does for  
> instance take the value of /some/ HTTP request headers, and  
> translates them into /some/ environment values for cgi-bin programs,  
> but the HTTP request headers and cgi-bin environment values are  
> distinct items, and there is not a one-to-one relationship between  
> them. They do not even necessarily have the same name.
>
> It took me a while to "click" on this, but I believe that what you  
> are seeing with your cgi-bin script is :
> - your Apache setup sets a HTTP Header "REMOTE_USER", and proxies  
> that modified request
> - the request is received by (another instance of) Apache, which  
> calls a cgi-bin script to handle it.
> - prior to calling the cgi-bin script, Apache picks up the content  
> of the HTTP header named "REMOTE_USER", and sets up that content as  
> a *cgi-bin environment variable* named "HTTP_REMOTE_USER".
> - then in your cgi script, you are not looking at the HTTP header  
> "REMOTE_USER" (which was received by Apache), but you are looking  
> for an *environment variable* "REMOTE_USER", which is not there.
> It is not there because the cgi-bin environment variable (as set by  
> Apache) is named "HTTP_REMOTE_USER".
> Get the difference ?
>
> A cgi-bin script does not, in general, have access to the HTTP  
> headers that came in with the request which caused Apache to run  
> this cgi-bin script.
> Instead, Apache "translates" *some* of these request HTTP headers  
> into cgi-bin environment variables, to which the cgi-bin program  
> *does* have access.
> (For example, Apache also splits off the query-string part of the  
> request URL, and passes it to the cgi-bin program as the environment  
> variable QUERY_STRING. But that was never a HTTP request header.)
>
> - But when you are going to pass this request to Glassfish, Apache  
> is not going to set up environment values for Glassfish.  It is  
> going to pass HTTP headers.  And one of them *will* be "REMOTE_USER:".
>
> So in fact you have already solved your problem.
> You are just testing it with the wrong tool.
> If your Apache server is set up with mod_perl, I could give you a  
> Perl cgi-bin script which would show you the difference.
> That's because under mod_perl, Perl cgi-bin scripts *can* ask Apache  
> for the original HTTP request headers.
>
>
> Devin Bougie wrote:
>> I have tried a different approach by moving the RewriteRules into  
>> the Location directive.  With this configuration, the  
>> HTTP_REMOTE_USER variable is set and visible by the backend script  
>> and application.  However, REMOTE_USER is still blank.  Here is the  
>> alternate configuration:
>> ------
>> <Location "/test">
>>        order deny,allow
>>        deny from all
>>        AuthType KerberosV5
>>        AuthName "W4restrict"
>>        KrbDefaultInstance net
>>        Satisfy any
>>        require valid-user
>>        RewriteEngine           on
>>        RewriteCond %{REMOTE_USER} (.+)
>>        RequestHeader Set Proxy-ip %{REMOTE_ADDR}e
>>        RequestHeader Set Host ourserver.com:443
>>        RequestHeader set REMOTE_USER %{REMOTE_USER}e
>>        RewriteRule ^/var/www/html/test/(.*) http://localhost/cgi-bin/test/$1 
>>  [P,L,E=REMOTE_USER:%{REMOTE_USER}]
>> </Location>
>> ------
>> And here is what we see in rewrite.log:
>> ------
>> 192.168.213.159 - dab66 [29/Oct/2009:11:04:47 --0400] [ourserver.com/sid#8885358][rid#971a7d0/initial

>> ] (3) [per-dir /test/] add path info postfix: /var/www/html/test - 
>> > /var/www/html/test/remote.cgi
>> 192.168.213.159 - dab66 [29/Oct/2009:11:04:47 --0400] [ourserver.com/sid#8885358][rid#971a7d0/initial

>> ] (3) [per-dir /test/] applying pattern '^/var/www/html/test/(.*)'  
>> to uri '/var/www/html/test/remote.cgi'
>> 192.168.213.159 - dab66 [29/Oct/2009:11:04:47 --0400] [ourserver.com/sid#8885358][rid#971a7d0/initial

>> ] (4) RewriteCond: input='dab66' pattern='(.+)' => matched
>> 192.168.213.159 - dab66 [29/Oct/2009:11:04:47 --0400] [ourserver.com/sid#8885358][rid#971a7d0/initial

>> ] (2) [per-dir /test/] rewrite /var/www/html/test/remote.cgi -> http://localhost/cgi-bin/test/remote.cgi
>> 192.168.213.159 - dab66 [29/Oct/2009:11:04:47 --0400] [ourserver.com/sid#8885358][rid#971a7d0/initial

>> ] (5) setting env variable 'REMOTE_USER' to 'dab66'
>> 192.168.213.159 - dab66 [29/Oct/2009:11:04:47 --0400] [ourserver.com/sid#8885358][rid#971a7d0/initial

>> ] (2) [per-dir /test/] forcing proxy-throughput with http://localhost/cgi-bin/test/remote.cgi
>> 192.168.213.159 - dab66 [29/Oct/2009:11:04:47 --0400] [ourserver.com/sid#8885358][rid#971a7d0/initial

>> ] (1) [per-dir /test/] go-ahead with proxy request proxy:http:// 
>> localhost/cgi-bin/test/remote.cgi [OK]
>> ------
>> Any suggestions for passing REMOTE_USER through an Apache proxy  
>> would be greatly appreciated.
>> Many Thanks,
>> Devin
>> On Oct 28, 2009, at 4:03 PM, Devin Bougie wrote:
>>> ... For what it's worth, I have tried inserting a RewriteCond to  
>>> make sure the proxy only occurs when REMOTE_USER is set.  This  
>>> cleaned up the rewrite.log file a bit, but the script is still not  
>>> able to see REMOTE_USER.  Here is our updated configuration and  
>>> rewrite.log.
>>>
>>> ------
>>> ######
>>> # GlassFish proxy
>>> ProxyPreserveHost       on
>>>
>>> RewriteEngine           on
>>> RewriteCond %{LA-U:REMOTE_USER} (.+)
>>> RewriteLog /var/log/httpd/rewrite.log
>>> RewriteLogLevel 9
>>>
>>> RequestHeader Set Proxy-keysize 512
>>> RequestHeader Set Proxy-ip %{REMOTE_ADDR}e
>>> RequestHeader Set Host ourserver.com:443
>>> RequestHeader set REMOTE_USER %{LA-U:REMOTE_USER}e
>>>
>>> RewriteRule ^/test$ /test/ [R,L]
>>> RewriteRule ^/test/(.*) http://localhost/cgi-bin/test/$1  
>>> [P,L,E=REMOTE_USER:%{LA-U:REMOTE_USER}]
>>> <Location "/test">
>>>       order deny,allow
>>>       deny from all
>>>       AuthType KerberosV5
>>>       AuthName "kerberos authentication"
>>>       Satisfy any
>>>       require valid-user
>>> </Location>
>>> ------
>>> ... [rid#8e23fc0/initial] (2) init rewrite engine with requested  
>>> uri /test/remote.cgi
>>> ... [rid#8e23fc0/initial] (3) applying pattern '^/test$' to uri '/ 
>>> test/remote.cgi'
>>> ... [rid#8e23fc0/initial] (3) applying pattern '^/test/(.*)' to  
>>> uri '/test/remote.cgi'
>>> ... [rid#8e23fc0/initial] (2) rewrite /test/remote.cgi -> http://localhost/cgi-bin/test/remote.cgi
>>> ... [rid#8e38648/subreq] (2) init rewrite engine with requested  
>>> uri /test/remote.cgi
>>> ... [rid#8e38648/subreq] (1) pass through /test/remote.cgi
>>> ... [rid#8e23fc0/initial] (5) lookahead: path=/test/remote.cgi  
>>> var=REMOTE_USER -> val=dab66
>>> ... [rid#8e23fc0/initial] (5) setting env variable 'REMOTE_USER'  
>>> to 'dab66'
>>> ... [rid#8e23fc0/initial] (2) forcing proxy-throughput with http://localhost/cgi-bin/test/remote.cgi
>>> ... [rid#8e23fc0/initial] (1) go-ahead with proxy request  
>>> proxy:http://localhost/cgi-bin/test/remote.cgi [OK]
>>> ------
>>>
>>> Our end goal is to proxy from the Apache server to a GlassFish  
>>> Enterprise Server.  Just for reference, here is the rewrite.log  
>>> for a request that's proxied to a GlassFish Web Application.
>>> ------
>>> ... [rid#8e23fc8/initial] (2) init rewrite engine with requested  
>>> uri /HelloWeb/UserServlet
>>> ... [rid#8e23fc8/initial] (3) applying pattern '^/HelloWeb$' to  
>>> uri '/HelloWeb/UserServlet'
>>> ... [rid#8e23fc8/initial] (3) applying pattern '^/HelloWeb/(.*)'  
>>> to uri '/HelloWeb/UserServlet'
>>> ... [rid#8e23fc8/initial] (2) rewrite /HelloWeb/UserServlet -> http://localhost:38080/HelloWeb/UserServlet
>>> ... [rid#8e1ffb8/subreq] (2) init rewrite engine with requested  
>>> uri /HelloWeb/UserServlet
>>> ... [rid#8e1ffb8/subreq] (1) pass through /HelloWeb/UserServlet
>>> ... [rid#8e23fc8/initial] (5) lookahead: path=/HelloWeb/ 
>>> UserServlet var=REMOTE_USER -> val=dab66
>>> ... [rid#8e23fc8/initial] (5) setting env variable 'REMOTE_USER'  
>>> to 'dab66'
>>> ... [rid#8e23fc8/initial] (2) forcing proxy-throughput with http://localhost:38080/HelloWeb/UserServlet
>>> ... [rid#8e23fc8/initial] (1) go-ahead with proxy request  
>>> proxy:http://localhost:38080/HelloWeb/UserServlet [OK]
>>> ------
>>>
>>> Any suggestions would be greatly appreciated.
>>>
>>> Thank you again,
>>> Devin
>>>
>>> On Oct 28, 2009, at 11:15 AM, André Warnier wrote:
>>>
>>>> Devin Bougie wrote:
>>>> ...
>>>>
>>>> Hi.
>>>>
>>>> I'll give you my interpretation, after looking at the log, not  
>>>> really at the configuration.
>>>>
>>>> I think the confusion may be about when and where, things happen  
>>>> exactly. And it is not really helped by your choice to proxy from  
>>>> your server to itself..
>>>>
>>>> If you examine the log below, you will see different/distinct  
>>>> requests, identified by their respective "rid" number.
>>>>
>>>> The first is the request rid#8aa28f8 that comes in originally, on  
>>>> your "first" server (before the proxying occurs).
>>>> That one does the proxying before your <Location /test> is even  
>>>> invoked (in my opinion).  So at that point, the authentication  
>>>> has not even happened, and REMOTE_USER is undefined or empty.
>>>> That request, you then proxy to your "second" server.
>>>>
>>>> Now the proxied request comes in to your "second" server. That is  
>>>> request rid#8aa8908.  That one starts without a REMOTE_USER (see  
>>>> above), but then goes through the <Location> section, where it  
>>>> acquires an id.
>>>> But by then it is too late for proxying..
>>>>
>>>> It would all probably be clearer if you set this up in two  
>>>> distinct VirtualHosts, and proxied from the first to the second.
>>>>
>>>> Another thing, is that Apache "environment variables", are kind  
>>>> of "virtual", in the sense that they exist inside of Apache, for  
>>>> the duration of one request.
>>>> When you proxy something to another server, this is a new  
>>>> request, and this other server does not magically inherit the  
>>>> environment of your first request in the first server.
>>>> To pass it on, you would have to set it in a header which you  
>>>> pass to the second server.  But then, you must have a value to  
>>>> pass, by the time you create the header.
>>>> Which does not seem to be the case here.
>>>>
>>>> Hope that is clear.
>>>> As for me, I think I need a cup of coffee now.
>>>>
>>>>
>>>>> ------
>>>>> ######
>>>>> # GlassFish proxy
>>>>> ProxyPreserveHost       on
>>>>> RewriteEngine           on
>>>>> RewriteLog /var/log/httpd/rewrite.log
>>>>> RewriteLogLevel 9
>>>>> RequestHeader Set Proxy-keysize 512
>>>>> RequestHeader Set Proxy-ip %{REMOTE_ADDR}e
>>>>> RequestHeader Set Host ourserver.com:443
>>>>> RequestHeader set REMOTE_USER %{LA-U:REMOTE_USER}e
>>>>> RewriteRule ^/test$ /test/ [R,L]
>>>>> RewriteRule ^/test/(.*) http://localhost/cgi-bin/test/$1  
>>>>> [P,L,E=REMOTE_USER:%{LA-U:REMOTE_USER}]
>>>>> <Location "/test">
>>>>>      order deny,allow
>>>>>      deny from all
>>>>>      AuthType KerberosV5
>>>>>      AuthName "kerberos authentication"
>>>>>      Satisfy any
>>>>>      require valid-user
>>>>> </Location>
>>>>> ------
>>>>> And here is what I see in rewrite.log.  REMOTE_USER is  
>>>>> eventually set properly, just not soon enough for the script.
>>>>> ------
>>>>> ... [rid#8aa28f8/initial] (2) init rewrite engine with requested  
>>>>> uri /test/remote.cgi
>>>>> ... [rid#8aa28f8/initial] (3) applying pattern '^/test$' to uri  
>>>>> '/test/remote.cgi'
>>>>> ... [rid#8aa28f8/initial] (3) applying pattern '^/test/(.*)' to  
>>>>> uri '/test/remote.cgi'
>>>>> ... [rid#8aa28f8/initial] (2) rewrite /test/remote.cgi -> http://localhost/cgi-bin/test/remote.cgi
>>>>> ... [rid#8aa4900/subreq] (2) init rewrite engine with requested  
>>>>> uri /test/remote.cgi
>>>>> ... [rid#8aa4900/subreq] (1) pass through /test/remote.cgi
>>>>> ... [rid#8aa28f8/initial] (5) lookahead: path=/test/remote.cgi  
>>>>> var=REMOTE_USER -> val=
>>>>> ... [rid#8aa28f8/initial] (5) setting env variable 'REMOTE_USER'  
>>>>> to ''
>>>>> ... [rid#8aa28f8/initial] (2) forcing proxy-throughput with http://localhost/cgi-bin/test/remote.cgi
>>>>> ... [rid#8aa28f8/initial] (1) go-ahead with proxy request  
>>>>> proxy:http://localhost/cgi-bin/test/remote.cgi [OK]
>>>>> ... [rid#8aa8908/initial] (2) init rewrite engine with requested  
>>>>> uri /test/remote.cgi
>>>>> ... [rid#8aa8908/initial] (3) applying pattern '^/test$' to uri  
>>>>> '/test/remote.cgi'
>>>>> ... [rid#8aa8908/initial] (3) applying pattern '^/test/(.*)' to  
>>>>> uri '/test/remote.cgi'
>>>>> ... [rid#8aa8908/initial] (2) rewrite /test/remote.cgi -> http://localhost/cgi-bin/test/remote.cgi
>>>>> ... [rid#8abcf90/subreq] (2) init rewrite engine with requested  
>>>>> uri /test/remote.cgi
>>>>> ... [rid#8abcf90/subreq] (1) pass through /test/remote.cgi
>>>>> ... [rid#8aa8908/initial] (5) lookahead: path=/test/remote.cgi  
>>>>> var=REMOTE_USER -> val=dab66
>>>>> ... [rid#8aa8908/initial] (5) setting env variable 'REMOTE_USER'  
>>>>> to 'dab66'
>>>>> ... [rid#8aa8908/initial] (2) forcing proxy-throughput with http://localhost/cgi-bin/test/remote.cgi
>>>>> ... [rid#8aa8908/initial] (1) go-ahead with proxy request  
>>>>> proxy:http://localhost/cgi-bin/test/remote.cgi [OK]
>>>>> ------
>>>>> Any suggestions would be greatly appreciated.  Please let me  
>>>>> know if there is any more information I can provide.
>>>>> Many thanks,
>>>>> Devin
>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> The official User-To-User support forum of the Apache HTTP Server  
>>>> Project.
>>>> See <URL:http://httpd.apache.org/userslist.html> for more info.
>>>> To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
>>>> "   from the digest: users-digest-unsubscribe@httpd.apache.org
>>>> For additional commands, e-mail: users-help@httpd.apache.org
>>>>
>>>
>
>
> ---------------------------------------------------------------------
> The official User-To-User support forum of the Apache HTTP Server  
> Project.
> See <URL:http://httpd.apache.org/userslist.html> for more info.
> To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
>  "   from the digest: users-digest-unsubscribe@httpd.apache.org
> For additional commands, e-mail: users-help@httpd.apache.org
>


---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
   "   from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org


Mime
View raw message