Nexus sonatype apache 2.4 proxy does not allow admin login - apache

I have just setup nexus 2.8.1 and a reverse proxy via the following directives in an Apache 2.4 configuration.
<Location /nexus>
RequestHeader unset Authorization
ProxyPreserveHost On
ProxyPass http://nexushost.server:8082/nexus
ProxyPassReverse http://nexushost.server:8082/nexus
RequestHeader set X-Forwarded-Proto "https"
</Location>
However, whenever I try to login it always fails with a invalid username/password or access to ui not enabled.
If I try the same access by going directly to the http://nexushost.server:8080/nexus page then I don't have any issues logging in with the same credentials.
Has anyone else experienced a similar issue.

You have to map cookies to be passed through as well as a few other things. Check out the documentation in the Nexus book.
http://books.sonatype.com/nexus-book/reference/install-sect-proxy.html
Specifically the cookies are required for the UI to work in a browser.

I believe your problem comes from this directive:
RequestHeader unset Authorization
I guess you're doing that because you're using Basic auth in your Apache and you don't want the Authorization header to drift unto Nexus. Unfortunately Nexus uses the same header to perform authentication (you can verify this by opening the network analyzer of your browser).
I came up with the following strategies:
You perform basic auth in Apache and disable auth in Nexus, by giving anonymous all the rights for example. For obvious security reasons, you must make sure that Nexus is bound to 127.0.0.1 and not 0.0.0.0.
You disable basic auth in Apache (plus of course removing the above directive) and let Nexus perform the authentication.
You map your Apache user/passwords to those of Nexus. You'll need to remove the above directive to let the Authorization header propagate to Nexus. This gives you the advantage of not showing Nexus at all for unauthenticated users, while retaining the right management of Nexus. The only drawback is that you need to manage passwords in 2 places.
Same as 3 but to workaround the password management overhead, you set in nexus the same password for all your users (e.g 'nexus_password') then you make Apache rewrite the authorization header with this password. Here is an example of Apache configuration that does it:
RewriteEngine On
RewriteMap base64map prg:/usr/bin/b64
<Location />
RewriteCond %{REMOTE_USER} (.*)
RewriteRule .* - [E=R_U:${base64map:%1:nexus_password}]
RequestHeader set Authorization "Basic %{R_U}e"
</Location>
With /usr/bin/b64 wrapping around base64:
#!/bin/bash
# MANAGED BY PUPPET
# This is an apache RewriteMap interface for base64 : apache runs this program only once at startup
# See http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html#rewritemap
while read line; do
echo -n $line | /usr/bin/base64
done;
Same as 1, make sure Nexus is bound to localhost.

Related

How to pass user's claim to upstream layer using mod_auth_openidc?

I've successfully provisioned apache web server using mod_auth_openidc to protect our internal dashboards, using Auth0 and Google App Oauth, described in this documentation:
- https://github.com/zmartzone/mod_auth_openidc#openid-connect-sso-with-google-sign-in
- https://auth0.com/docs/quickstart/webapp/apache/01-login (without using auth0 rule pipeline)
My question is how to pass the user's claim to the upstream layer (our internal tools/dashboards) as http header? Is it possible?
Regards,
Agung
UPDATED
I've tried with the suggestion here,
here's the snippet of my /etc/apache2/sites-available/000-default.conf
<VirtualHost *:443>
ServerName my-host-name
UseCanonicalName on
ProxyPreserveHost on
DocumentRoot /var/www/html
# Pass the user's claim as http headers
OIDCPassClaimsAs "headers"
OIDCPassUserInfoAs "claims"
OIDCPassRefreshToken "On"
<Location />
AuthType openid-connect
<RequireAll>
Require claim email~^(.*)#domain.com$
Require claim email_verified:true
</RequireAll>
ProxyPass http://echo-server.default.svc.cluster.local:8080/
ProxyPassReverse http://echo-server.default.svc.cluster.local:8080/
LogLevel debug
</Location>
</VirtualHost>
I am using echoserver (gcr.io/google_containers/echoserver:1.0) as the backend of http://echo-server.default.svc.cluster.local:8080, and it doesn't print any user's claim as http headers. Is there any misconfiguration on my part? How to debug this problem?
I'm using docker image httpd:2.4-buster, installing libapache2-mod-auth-openidc at version 2.3.10 from the Debian package repo, and proxying requests for a sub-location (not /). I turned on debug by adding LogLevel auth_openidc:debug to httpd.conf and then I saw traces of the set-header and set-env calls for claims. But using the setup above, I could not observe any OIDC-set headers arriving at the proxied Python Flask WSGI app.
My workaround was converting environment variables into headers. I added the following config lines inside the <Location> block for the REST API path, that's within a <VirtualHost> block of Apache HTTPD config:
# module sets REMOTE_USER as env var
RequestHeader set X-Forwarded-User-Email %{REMOTE_USER}s
# module sets OIDC_CLAIM_sub as env var
PassEnv OIDC_CLAIM_sub
RequestHeader set X-Forwarded-User %{OIDC_CLAIM_sub}e
Then the app gets both the user name and fully qualified user#host.domain as request headers.
Update: Got further help from #hans-z via a discussion # https://github.com/zmartzone/mod_auth_openidc/discussions/705
That discussion taught me that the WSGI http server silently drops all headers that contain an underscore in the name! An alternate solution (instead of converting environment variables to headers) is to change the mod-auth-openidc prefix string like this in a httpd.conf file:
OIDCClaimPrefix Oidc-Claim-
Then all the headers set by mod-auth-openidc survive the trip into the proxed Flask + WSGI app.
That's what the module does by default: it will pass the user's claims in both environment variables and headers, which can be configured with OIDCPassClaimsAs as documented in:
https://github.com/zmartzone/mod_auth_openidc/blob/v2.3.8/auth_openidc.conf#L668
# Define the way in which the claims and tokens are passed to the application environment:
# "none": no claims/tokens are passed
# "environment": claims/tokens are passed as environment variables
# "headers": claims/tokens are passed in headers (also useful in reverse proxy scenario's)
# "both": claims/tokens are passed as both headers as well as environment variables (default)
# When not defined the default is "both"
# The access token is passed in OIDC_access_token; the access token expiry is passed in OIDC_access_token_expires.
# The refresh token is only passed in OIDC_refresh_token if enabled for that specific directory/location (see: OIDCPassRefreshToken)
#OIDCPassClaimsAs [none|headers|environment|both]
Note that those headers are added to the backend HTTP request that is propagated to the application so you won't see them in a browser.

Reverse proxy with request dispatch (to Rstudio server)

I have a multi-tier application of three layers lets say public, business and workspace (all running apache).
Client requests hits the public servers, requests are processed and dispatched on to business servers that does 'things' and response is returned back to public server which then processes the response and pass it on to the client.
I have a scenario wherein I want a request say /rstudio coming to the public server dispatched onto the business which intern reverse proxy to workspace server. There are two catch here:
the workspace server varies per request
application running on workspace server (Rstudio) uses GWT and references resources (static resources js, css etc and RPC coms) on the root url. All the in-application redirection also happens on the domain.
From the business server, I have setup reverse proxy to Rstudio server from my application server.
<Proxy *>
Allow from localhost
</Proxy>
ProxyPass /rstudio/ http://business_server/
ProxyPassReverse /rstudio/ http://business_server/
RedirectMatch permanent ^/rstudio$ /rstudio/
and this work fine (ref. https://support.rstudio.com/hc/en-us/articles/200552326-Running-with-a-Proxy). To handle dynamic workspace server, I could the following but ProxyPassReverse does not support expression in value and this no joy with this approach.
ProxyPassMatch ^/rstudio/(.*)$ http://$1
ProxyPassReverse ^/rstudio/(.*)$ http://$1
RedirectMatch permanent ^/rstudio$ /rstudio/
I have tried the same with mod_rewrite rule (following) but without ProxyPassReverse and due to domain redirection on the GWT Rstudio, this does not work. Adding ProxyPassReverse would fix the problem but I am caught up with no expression on value part to deal with dynamic workspace server issue.
RewriteRule "^/rstudio/(.*)" "http://$1" [P]
Following is the third approach to solve this problem using LocationMatch and mod_headers:
<LocationMatch ^/rstudio/(.+)>
ProxyPassMatch http://$1
Header edit Location ^http:// "http://%{SERVER_NAME}e/rstudio/"
</LocationMatch>
But this is no joy too because value on header directive is not evaluated against environment variable (and only back-references work here). Althought I can get the reverse proxy thing working if I had code the business_server, which is :
<LocationMatch ^/rstudio/(.+)>
ProxyPassMatch http://$1
Header edit Location ^http:// "http://private_server/rstudio/"
</LocationMatch>
Question 1: I was wondering if there are any better way to solve this problem without hardcoding the server DNS in apache conf?
Question 2: With the hard coded server DNS the reverse proxy works for me (patchy but works) but I am hit with GWT issue of resource references on root and the request dispatch is not fully working. I get to the signin page but resources are not found.
I was wondering if there is any better way to handle that?
Following is the example log from browser:
Navigated to https://public_server/rstudio
rworkspaces:43 GET https://public_server/rstudio.css
rworkspaces:108 GET https://public_server/js/encrypt.min.js
rworkspaces:167 GET https://public_server/images/rstudio.png 404 (Not Found)
rworkspaces:218 GET https://public_server/images/buttonLeft.png 404 (Not Found)
rworkspaces:218 GET https://public_server/images/buttonTile.png 404 (Not Found)
rworkspaces:218 GET https://public_server/images/buttonRight.png 404 (Not Found)

reverse proxy with SSL and url encoding, path change

environment http://etrafficcontrol.com/misc/proxy.png
I have two applications. One is an e-commerce site (Drupal 7 running on LAMP) hosted on AWS, and the other is the checkout system which is ASP on IIS-6, is located inside our company, and requires SSL.
Currently we put up with the situation where our customers get forwarded to another domain for checkout -- kind of like what happens with ebay and PayPal. But this leads to difficulty with site tracking code, and kind of feels wrong for the shopper to get forwarded off of the e-commerce site for checkout.
The main concern is that we use Google campaigns, so we want to track conversions from advertising to, and rich content on, domain-1, but the actual sale happens at the time of checkout on domain-2.
Rather than send visitors from www.domain1.com/cart to domain2.com/miscX, I've tried to setup ProxyPass and ProxyPassReverse so I can send them to www.domain1.com/shop/miscX.
App1 (drupal) is in domain1.com/*, and the .htaccess stuff bypasses Drupal's design to intercept everything. The "misc" paths come from the fact that I'm redirecting into a subdirectory, and then proxying from there. When the proxied pages render, they have some hard-coded paths to /miscX, and without making special provisions for those during the rediects, I wind up with /miscX/ (instead of /shop/miscX/ which will follow the proxy) and that causes missing css, js, etc.
Note: Our business customers can login directly to domain2.com, so I'd like to keep that portal unchanged.
Below, local-d7 is a local test instance of the domain1 server. A test of the proxy shows that this concept works, with SSL.
I have this almost working, but it seems like URL-encoded parameters are being lost (even though query strings are ok). When I introduce the proxy, server2 doesn't appear see encoded params (it's a specialized app and I don't know how to view what IIS is receiving). When I route the domain2 test portal login thru apache on server-1 in such a way that doesn't have encoded params, the login works.
In effect I'm trying to
reverse proxy
change path (put an app running in / on domain-2 and expose into a subdir "/shop" on Domain-1
support SSL
proxy an IIS server behind Apache
try to not modify the IIS server so that it can continue to be used by it's original domain-2.com URL, and
do this on a hosted server where I [may] have limited configuration control of Apache. (currently testing on XAMPP).
I've tried all sorts of things in addition to what's shown here, including rewriterules, redirects, etc. I'm just not experienced at all at mod_proxy or mod_rewrite, etc. But it seems to me that this arrangement of a proxy should be doable with some amount of work and possibly fixing server SSL certificates.
Advice? --Thanks
vhosts.conf
## Redirect /misc1/ https://local-d7/shop/misc1/
## Redirect /misc2/ https://local-d7/shop/misc2/
## Redirect /misc3/ https://local-d7/shop/misc3/
## ProxyRequests Off
## ProxyPreserveHost On
## RequestHeader set Proxy-SSL true
## ProxyPass /shop/ https://www.shop.com/
## ProxyPassReverse /shop/ https://www.shop.com/
ProxyPass /shop/ https://www.domain2.com/
ProxyPassReverse /shop/ https://www.domain2.com/
ProxyPass /misc1/ https://www.domain2.com/misc1/
ProxyPassReverse /misc1/ https://www.domain2.com/misc1/
ProxyPass /misc2/ https://www.domain2.com/misc2/
ProxyPassReverse /misc2/ https://www.domain2.com/misc2/
ProxyPass /misc3/ https://www.domain2.com/misc3/
ProxyPassReverse /misc3/ https://www.domain2.com/misc3/
.htaccess
RewriteCond %{REQUEST_URI} ^/misc1/
RewriteCond %{REQUEST_URI} ^/misc2/
RewriteCond %{REQUEST_URI} ^/misc3/
RewriteRule (.*) /shop/$1

Sonatype Nexus: Proxy from SSL using Apache

We're running Sonatype's Nexus to store all of our builds, cache our dependencies, etc. etc. However, I'd like to move away from the default install's port 8081 URL and instead host it over SSL via an Apache proxy. I've setup Apache's mod_proxy to proxy to it such that https://myserver.com/nexus brings up Nexus. I used the following configuration directives inside of my virtual host config:
# Configure mod_proxy to be used for proxying URLs on this site to other URLs/ports on this server.
ProxyRequests Off
ProxyVia Off
ProxyPreserveHost On
<Proxy *>
AddDefaultCharset off
Order deny,allow
Allow from all
</Proxy>
# Proxy the Sonatype Nexus OSS web application running at http://localhost:8081/nexus
<Location /nexus>
ProxyPass http://localhost:8081/nexus
ProxyPassReverse http://localhost:8081/nexus
</Location>
This seems to match the instructions at Running Nexus Behind a Proxy. However, I was unable to clear the "Base URL" setting in Nexus: it wouldn't let me leave it blank.
And everything mostly works: I can access Nexus at the HTTPS URL, log in, and perform most GUI functions.
However, when logging in I get the following warning message:
WARNING: Base URL setting of http://myserver.com/nexus does not match your actual URL! If you're running Apache mod_proxy, here's more information on configuring Nexus with it.
And not everything in the GUI actually works. So far I've noticed the following:
System Feeds: Gives the following error:
Problem accessing /nexus/service/local/feeds. Reason:
The resource identified by the request is only capable of generating response entities which have content characteristics not acceptable according to the accept headers sent in the request
Nexus returned an error: ERROR 406: The resource identified by the request is only capable of generating response entities which have content characteristics not acceptable according to the accept headers sent in the request
Deleting Hosted Repositories: I went through and deleted several empty & unneeded repositories. However, after confirming the deletions, only the first was removed. I had to login to the 8081 site to delete any of the others.
Per the documentation, it looks like a better solution may be to add a RequestHeader to the Apache configuration:
RequestHeader set X-Forwarded-Proto "https"
I tried the accepted answer, which appears to work, but once I added the RequestHeader, I was able to uncheck Force URL and the warning was cleared. I have not tested the other behavior the OP is describing, though.
You just need to adjust the baseUrl setting in the Administration->Server configuration screen. Set the url you are using and click the Force Base Url option.

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).