Keep Server Online
If you find the Apache Lounge, the downloads and overall help useful, please express your satisfaction with a donation.
or
A donation makes a contribution towards the costs, the time and effort that's going in this site and building.
Thank You! Steffen
Your donations will help to keep this site alive and well, and continuing building binaries. Apache Lounge is not sponsored.
| |
|
Topic: [solved] mod_auth_mellon - pass the apache env thru HTTP? |
|
Author |
|
cbas
Joined: 12 Jan 2022 Posts: 11 Location: Bloomington, MN
|
Posted: Tue 18 Jan '22 17:59 Post subject: [solved] mod_auth_mellon - pass the apache env thru HTTP? |
|
|
Hello,
We have a requirement to add SAML authentication.
mod_auth_mellon was chosen for a number of reasons.
I can set up a simple website and have a SAML conversation with samltest.id acting as the IDP.
I can then get the MELLON_* variables out of the apache environment in a WebOb WSGI application as is described in chapter 9 of the Mellon User Guide.
What I can't get is the MELLON_* variables from anywhere inside our web application.
Our application runs in a Zope 2 environment. We've verified that the apache environment does not get forwarded through the HTTP request. The raw data coming through the socket does not contain it.
We have also experimented with a Zope 4 (Plone 5.2) environment running the new default WSGI server, Waitress. We have not yet debugged down to the socket level here, but still, the apache environment is not coming through.
Is there a simple configuration I have not seen I can make in the apache configs to put the MELLON_* variables in the HTTP header? I have not seen it, or if I did, it did not click with me.
Aside from the above question, is there any way to get the apache environment to get passed through to another WSGI server? (We would prioritize upgrading to Zope 4 if there is.)
My test server is running Amazon linux, apache version 2.4.48.
We are also in process of updating to Amazon linux 2.
Thanks in advance,
Christopher
Last edited by cbas on Tue 01 Feb '22 17:22; edited 1 time in total |
|
Back to top |
|
James Blond Moderator
Joined: 19 Jan 2006 Posts: 7371 Location: Germany, Next to Hamburg
|
|
Back to top |
|
cbas
Joined: 12 Jan 2022 Posts: 11 Location: Bloomington, MN
|
Posted: Wed 19 Jan '22 18:14 Post subject: |
|
|
Thanks for your reply.
PassEnv certainly looks like the correct kind of config.
I placed the PassEnv/Header Set directives within the Location directive in the Mellon conf file.
I believe I'm starting to understand the directives, here's what I have - trying different things to see what sticks:
Code: | # uid
PassEnv MELLON_urn:oid:0.9.2342.19200300.100.1.1
SetEnv HTTP_SAML_UID %{MELLON_urn:oid:0.9.2342.19200300.100.1.1}e
Header Set HTTP_SAML_UID %{MELLON_urn:oid:0.9.2342.19200300.100.1.1}e
# email
PassEnv MELLON_urn:oid:0.9.2342.19200300.100.1.3
SetEnv HTTP_SAML_EMAIL %{MELLON_urn:oid:0.9.2342.19200300.100.1.3}e
Header Set HTTP_SAML_EMAIL %{MELLON_urn:oid:0.9.2342.19200300.100.1.3}e
|
But, when I restart httpd there are warnings:
Code: | # service httpd restart
Stopping httpd: [ OK ]
Starting httpd: [Wed Jan 19 09:38:49.393631 2022] [env:warn] [pid 30112] AH01506: PassEnv variable MELLON_urn:oid:0.9.2342.19200300.100.1.1 was undefined
[Wed Jan 19 09:38:49.393751 2022] [env:warn] [pid 30112] AH01506: PassEnv variable MELLON_urn:oid:0.9.2342.19200300.100.1.3 was undefined
[ OK ]
|
The issue is the MELLON_* env vars are dynamically created at run time.
Indeed, when I try running my `dump` scripts within our application website, neither the MELLON_* nor HTTP_SAML_* vars are there.
I don't suppose any apache configs are dynamic?
Thanks again. |
|
Back to top |
|
cbas
Joined: 12 Jan 2022 Posts: 11 Location: Bloomington, MN
|
Posted: Wed 19 Jan '22 18:22 Post subject: |
|
|
Quote: | Except in early mode, the Header directives are processed just before the response is sent to the network. This means that it is possible to set and/or override most headers, except for some headers added by the HTTP header filter. Prior to 2.2.12, it was not possible to change the Content-Type header with this directive.
|
That seems to imply apache sets Headers dynamically...
Do I need to use `always` in my directives? |
|
Back to top |
|
tangent Moderator
Joined: 16 Aug 2020 Posts: 348 Location: UK
|
Posted: Sat 22 Jan '22 19:35 Post subject: |
|
|
Re PassEnv, to quote the documentation https://httpd.apache.org/docs/current/mod/mod_env.html#passenv
Specifies one or more native system environment variables to make available as internal environment variables, which are available to Apache HTTP Server modules as well as propagated to CGI scripts and SSI pages. Values come from the native OS environment of the shell which invoked the httpd process. So PassEnv passes OS environment variables present when Apache starts, not ones assigned dynamically within Apache. Your startup error is simply confirming OS variable "MELLON_urn:oid:0.9.2342.19200300.100.1.1" was undefined at startup; you can't set it as an argument to PassEnv.
You say you can get the MELLON_* variables out of the Apache environment, but not inside. Where inside? Are you proxying these requests down the line, in which case do you need to manipulate request rather than response headers?
I'm equally confused why you'd want to assign the MELLON_urn to a header named HTTP_SAML_UID. Surely, what you want to assign is the name of the authenticated user, viz something like:
Code: | Header set HTTP_SAML_UID %{MELLON_NAME_ID}e |
And yes, I'd include the ALWAYS option when settings such response headers. |
|
Back to top |
|
cbas
Joined: 12 Jan 2022 Posts: 11 Location: Bloomington, MN
|
Posted: Fri 28 Jan '22 19:40 Post subject: |
|
|
Thanks for your reply.
Sorry. I missed a sentence in my OP.
Between setting up a simple website where I could run the WSGI app and running our full blown web app I shut down the simple website and started our actual website.
-----
For the simple website I setup a WSGIScriptAlias to a URL and was able to access req.environ from the WSGI application.
Shutting that down and starting our Zope website we were able to debug the ZServer code and dump the raw request coming in from Apache, straight from the socket. All that came through were the standard headers.
The reason I'm interested in the MELLON_urn variables is that's the actual SAML attributes. The MELLON_NAME_ID is the "unique" user id which is a giant random string - it's only useful information to the Identity Provider server to track its session.
-----
Yes, I've thought maybe I need to do something request related.
This project is the first time I've done anything with Apache further than simply watching the default installation "just work".
As such, working directly with the requests/responses is all a learning experience for me.
One thing I've tried is setting up a WSGIScriptAlias at "/" with the hopes that WSGI script could intercept all traffic, create a cookie, then load the intended web page. (This method was described in the WSGI documentation.) It didn't work - possibly due to lack of understanding.
I started using WebOb because that's what the Mellon User Guide used. It's not entirely clear to me how to implement a request within a response. If there's another python module which is easier to use, I'm game.
-----
I have not gotten around to re-debugging the web traffic since adding the PassEnv config. But, it sounds like PassEnv was not the correct solution, so not worth doing.
-----
I was hoping the WSGI server within Zope 4 would behave like the WSGI app in the simple website. From the environment snooping I've done, it is not receiving any more environment than Zope 2 did.
What mod_auth_mellon does by putting info into the Apache environment sounds like standard procedure from what I've read. There must be an EASY way to get that info in a web app if it is SOP...
Is the fact that Zope operates its own server the issue? How can Apache forward its environment to another server?
Zope, even Zope 4, needs Apache or Nginx to handle HTTPS, so there's no way around having Apache stand in front of Zope. There is a (what seems like standard) VirtualHost/RewriteEngine configuration to handle the HTTP/HTTPS traffic. |
|
Back to top |
|
tangent Moderator
Joined: 16 Aug 2020 Posts: 348 Location: UK
|
Posted: Fri 28 Jan '22 22:48 Post subject: |
|
|
Thanks for the extra detail, though I have to confess to being a little confused.
So you need Apache to act as a secure authenticating frontend proxy to your Zope 4 backend. This should be fairly straightforward.
The issue seems to be you're not forwarding the relevant mod_auth_mellon variables on to the Zope server, and based on the detail posted to date, this would need to be passed as request headers through mod_proxy.
Can you anonymize the relevant parts of your configuration and post it to https://apaste.info for people to review? |
|
Back to top |
|
cbas
Joined: 12 Jan 2022 Posts: 11 Location: Bloomington, MN
|
Posted: Sat 29 Jan '22 0:37 Post subject: |
|
|
Chrome told me apaste.ionfo was insecure, so I used pastebin.
https://pastebin.com/HkQNE1Hw
That is my sanitized ssl.conf
Looks like we're already using a simple proxy. I've started reading the mod_proxy documentation, but it's too late in the day for any of it to make sense right now.
Thanks for looking. |
|
Back to top |
|
tangent Moderator
Joined: 16 Aug 2020 Posts: 348 Location: UK
|
Posted: Sat 29 Jan '22 23:51 Post subject: |
|
|
Thanks for the pastebin post, though I have to confess to being more confused than before. In particular, these entries perplex me:
Code: | <Directory proxy:http://localhost:8080/>
|
How can your Directory directive contain something like proxy:http? This parameter is supposed to be a local directory path on the Apache server. Equally, why does this complex rewrite target URL, for assorted site paths, apparently contain two host and port references in the target URL?
Code: | RewriteRule ^/(.*) http://localhost:8080/VirtualHostBase/https/_hhh_:443/$1 [P]
|
Error handling aside, I'd propose a more traditional proxy configuration, probably based on site location, passing requests through to your chosen backend server, e.g.
Code: |
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
<VirtualHost *:443>
<LocationMatch ^/(.*)$>
ProxyPass / http://localhost:8080/$1
ProxyPassReverse / http://localhost:8080/$1
</LocationMatch
</VirtualHost>
|
Can you also post some of your auth_mellon configuration settings (anonymized), to try and work out why the Melllon variables are not being passed to your back end? |
|
Back to top |
|
cbas
Joined: 12 Jan 2022 Posts: 11 Location: Bloomington, MN
|
Posted: Mon 31 Jan '22 22:26 Post subject: |
|
|
I don't know why `<Directory proxy:http://localhost:8080/>` is in the ssl.conf. Our current admin could not explain it. That config was introduced before she started. I took it out and the website seems to perform properly.
That RewriteRule was taken from the Zope documentation. There's no explanation of VirtualHostBase. They refer to the documentation for mod_rewrite.
I commented out the RewriteRule and used ProxyPass/ProxyPassReverse instead (without the VirtualHostBase).
It broke our website - errors of "mixed content" directing me to use HTTPS happened.
Using ProxyPass/ProxyPassReverse with the full VirtualHostBase URL the website appears to function normally.
However, even with the strange Directory directive removed and using ProxyPass instead of the less efficient RewriteRule, I'm still not getting any more coming through in the REQUEST.environ.
I'll work on a sanitized mellon.conf and post it later. |
|
Back to top |
|
cbas
Joined: 12 Jan 2022 Posts: 11 Location: Bloomington, MN
|
Posted: Mon 31 Jan '22 23:34 Post subject: |
|
|
https://pastebin.com/EVKbgeka
That's my mellon.conf.
IIRC, the only non-default I'm using is turning the diagnostics on. |
|
Back to top |
|
tangent Moderator
Joined: 16 Aug 2020 Posts: 348 Location: UK
|
Posted: Mon 31 Jan '22 23:46 Post subject: |
|
|
I'm not familiar with Zope, but a quick check of their documentation concerning VirtualHostBase shows it can act as a proxy rewriting URLs to other servers - https://zope.readthedocs.io/en/latest/zopebook/VirtualHosting.html. So reading that explains why your original RewriteRule makes sense.
Code: | RewriteRule ^/(.*) http://localhost:8080/VirtualHostBase/https/_hhh_:443/$1 [P] |
The ultimate target is https://_hhh_:443/$1
Re the mixed content errors, your site frontend is https, whilst my suggestion using ProxyPass in a location block was targeting http on port 8080, not realising Zope would further rewrite the target to an https resource elsewhere - your _hhh_ server. The response body from Zope doubtless contained http:// references, which would cause problems.
My logic with the LocationMatch block I posted was also flawed, so you could revert to your previous RewriteRule entry, or try this revised block.
Code: | <Location "/">
ProxyPass "http://localhost:8080/VirtualHostBase/https/_hhh_:443/"
ProxyPassReverse "http://localhost:8080/"
</Location> |
This still leaves your MELLON variable problem of course, for which I think you will have to set RequestHeaders to pass on to your Zope server through the proxy connection. |
|
Back to top |
|
tangent Moderator
Joined: 16 Aug 2020 Posts: 348 Location: UK
|
Posted: Tue 01 Feb '22 16:16 Post subject: |
|
|
Ok, looking at your mellon.conf post, and reading up a little on mod_auth_mellon, I was wondering why you don't use MellonSetEnv or MellonSetEnvNoPretix, rather than conditional Apache SetEnv directives later on. That way you're sure the variables get set as part of the authentication phase.
Also note these variables only get passed through to other Apache sever modules, CGI scripts and SSI pages. They won't get passed through as request parameters to any proxied backend service. Hence my suggestion of setting request headers, e.g.
Code: |
# Pass the MELLON environment thru that we need
#
# uid
RequestHeader set HTTP_SAML_UID %{MELLON_urn:oid:0.9.2342.19200300.100.1.1}e env=MELLON_urn:oid:0.9.2342.19200300.100.1.1
# email
RequestHeader set HTTP_SAML_EMAIL %{MELLON_urn:oid:0.9.2342.19200300.100.1.3}e env=MELLON_urn:oid:0.9.2342.19200300.100.1.3
|
Also, in your SAML test block, the header echo directive copies matching request headers to response headers, so the fact you don't see anything rather confirms Mellon derived request headers weren't set. The following should echo any request headers with a HTTP_SAML_ prefix.
Code: |
Header always echo ^HTTP_SAML_.*
|
|
|
Back to top |
|
cbas
Joined: 12 Jan 2022 Posts: 11 Location: Bloomington, MN
|
Posted: Tue 01 Feb '22 17:21 Post subject: |
|
|
:facepalm: I misinterpreted/conflated the documentation on MellonSetEnv with the config to set the "MELLON_" prefix.
Thank you for being an extra set of eyes.
Also, the RequestHeader config worked! Thank you!
As I stated up-thread, I'm learning all of this Apache admin as I go. My google-fu is not the greatest. I've searched for Apache training and can't find any beyond the most basic level - and at the basic level, Apache just works out of the box.
So, once again, thank you! |
|
Back to top |
|
alfred0809
Joined: 22 May 2022 Posts: 2 Location: Bangalore
|
|
Back to top |
|
|
|
|
|
|