Apache - Convert underscores to dashes in headers - apache2.4

In a project a had to run CA Webagent Siteminder which sends me legacy headers with underscores. Since Apache 2.4 underscores are deprecated and dropped silently.
I need a workaround via mod_headers which converts all underscores _ to dashes - in the request-header.
Before
legacy_header_one
legacy_header_two
legacy_header_three
After
legacy-header-one
legacy-header-two
legacy-header-three

You have two options here:
Apache Bypass
#
# The following works around a client sending a broken Accept_Encoding
# header.
#
SetEnvIfNoCase ^Accept.Encoding$ ^(.*)$ fix_accept_encoding=$1
RequestHeader set Accept-Encoding %{fix_accept_encoding}e env=fix_accept_encoding
Siteminder Bypass
#its not explicitly stated but im assuming this should be in your WebAgent.conf file
LegacyVariables="NO"
EDIT:
I know this doesn't directly answer your question of converting from _ to - but it is an answer to help mitigate the Apache 2.4 vs. CA Siteminder header issue.

In your virtualhost config:
SetEnvIfNoCase ^OAM.REMOTE.USER$ ^(.*)$ fix_accept_encoding=$1
RequestHeader set OAM-REMOTE-USER %{fix_accept_encoding}e env=fix_accept_encoding
If you are using mod_wsgi for Django or Flask, you will need to add:
WSGIPassAuthorization On

Related

Apache 2.4 all caps headers with underscores workaround not working laravel 8

I am using a service that sends headers in All Caps and with underscores. Following the answers in this question I have added the following lines of code to my .htacces file.
SetEnvIfNoCase ^HTTP.X.KOPOKOPO.SIGNATURE$ ^(.*)$ fix_http_x_kopokopo_signature=$1
RequestHeader set HTTP-X-KOPOKOPO-SIGNATURE %{fix_http_x_kopokopo_signature}e env=fix_http_x_kopokopo_signature
Here is the problem, when I check my $_SERVER superglobal variable for the header HTTP_X_KOPOKOPO_SIGNATURE it is not present and instead I find fix_http_x_kopokopo_signature without any value.
I am on apache 2.4.51 and laravel 8.

How can i add current URL to .htaccess CSP header dynamically?

I'm currently working on Shopify app, one of their main requirement is to add an iframe-protection. here is more info
Currently, to resolve this I need the CSP to set should be in this format :
Content-Security-Policy: frame-ancestors https://shopify-dev.myshopify.com https://admin.shopify.com;
The https://shopify-dev.myshopify.com in above code should be the merchant/ requester domain.
What I tried?
I created .htaccess file with following, it's not adding the dynamic url.
<IfModule mod_rewrite.c>
RewriteEngine On
Header set Content-Security-Policy "frame-ancestors '%{HTTP_HOST}' 'https://admin.shopify.com';"
</IfModule>
This is what I'm getting in console:
Apache
On Apache, you would need to do it like this instead:
### Apache ###
Header set Content-Security-Policy "frame-ancestors https://%{HTTP_HOST}e https://admin.shopify.com;"
Note the e after %{HTTP_HOST}e (specific syntax for mod_headers). I've also removed the single quotes (not present in the Spotify example) and included the https:// protocol.
The <IfModule> and RewriteEngine On directives are irrelevant here.
Reference:
https://httpd.apache.org/docs/current/mod/mod_headers.html#header
UPDATE:
LiteSpeed
However, if you are using LiteSpeed (as opposed to Apache) you will instead need to first explicitly assign the Host header to an environment variable and use this in the Header directive instead. (Apache is able to access server variables directly using this syntax, but not LiteSpeed.)
For example:
### LiteSpeed ###
# Assign the "Host" header to an env var "HOSTNAME"
SetEnvIf Host "(.*)" HOSTNAME=$1
# Use "HOSTNAME" (env var) instead in the Header directive
Header set X-Content-Security-Policy "frame-ancestors https://%{HOSTNAME}e https://admin.shopify.com;"
Attempting to use the syntax %{HTTP_HOST} (as you originally had) on Apache would have resulted in a 500 Internal Server Error (with the error "Unrecognized header format %" being reported in the error logs). However, on LiteSpeed this just outputs the literal string {HTTP_HOST} and no error.

Why nginx does not forward Vary header sent by Apache in proxy mode?

I'm using Plesk (seems to be 17.8.11 provided by OVH) and nginx is configured as proxy. My PHP script returns images into WEBP format when the browser accept it, otherwise it returns orignal format (JPG or PNG).
In .htaccess I return header Vary: Accept so proxies know that the content depends on the Accept header.
In nginx settings of Plesk I only checked the 'Proxy mode' option, other checkboxes are cleared.
When I fetch the image the Vary: Accept is not present, I cannot imagine that nginx does not handle this header, please help me to figure this out.
For the Vary: header to be allowed and understood by nginx, you need the gzip on and gzip_vary on settings in your /etc/nginx/nginx.conf.
Plesk actually have a documentation about it, did you check the Plesk Support website ?
https://support.plesk.com/hc/en-us/articles/213380049-How-to-enable-disable-gzip-compression-in-nginx-on-a-Plesk-server
By the way, your Plesk version is quite old, I would recommend you update it.
I finally found the reason: I was not sending "Vary: Accept" header for ".webp" extension, only for ".jpg" and ".png". My URLs ends with .jpg or .png, never .webp and this is working good with Apache. Here was my htaccess directives:
<IfModule mod_setenvif.c>
SetEnvIf Request_URI "\.(jpe?g|png)$" REQUEST_image
</IfModule>
<IfModule mod_headers.c>
Header append Vary Accept env=REQUEST_image
</IfModule>
To fix it I added .webp in URLs filter:
<IfModule mod_setenvif.c>
SetEnvIf Request_URI "\.(jpe?g|png|webp)$" REQUEST_image
</IfModule>
<IfModule mod_headers.c>
Header append Vary Accept env=REQUEST_image
</IfModule>
Now it's all good.

Apache 2.4 + PHP-FPM and Authorization headers

Summary:
Apache 2.4's mod_proxy does not seem to be passing the Authorization headers to PHP-FPM. Is there any way to fix this?
Long version:
I am running a server with Apache 2.4 and PHP-FPM. I am using APC for both opcode caching and user caching. As recommended by the Internet, I am using Apache 2.4's mod_proxy_fcgi to proxy the requests to FPM, like this:
ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/foo/bar/$1
The setup works fine, except one thing: APC's bundled apc.php, used to monitor the status of APC does not allow me to log in (required for looking at user cache entries). When I click "User cache entries" to see the user cache, it asks me to log in, clicking on the login button displays the usual HTTP login form, but entering the correct login and password yields no success. This function is working perfectly when running with mod_php instead of mod_proxy + php-fpm.
After some googling I found that other people had the same issue and figured out that it was because Apache was not passing the Authorization HTTP headers to the external FastCgi process. Unfortunately I only found a fix for mod_fastcgi, which looked like this:
FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -host 127.0.0.1:9000 -pass-header Authorization
Is there an equivalent setting or some workaround which would also work with mod_proxy_fcgi?
Various Apache modules will strip the Authorization header, usually for "security reasons". They all have different obscure settings you can tweak to overrule this behaviour, but you'll need to determine exactly which module is to blame.
You can work around this issue by passing the header directly to PHP via the env:
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
See also Zend Server Windows - Authorization header is not passed to PHP script
In some scenarios, even this won't work directly and you must also change your PHP code to access $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] rather than $_SERVER['HTTP_AUTHORIZATION']. See When setting environment variables in Apache RewriteRule directives, what causes the variable name to be prefixed with "REDIRECT_"?
This took me a long time to crack, since it's not documented under mod_proxy or mod_proxy_fcgi.
Add the following directive to your apache conf or .htaccess:
CGIPassAuth on
See here for details.
Recently I haven'd problem with this arch.
In my environement, the proxy to php-fpm was configured as follow:
<IfModule proxy_module>
ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/usr/local/apache2/htdocs/$1
ProxyTimeout 1800
</IfModule>
I fixed the issue set up the SetEnvIf directive as follow:
<IfModule proxy_module>
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/usr/local/apache2/htdocs/$1
ProxyTimeout 1800
</IfModule>
I didn't find any similar settings with mod_proxy_fcgi BUT it just works for me by default. It asks for user authorization (.htaccess as usual) and the php gets it, and works like with mod_php or fastcgi and pass-header. I don't know if I was helpful...
EDIT:
it only works on teszt.com/ when using the DirectoryIndex... If i pass the php file name (even if the index.php!) it just doesn't work, don't pass the auth to the php. This is a blocker for me, but I don't want to downgrade to apache 2.2 (and mod_fastgi) so I migrate to nginx (on this machine too).

Rewrite authenticated Apache2.2 user for mod_proxy_ajp

I have a Tomcat connected via mod_proxy_ajp to an Apache2.2 instance. Apache does the authentication via mod_auth_kerb, and Tomcat uses request.getRemoteUser() to get the authenticated user.
This basically works, but I want to rewrite the user. However, none of the headers I set affect what is returned by request.getRemoteUser(), I only see them as additional headers, what do I have to do?
# Rewrite Magic: change REMOTE_USER to something Alfresco expects
RewriteEngine On
RewriteMap domain_map txt:/etc/apache2/rewrite-map.txt
# Grab the REMOTE_USER apache environment variable for HTTP forwarding (requires sub-request!)
RewriteCond %{LA-U:REMOTE_USER} (.*)#(.*)
# change the format and replace the domain, e.g.:
# user#some.domain ==> other.domain_user
RewriteRule . - [E=RU:${domain_map:%2|%2}_%1]
# copy processed user to HTTP headers
RequestHeader set REMOTE_USER %{RU}e
RequestHeader set HTTP_REMOTE_USER %{RU}e
RequestHeader set AJP_REMOTE_USER %{RU}e
RequestHeader set AJP_HTTP_REMOTE_USER %{RU}e
Thanks!
I suspect that the headers are not being set as you expect them to be set, and they are getting to Tomcat empty.
I have experienced some puzzling processing order issues that caused RequestHeader to ignore the environment variables set by a RewriteRule. Take a look at https://stackoverflow.com/a/9303018/239408 in case it helps
It seems the getRemoteUser() value can not be overwritten by Apache header directives, as the AJP protocol handler gets the username from some internal Apache structure. I worked around this by sending the username via http header and modifying the Java code to use that instead of using getRemoteUser().