Apache Rewritemap not being read? - regex

I have a simple key value map file which converts olduserid's to new userid's
The objective is to pullup a member profile page from the old site and redirect to tyhe newsite where the member has a new userid.
My virtualhost config file is like this
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
ServerAlias *.example.com
DocumentRoot /home/example/www
AllowEncodedSlashes NoDecode
<Directory /home/example/www>
Options Indexes FollowSymLinks MultiViews
Require all granted
AllowOverride All
</Directory>
CustomLog /var/log/httpd/example.com-access.log combined
ErrorLog /var/log/httpd/example.com-error.log
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel error
RewriteEngine on
RewriteMap profiles "txt:/home/example/www/userMap.txt"
RewriteCond %{SERVER_NAME} =*.example.com [OR]
RewriteCond %{SERVER_NAME} =example.com [OR]
RewriteCond %{SERVER_NAME} =www.example.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]`
The in root directory my .htaccess looks like this
RewriteEngine on
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{QUERY_STRING} ^$ RewriteRule ^member/([0-9])+$ https://www.newxample.com/member/$%7Bprofiles:$1%7D" [NC,L]
The mapfile looks like this but larger
5 1
3583 7657
3584 7658
3585 703
The permissions for the map file and it's location are 777
I have tried so many ways to write the rules and condition but am getting nowhere.
The redirect works but it does not include the values of the newuseris. It's simply null empty nada!
Any help would be greatly appreciated.

tl;dr I'm guessing you haven't defined the rewrite map (and possibly other config) in the <VirtualHost *:443> (HTTPS) container AND/OR you are only capturing the first digit of the old user ID.
The virtualhost config you've posted is for port 80 (HTTP) only. Which is redirected to HTTPS (port 443). There's not much point defining the RewriteMap in <VirtualHost *:80>, since you will also need to define it again in <VirtualHost *:443>. The same applies to granting access and allowing .htaccess overrides etc.
Basically, the vHost:80 container really just serves to redirect to HTTPS, then most of the config is defined in vHost:443.
Since you are redirecting to HTTPS directly in the vHost container, the .htaccess file is only going to be processed (if at all) when the request is already over HTTPS.
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{QUERY_STRING} ^$ RewriteRule ^member/([0-9])+$ https://www.newxample.com/member/$%7Bprofiles:$1%7D" [NC,L]
The formatting/encoding of the code dump in your question is messed up (I'm assuming this is just a formatting issue with your question and not in your actual code), however, your regex that is capturing the old user ID is only capturing the first digit, so the lookup will likely fail (or return the wrong result):
^member/([0-9])+$
Should be:
^member/([0-9]+)$
Or, use a shorthand character class, eg. ^member/(\d+)$
Aside:
RewriteCond %{SERVER_NAME} =*.example.com [OR]
RewriteCond %{SERVER_NAME} =example.com [OR]
RewriteCond %{SERVER_NAME} =www.example.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
By default, SERVER_NAME is the same as HTTP_HOST, ie. the value of the Host header used in the request. This is what you would seem to be assuming here, however, it is never equal to *.example.com (which is simply a wildcard alias). There shouldn't be a need to check the requested Host here since for the request to be at this point in the config, it must have already passed the ServerName / ServerAlias check. (This is assuming this is not the "default" vHost.)
The three RewriteCond directives are therefore redundant.

Related

Is Apache RewriteRule interfering with If and Location directives?

I'm using Apache to implement Shibboleth single sign on for a Laravel site. I'd like to bypass one specific subset of URLs from authentication (api/public, for example) so they're publicly accessible. For some reason the public folder's .htaccess file seems to be preventing this from working as expected.
I've tried this a bunch of different ways and all roads have lead to this same issue. Here's what I'm trying currently.
<Directory /var/www/html/mysite/public>
SSLOptions +StdEnvVars
Options Indexes FollowSymLinks MultiViews
AllowOverride All
<If "%{REQUEST_URI} =~ m#api/public#">
Require all granted
</If>
<Else>
AuthType shibboleth
ShibRequestSetting requireSession 1
Require valid-user
</Else>
</Directory>
Here's the .htaccess file that Laravel ships with:
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
Unfortunately with the .htaccess file in place, the Else code is still getting executed and the Shib code runs. But I'm pretty sure the If condition is catching, because if throw in Require all denied as a test then it does forbid as expected.
If I remove the .htaccess however, this works! But it also means that any routing within Laravel is now broken, which I do need for this public-facing URL.
My best guess is that the .htaccess RewriteRule is causing the Else code to still run even after the If statement caught. Any suggestions on a way around this? Running into the same problem using Location directive.
Thanks.
Figured out a solution for this, will share here in case someone else runs into this. The issue was indeed that RewriteRule causes us to run through the whole thing again. The If stopped Shibboleth as expected the first time, but then we'd go through again after Laravel redirects us to index.php and pick it up anyway.
Solved it by changing the Else to an ElseIf where we exclude index.php:
<Directory /var/www/html/mysite/public>
SSLOptions +StdEnvVars
Options Indexes FollowSymLinks MultiViews
AllowOverride All
<If "%{REQUEST_URI} =~ m#api/public#">
Require all granted
</If>
<ElseIf "%{REQUEST_URI} !~ m#index\.php#">
AuthType shibboleth
ShibRequestSetting requireSession 1
Require valid-user
</ElseIf>
</Directory>

Redirect httpd file

I tried editing httpd file using all the solutions i found to redirect a https://pc.web.com/MyWeb/MyWebPortal.portal;jsessionid=jZLxT04pfQ (example website) to http://pc.web.com.
But none of the solutions are working! can anyone could guide me on this?
<VirtualHost *:80>
ServerName pcnow.web.com
DocumentRoot "C:/Program Files (x86)/Apache Software Foundation/Apache2.2/htdocs"
RewriteCond %{pc.web.com} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
even redirect is also not working!!
There are multiple mistakes in your configuration
<VirtualHost *:80>
ServerName pcnow.web.com
DocumentRoot "C:/Program Files (x86)/Apache Software Foundation/Apache2.2/htdocs"
RewriteCond %{pc.web.com} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
...
First, you want to redirect https request to http so your virtual host should probably listen to port 443 and you should set the certificate and the appropriate SSL configurations in it.
Second, you have a typo in the server name ServerName pcnow.web.com should be ServerName pc.web.com.
Third, your RewriteCond is invalid.
The RewriteCond syntax should be in the form of:
RewriteCond TestString CondPattern [flags].
So in your case the TestString will be something like: %{REQUEST_URI}.
And the CondPattern should be a regex matching what all URIs that need to be redirected, for example: ^/MyWeb/MyWebPortal\.portal;jsessionid=.*.
Or all together:
RewriteCond %{REQUEST_URI} ^/MyWeb/MyWebPortal\.portal;jsessionid=.*.
And last, the RewriteRule second parameter contracting an invalid URL to redirect. The reason is it concatenating the value of the RewriteRule expression match with the value of the RewriteCond condition match which was written incorrectly.
The RewriteRule rule should as follow: RewriteRule .* http://pc.web.com [R=301,L].
you can take a look over here for more details: http://httpd.apache.org/docs/current/mod/mod_rewrite.html

Apache redirect based on host and uri

I have a fairly simple redirect rule setup in my Apache vhost.
<VirtualHost *:80>
ServerName mobile.foo.com
ServerAlias *.foo.com
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(.*)\.foo\.com$
RewriteRule ^(.*)$ http://mobile.bar.com/foo [R=301,L]
</VirtualHost>
I want to add another condition based on the request uri. The redirect above should not be performed if the request uri equals google.html. I guess another rewrite condition is needed based on the request uri variable. Any ideas on how the regex should look like?
Should look like this:
RewriteCond %{REQUEST_URI} !^/google\.html$

Problem with redirecting *.example.com & example.com to www.example.com for HTTPS

We have a site I'll call example.com. Most of the time you see http://www.example.com and sometimes we redirect you to https://www.example.com.
We want to redirect anyone going to http://example.com or http://*.example.com to http://www.example.com, and the same for https. (It's mainly to avoid the alert you get if you go to https://example.com instead of https://www.example.com)
Our vhost file is at the end of the post. It works nicely except for one strange behavior:
http://example.com -> successfully redirects to http://www.example.com
http://www.example.com -> successfully does not redirect
http://foo.example.com -> successfully redirects to http://www.example.com
https://example.com -> successfully redirects to https://www.example.com
https://www.example.com -> successfully does not direct
https://foo.example.com -> ERROR - redirects to http://www.example.com
It's this last result I can't fathom. I've tried a lot of trial and error solutions from Google & Stack Overflow but nothing seems to change it. Even if we swap the order of the configurations (so that 443 is before 80) it still redirects https://foo.example.com to http://www.example.com
We are running Apache/2.2.12 on Ubuntu.
Here's the configuration file:
<VirtualHost *:80>
ServerName www.example.com
ServerAlias example.com *.example.com
ServerSignature On
DocumentRoot /var/www/example.com/public
RailsEnv 'production'
PassengerHighPerformance on
<Directory /var/www/example.com/public>
AllowOverride all
Options -MultiViews
</Directory>
SSLEngine Off
CustomLog /var/log/apache2/example.log combined
ErrorLog /var/log/apache2/example-error.log
# Possible values include: debug, info, notice, warn, error, crit, alert, emerg.
LogLevel warn
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^[^\./]+\.[^\./]+$
RewriteRule ^/(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
</VirtualHost>
<VirtualHost *:443>
ServerName www.example.com
ServerAlias example.com *.acome.com
DocumentRoot /var/www/example.com/public
RailsEnv 'production'
PassengerHighPerformance on
<Directory /var/www/example.com/public>
AllowOverride all
Options -MultiViews
</Directory>
SSLCertificateFile /etc/ssl/certs/www.example.com.crt
SSLCertificateKeyFile /etc/ssl/private/example.com.private.key
SSLCACertificateFile /etc/ssl/certs/EV_intermediate.crt
SSLEngine On
CustomLog /var/log/apache2/ssl-example.log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
ErrorLog /var/log/apache2/ssl-example-error.log
# Possible values include: debug, info, notice, warn, error, crit, alert, emerg.
LogLevel warn
RewriteEngine On
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} ^[^\./]+\.[^\./]+$
RewriteRule ^/(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
</VirtualHost>
ServerAlias acme.com *.acome.com
Is that the problem right there? You have misspelled your domain name.
Thanks to everyone who took the time to read the question, or (even better) to try and help. It's what makes Stack Overflow such a useful resource.
We re-read TFM, learnt a bit more about Apache rewrite and here's the answer.
Problem #1: The rewrite rules (taken from Google) were designed to only redirect acme.com to www.acme.com, not any other sub-domain.
Problem #2: For some reason, Chrome was redirecting to http://www.acme.com by itself. When we removed the rewrite rules completely, the described behavior still happened.
Solution: Change the rewrite rules to actually catch any sub-domain other than www.
See below for a working solution.
There remains one issue. if you go to https://acme.com (or any sub-domain), some browsers will throw a warning saying the SSL certification does not match before redirecting you. The only way to fix this is to get a wildcard cert. As we're using an Extended Validation cert that was already very expensive we're just going to have to live with that warning for now. Would love to hear about any workarounds that would avoid showing an invalid cert warning before redirection.
<VirtualHost *:80>
ServerName www.acme.com
ServerAlias acme.com *.acme.com
ServerSignature On
DocumentRoot /var/www/acme.com/public
RailsEnv 'production'
PassengerHighPerformance on
<Directory /var/www/acme.com/public>
AllowOverride all
Options -MultiViews
</Directory>
SSLEngine Off
CustomLog /var/log/apache2/acme.log combined
ErrorLog /var/log/apache2/acme-error.log
# Possible values include: debug, info, notice, warn, error, crit, alert, emerg.
LogLevel warn
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} ^/(stats/|missing\.html|failed_auth\.html|error/).* [NC]
RewriteRule .* - [L]
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule .* - [L]
RewriteCond %{HTTP_HOST} !^www\.[a-z-]+\.[a-z]{2,6} [NC]
RewriteCond %{HTTP_HOST} ([a-z-]+\.[a-z]{2,6})$ [NC]
RewriteRule ^/(.*)$ http://www.%1/$1 [R=301,L]
</VirtualHost>
<VirtualHost *:443>
ServerName www.acme.com
ServerAlias acme.com *.acme.com
DocumentRoot /var/www/acme.com/public
RailsEnv 'production'
PassengerHighPerformance on
<Directory /var/www/acme.com/public>
AllowOverride all
Options -MultiViews
</Directory>
SSLCertificateFile /etc/ssl/certs/www.acme.com.crt
SSLCertificateKeyFile /etc/ssl/private/acme.com.private.key
SSLCACertificateFile /etc/ssl/certs/EV_intermediate.crt
SSLEngine On
CustomLog /var/log/apache2/ssl-acme.log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
ErrorLog /var/log/apache2/ssl-acme-error.log
# Possible values include: debug, info, notice, warn, error, crit, alert, emerg.
LogLevel warn
RewriteEngine On
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} ^/(stats/|missing\.html|failed_auth\.html|error/).* [NC]
RewriteRule .* - [L]
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule .* - [L]
RewriteCond %{HTTP_HOST} !^www\.[a-z-]+\.[a-z]{2,6} [NC]
RewriteCond %{HTTP_HOST} ([a-z-]+\.[a-z]{2,6})$ [NC]
RewriteRule ^/(.*)$ https://www.%1/$1 [R=301,L]
</VirtualHost>

static site apache and dynamic/member site django

I have a site for static content, accessible to all that runs on apache. As an adjunct to that, there is a members site that runs on django. I haven't had any issue 'sharing' my .css and making both sides equivalent in appearance, but what I can't quite seem to grok is getting my django site to be django password protected (with the additional caveat that all member material, from the login forward, goes through 443).
I can serve all the pages, I have tried to use mod_rewrite as follows:
<Directory /Library/Webserver/Documents>
.
.
.
</Directory>
WSGIScriptAlias /members /usr/local/django/mysite/apache/django.wsgi
<Directory /members>
RewriteCond %{HTTPS} off
RewriteRule (.*) https://{HTTP_HOST}%{REQUEST_URI} [L]
.
.
</Directory>
I have tried every one of a thousand different items in the '/members location above, nothing seems to hit (and yes, RewriteEngine On is included - I can watch the debug come out).
Try:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
You should be redirecting back to same host the request was made against, not necessarily the actual web server host.
I also don't believe there is a %{URI} variable in mod_rewrite. Supposed to use %{REQUEST_URI}.
EDIT 1
As per comments, should be:
<Location /members>
RewriteCond %{HTTPS} off
RewriteRule (.*) https://{HTTP_HOST}%{REQUEST_URI} [L]
.
.
</Location>
or:
<Directory /usr/local/django/mysite/apache>
RewriteCond %{HTTPS} off
RewriteRule (.*) https://{HTTP_HOST}%{REQUEST_URI} [L]
.
.
</Directory>
So, Location is for URL and Directory is for file system directory.