Push http header into cookie - apache

I'm trying to propagate an http header across proxies using a cookie from apache 2.4 to nginx.
Apache is only around to do kerberos authentication against Active Directory. Due to the overhead that the AD authentication adds to every get request, I want to limit the authentication. The idea is to set a cookie that expires after x time and only perform the auth through apache if the cookie doesn't exist.
Furthermore, I want the remote_user from apache made available to nginx.
Nginx listens on port 80, and does an auth sub-request to apache on port 81 (same host)
I am able to set http headers in apache, but these get lost in nginx land.
I first tried reading the specific http header that I am interested in from nginx, but I can't see it once the request is transferred to nginx, although I can see them being set on the apache side.
My second idea was to push the header that I am interested in to a server cookie and then extract it in the nginx side, but the cookie value is always empty.
In the apache conf I have:
RewriteRule .* - [E=PROXY_USER:%{LA-U:REMOTE_USER}]
Header add X-Auth-User %{PROXY_USER}e
I can see that header fine on the apache side, but nothing on the nginx side.
Trying to pump the data into a cookie in apache:
RewriteCond %{LA-U:REMOTE_USER} (.*)
RewriteRule ^/ - [env=COOKIE1:%1]
RewriteRule .* - [CO=acaprox:tst=%{COOKIE1}e:.my-domain.com:300:/] [R=307,L]
The trouble with this approach is that the value of test is always empty.
I also tried reusing the environment variable that I can successfully push into the header, into the cookie, but it is also always empty:
RewriteRule .* - [CO=cookietest:tst=%{ENV:PROXY_USER}:.my-domain.com:300:/] [R=307,L]
As is probably blatantly obvious, I don't have much experience in this space.

The issue appears to be related to remote_user, other variables work with the approach I was using.
The solution for me was to set an additional header at the upstream proxy (ie, x-remote-user), and then pull the value from it if the auth_request was successful.
auth_request $user $upstream_http_x_remote_user
The $user variable can then be pushed into a cookie

Related

How can I use mod_rewrite to proxy the userinfo component of a URI?

This has been driving me crazy. I have a web application that's being served via Apache Web Server. The database server that backs the application is Apache CouchDB, which exposes an HTTP API to retrieve documents and stream attachments.
I've secured the CouchDB database by providing a security object, which only allows certain users to access data within the database, and returns 401 for anonymous requests to HTTP endpoints.
I want to be able to map public URLs to document attachments stored within this database. So, I've attempted to create a rewrite rule inside my .htaccess file that proxies requests from certain URLs directly to CouchDB, while hardcoding the user credentials, like so:
## DOWNLOAD STREAM:
RewriteCond %{HTTP_HOST} ^domain.com$
RewriteRule download/(.*) http://user:pass#127.0.0.1:5984/database/$1 [P]
In an ideal world, the above example would take the following URL:
http://domain.com/download/UUID/attachment.ext
And proxy it to:
http://user:pass#127.0.0.1:5984/database/UUID/attachment.ext
This method does indeed proxy the request to CouchDB, but omits the userinfo component of the URI scheme. So, the request is treated as anonymous and I get a 401 error. The attachment is only streamed if I remove security from the database.
I've spent a couple of hours reading up on Apache configuration and experimenting to no avail. Web searches are fruitless because of all the related queries with similar keywords.
How can I ensure that mod_rewrite includes the username and password provided in the rewrite rule when it proxies to CouchDB?
I figured it out! Rather than including the username:password as part of the URI scheme, the Authorization header needs to be set independently. The following solution works completely within a .htaccess file, which is important since OS X periodically blows away settings inside VirtualHost sites:
SetEnvIf Request_URI ^/download/* ADD_COUCH_BASIC_AUTH
RequestHeader set Authorization "Basic XXXXXXXXXXXX" env=ADD_COUCH_BASIC_AUTH
## DOWNLOAD STREAM
RewriteCond %{HTTP_HOST} ^example.com$
RewriteRule download/(.*) http://127.0.0.1:5984/database/$1 [P]
The way this works: we use SetEnvIf to check whether the request path matches the path we want to proxy, and if so, set an arbitrary environment variable ADD_COUCH_BASIC_AUTH
On the subsequent line, we add a Basic Auth header to the outgoing request, only if the environment variable we set exists. So, the basic auth header will only be added when requesting a resource via /download/, thus sending authentication credentials to CouchDB.
Note: you'll have to Base64-encode your username:password credentials, and replace XXXXXXXXXXX with the encoded value. An easy way to do this, on a Mac:
echo -n 'user:pass' | openssl base64
Hope this helps somebody besides me!

Edit Set-Cookie header only on specific redirects

In some cases my web application responses with a redirect (302) to another application and simultanously sets a cookie to the user Browser. What I want is apache to catch the "Set-Cookie" header and alter it (eg. make the cookie secure). However, I want this to happen only for redirects to a specific domain. For all the other redirects I want the cookie to remain untouched:
<if response is redirect to http://my.certain.domain.gr> <-How to implement this condition?
Header edit Set-Cookie ^(.*)$ $1;Secure;
This needs to be done (if possible) within apache configuration rather that altering the application code for reasons that are out of my responsibility.
How can this be achieved in apache?

Redirection on Apache (Maintain POST params)

I have Apache installed on my server and I need to redirect from http to https. The reason for this is our load balancer solution cannot hand https so requests come in on http and then we transfer them to https using the below lines in the httpd.conf file.
<VirtualHost 10.1.2.91:80>
Redirect 302 /GladQE/link https://glad-test.com/GladQE/link.do
</VirtualHost>
This works fine for GET requests but POST requests will lose the parameters passed on the URL. What would be the easiest way to perform this redirect and maintain POST params?
I need to get from http://glad-test.com/GladQE/link.do to here https://glad-test.com/GladQE/link.do maintaining POST params
Thanks
Tom
You can try with the HTTP status code 307, a RFC compilant browser should repeat the post request.
Reference: http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
In contrast to how 302 was historically implemented, the request
method is not allowed to be changed when reissuing the original
request. For instance, a POST request should be repeated using another
POST request.
To change from 302 to 307, do that:
<VirtualHost 10.1.2.91:80>
Redirect 307 /GladQE/link https://glad-test.com/GladQE/link.do
</VirtualHost>
Standard Apache redirects will not be able to handle POST data as they work on the URL level. POST data is passed in the body of the request, which gets dropped if you do a standard redirect.
You have an option of either using a PHP script to transparently forward the POST request, or using a combination of Rewrite (mod_rewrite) and Proxy (mod_proxy) modules for Apache like follows:
RewriteEngine On
RewriteRule /proxy/(.*)$ http://www.example.com/$1 [P,L]
P flag passes the request to the Proxy module, so anything that comes to your site (via GET or POST doesn't matter) with a URL path starting with a /proxy/ will transparently be handled as a proxy redirect to http://www.example.com/.
For the reference:
http://httpd.apache.org/docs/current/mod/mod_rewrite.html
http://httpd.apache.org/docs/current/mod/mod_proxy.html
Either your public facing website MUST use SSL to protect confidentiality or there is no sensitive data enver passing through it, and no possibility that your site will ever be used for a lauinchboard for sslstripping (there's a very good reason why Google serve up search results over HTTPS).
If you are not encrypting traffic between browser and your site then why are you trying to encrypt them between your load balancer and your webserver? If you do happen to have a SSL termination outside the load balancer (a very silly approach) then using HTTPS between the load balancer and the webserver is far from efficient. The question also implies lots of other security problems like session fixation/sniffing and SSLStripping vulnerabilities.

How to append cookie value to end of response Location header with Apache?

I have a page that issues an HTTP redirect. I need to append the current session id (jsessionid) to the end of the HTTP redirect to pass this id as a GET parameter in the redirect.
Can mod_header's Header append directive pick up a cookie value via SetEnvIf?
Should a rewrite rather be involved? But mod_rewrite just rewrites the request not the response, yes?
How would you solve this from an Apache perspective without touching back-end code?
Update: the Apache-JVM is handled by either mod_jk OR via IBM HTTP Server connection to WebSphere.
As to my knowledge, with Apache HTTPd you do it like this:
SetEnvIf Cookie "mycookie=([^;]+)" MYCOOKIE=$1
SetEnvIf Cookie "mycookie=([^;]+)" HAVE_MYCOOKIE=1
Header add Set-Cookie "mycookie=%{MYCOOKIE}e; expires=0" env=HAVE_MYCOOKIE
You can also add additional cookie attributes like path and domain if you want.

mod_rewrite for trailing slash problem

I'm pulling my hair out on what should be an insanely simple problem. We are running WebSphere IHS (Apache) through an F5 BigIP. BigIP is doing the https translation for us. Our url (changed for web, not valid) is https://superniftyserver.com/lawson/portal.
When someone types in just that without the slash after portal, Apache assumes "portal" to be a file and not a directory. When Apache finds out what it is, it sends the 301 Permanent Redirect. But since Apache knows only http, it sends the URL as http://superniftyserver.com/lawson/portal/ which then creates problems.
So I tried a server level httpd.conf change for mod_rewrite, this is one of the dozens of combinations I've tried.
RewriteEngine on
RewriteRule ^/lawson/portal(.*) /lawson/portal/$1
I also tried
RewriteRule ^/lawson/portal$ /lawson/portal/
Among many other things... What am I missing?
If you can't get an answer on the RewriteRule syntax, here are two other options for you: Write an custom iRule on BigIp (see F5 DevCentral) that looks for 301 responses and convert them to SSL; let the URL pass into your WebSphere server and do a programmatic redirect that sends out HTTPS. However, because F5 terminates the SSL connection, you have to set a custom header that you configure (see PQ86347) so the Java request.getScheme() works as you would expect.
Fixed!
SOL6912: Configuring an HTTP profile to rewrite URLs so that redirects from an HTTP server specify the HTTPS protocol
Updated: 8/7/07 12:00 AM
A ClientSSL virtual server is typically configured to accept HTTPS connections from a client, decrypt the SSL session, and send the unencrypted HTTP request to the web server.
When a requested URI does not include a trailing slash (a forward slash, such as /, at the end of the URI), some web servers generate a courtesy redirect. Without a trailing slash, the web server will first treat the resource specified in the URI as a file. If the file cannot be found, the web server may search for a directory with the same name and if found, send an HTTP 302 redirect response back to the client with a trailing slash. The redirect will be returned to the client in HTTP mode rather than HTTPS, causing the SSL session to fail.
Following is an example of how an HTTP 302 redirect response causes the SSL session to fail:
· To request an SSL session, a user types https://www.f5.com/stuff without a trailing slash.
· The client browser sends an SSL request to the ClientSSL virtual server, which resides on the BIG-IP LTM system.
· The BIG-IP LTM system then decrypts the request and sends a GET /stuff command to the web server.
· Since the /stuff file does not exist on the web server, but a /stuff/ virtual directory exists, the web server sends an HTTP 302 redirect response for the directory, but appends a trailing slash to the resource. When the web server sends the HTTP 302 redirect response, it specifies HTTP (not HTTPS).
· When the client receives the HTTP 302 redirect response, it sends a new request to the BIG-IP LTM virtual server that specifies HTTP (not HTTPS). As a result, the SSL connection fails.
Configuring an HTTP profile to rewrite URLs
In BIG-IP LTM version 9.x you can configure an HTTP profile to rewrite URLs so that redirects from an HTTP server specify the HTTPS protocol. To do so, perform the following procedure:
Log in to the Configuration utility.
Click Local Traffic.
Click Profiles.
Click the Create button.
Type a name for the profile.
Choose http from the Parent Profile drop-down menu.
Under Settings, set Redirect Rewrite to All, Matching, or Nodes, depending upon your configuration
For example:
o Choose All to rewrite any HTTP 301, 302, 303, 305, or 307 redirects to HTTPS
o Choose Matching to rewrite redirects when the path and query URI components of the request and the redirect are identical (except for the trailing slash)
o Choose Node to rewrite redirects when the redirect URI contains a node IP address instead of a host name, and you want the system to change it to the virtual server address
Click Finished.
You must now associate the new HTTP profile with the ClientSSL virtual server.
Try this:
# Trailing slash problem
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ https://<t:sitename/>$1/ [redirect,last]
LoadModule rewrite_module modules/mod_rewrite.so
make sure that line is somewhere in you httpd.conf file
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/lawson/portal$ RewriteRule ^(.*)$ https://superniftyserver.com/lawson/portal/ [R=301,L]