GOAL
Typical usage is a web application who normally needs an Apache authentication BUT placed behind a reverse proxy who handles itself authentication/authorization
If you need to define REMOTE_USER system variable on a proxied virtual host (backend) :
1° You need first to define a dedicated header on the front-end virtual host (the one which forwards the requests to the backend).
2° You need then to configure the backend virtual host to transform the dedicated header to the REMOTE_USER system variable.
User –>
Front-End : Forward + add custom header –>
Backend : use custom header to create system variable REMOTE_USER
Note this system variable REMOTE_USER can never be modified. It works in this case because it was not defined before on the backend
FRONT END VIRTUAL HOST
<VirtualHost *:443>
ServerName frontend.onemrva.priv
<Location />
AuthName "Application Access"
AuthType XXXXX (Basic, Digest, Kerberos, ...)
...
Require valid-user
# ------------------------------
# Pass headers to backend
# X-APP-USER = username as you want to be passed to backend (here created from APP_USER variable
# X-REAL-USER = original username as authentified in frontend for audit/log
# ------------------------------
RequestHeader set X-APP-USER "%{APP_USER}e"
RequestHeader set X-REAL-USER "%{REMOTE_USER}s"
</Location>
# --------------------------------
# Reverse Proxy to webapp backend
# --------------------------------
SSLProxyEngine On
SSLProxyVerify none
SSLProxyCheckPeerCN Off
SSLProxyCheckPeerName Off
ProxyPreserveHost On
ProxyPass / https://127.0.0.1:8443/
ProxyPassReverse / https://127.0.0.1:8443/
The key instruction is
RequestHeader set X-APP-USER "%{APP_USER}e"
It defines X-APP-USER (which will become REMOTE_USER on backen) from APP_USER variable.
This APP_USER variable should of course be defined somewhere before in the authentication/authorization phase.
Note in this example, the backend server is defined on https://127.0.0.1:8443/ It’s necessary to make it listen on an alternate TCP port (8443 here) if both backend and frontend runs on the same machine
BACKEND VIRTUAL HOST
#Listen only on localhost to restrict access
Listen 127.0.0.1:8443
<VirtualHost 127.0.0.1:8443>
ServerName webapp.onemrva.priv
# Define custom log format including X-APP-USERS-USER and X-REAL-USER
LogFormat "%h %l %u %t \"%r\" %>s %b X-APP-USER:%{X-APP-USER}i X-REAL-USER:%{X-REAL-USER}i REMOTE_USER:%{REMOTE_USER}e" webapp_custom
# Logs
ErrorLog logs/webapp-8443-error.log
CustomLog logs/webapp-8443-access.log webapp_custom
# Enable SSL
SSLEngine On
SSLCertificateFile /etc/pki/tls/certs/webapp.onemrva.priv.crt
SSLCertificateKeyFile /etc/pki/tls/private/webapp.onemrva.priv.key
# -----------------------------------------------
# Set REMOTE_USER from frontend header X-APP-USER
# -----------------------------------------------
SetEnvIf X-NAGIOS-USER (.+) REMOTE_USER=$1
DocumentRoot "/var/www/html/webapp"
<Directory "/var/www/html/webapp">
Options None
AllowOverride All
Require ip 127.0.0.1
</Directory>
</VirtualHost>
the key instruction is
SetEnvIf X-NAGIOS-USER (.+) REMOTE_USER=$1
Additional info on this config
- Localhost on port 8443 (127.0.0.1:8443) is defined for this Vhost on TCP 8443 : listening on another port is necessary when both frontend and backend runs on the same machine
- LogFormat : Custom log format to displays both “used application username” and “real username as received by the frontend”. In this example it’s called webapp_custom
- This webapp_custom is used while defining log file location
- Require ip 127.0.0.1 in <Directory> definition is a second security to be sure it can only be served through the frontend
