Execute RewriteRule proxy redirection directive after all others
I have a backend application behind a reverse proxy protected by an SSO. The SSO exports an HTTP header after successful authentication containing the userid. I need to pass this uid and other data to a program that will sign the all thing.
Here's how it works:
- Define the script with RewriteMap
- Set an environment var with the SSO-exported header value
- Call the script, get the values returned and append them to env var
- Check the env var and create a cookie with those values
Then the last RewriteRule directive will pass the traffic to the backend application, the thing is, as soon as I set the RewriteRule with the P flag, all the above variable affectations no longer work.
Question : How can I manage to execute all my directives and thus the cookie creation before proxying all the traffic so my cookie is available in my backend app ?
RewriteMap cookiemap prg:/dir/cookieSign.py
RewriteRule ^ - [env=LLNGUID:%{HTTP:Test}]
RewriteCond ${cookiemap:%{REMOTE_ADDR}-%{ENV:LLNGUID}} ^(.*)\s(.*)\s(.*)\s([a-z]+)$
RewriteRule ^ - [E=SIGNATURE:%1,E=SETTIME:%2,E=SETIP:%3,E=UIDSCRIPT:%4]
RewriteCond "%{ENV:SIGNATURE}" "!^$"
RewriteCond "%{ENV:SETTIME}" "!^$"
RewriteCond "%{ENV:SETIP}" "!^$"
RewriteCond "%{ENV:UIDSCRIPT}" "!^$"
RewriteRule ^ - [CO=MY_COOKIE:userid=%{ENV:UIDSCRIPT}&sign=%{ENV:SIGNATURE}&time=%{ENV:SETTIME}&ip=%{ENV:SETIP}:.test.ltd:86400:/:true:true]
RewriteRule "^(.*)$" "http://127.0.0.1:8080$1" [P,L]
Thanks :)
The problem is not the order of execution - the directives are being executed in the order shown - but an issue with variable scope and cookie setting.
The environment variables you set here are not going to be available to the target server, since this is a different scope.
The cookie you are "setting" will not be available to your script in the current request. Setting a cookie (eg. with the CO
flag) sets a Set-Cookie
HTTP response header on the HTTP response back to the client/browser. The cookie is only sent back to your server on the next request when the browser (hopefully) sends back a Cookie
HTTP request header.
If you want to send this information to your backend server for the current request then you need to use a different method. Perhaps a query string on the proxied request?
For example:
RewriteMap cookiemap prg:/dir/cookieSign.py
RewriteRule ^ - [env=LLNGUID:%{HTTP:Test}]
RewriteCond ${cookiemap:%{REMOTE_ADDR}-%{ENV:LLNGUID}} ^([^\s]+)\s([^\s]+)\s([^\s]+)\s([a-z]+)$
RewriteRule ^ - [E=SIGNATURE:%1,E=SETTIME:%2,E=SETIP:%3,E=UIDSCRIPT:%4]
RewriteCond %{ENV:SIGNATURE} .
RewriteCond %{ENV:SETTIME} .
RewriteCond %{ENV:SETIP} .
RewriteCond %{ENV:UIDSCRIPT} .
RewriteRule ^ - [ENV=MY_QUERY:userid=%{ENV:UIDSCRIPT}&sign=%{ENV:SIGNATURE}&time=%{ENV:SETTIME}&ip=%{ENV:SETIP}]
RewriteRule (.*) http://127.0.0.1:8080$1?%{ENV:MY_QUERY} [P]
Notes:
- Changed the regex that matches the output of the rewritemap to use
[^\s]+
instead of.*
to avoid unnecessary backtracking. - No need to surround all arguments in quotes unless they contain spaces.
- Instead of checking for not-empty (
"!^$"
), it's arguably simpler to check that it is something, ie.
. - The
L
flag is not required when using theP
flag (it is implied).