[TIP] Apache module to authenticate a NativeSPApacheConfig to the backend app and sign attributes

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

[TIP] Apache module to authenticate a NativeSPApacheConfig to the backend app and sign attributes

Tom Noonan
I'd like to highlight an Apache2 module which makes a
NativeSPApacheConfig authenticating proxy configuration which proxies
to a backend service that is not launched by Apache more robust.
https://github.com/Root-App/mod_proxy_jwt_auth is a module that allows
the Apache instance to authenticate to the backend app via a json web
token (JWT), and will pass attribute environment variables set by
mod_shib as claims in the JWT resolving header spoofing concerns.  In
an environment that runs a NativeSPApacheConfig as a authenticating
proxy, with mod_proxy_jwt_auth configured in Apache to pass shib
attributes and sign the header, and where the backend server is
running independently of Apache this module resolves the following
pain points:

- The backend app can be configured to verify the header added by
mod_proxy_jwt_auth is properly signed using off-the-shelf JWT
libraries and not serve content if the header isn't valid.  This
resolves concerns about the backend server being misconfigured and
accepting requests that do not go through the NativeSPApacheConfig,
which is a concern when running in cloud environments like AWS.  In
this configuration the backend server still requires authentication
(from Apache) to serve content, but the SAML heavy lifting is left to
Shibboleth.

- mod_proxy_jwt_auth will add Shibboleth environment variables to the
token and sign them.  When signature verification is on then the
backend server can be confident the header variables are not spoofed.
This allows ShibUseEnvironment to be used as recommended in an
environment where the backend server process cannot access Apache
environment variables.

Here is an example config that passes name-id and Shib-Session-ID
through via the Authorization header:

<Location /example>
    ProxyJwtAuthEnabled On
    ProxyJwtAuthTokenAlgorithm RS256
    ProxyJwtAuthTokenAlgorithmKeyPath /etc/httpd/ssl/jwt_key.pem
    ProxyJwtAuthClaimMap name-id name-id
    ProxyJwtAuthClaimMap Shib-Session-ID shib-session-id

    AuthType shibboleth
    ShibRequestSetting requireSession 1
    require shib-session
    ShibUseEnvironment On
    ShibUseHeaders Off
</Location>

Then the backend app can decode the bearer JWT token in the
Authorization header and use the name-id and session-id it returns.
In Ruby the decode is one line of code using the JWT gem.

More details on JWTs are at jwt.io.  Hope this helps someone.

--Tom Noonan II
--
For Consortium Member technical support, see https://wiki.shibboleth.net/confluence/x/coFAAg
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: [TIP] Apache module to authenticate a NativeSPApacheConfig to the backend app and sign attributes

Peter Schober
* Tom Noonan <[hidden email]> [2018-05-03 18:22]:
> In this configuration the backend server still requires
> authentication (from Apache) to serve content, but the SAML heavy
> lifting is left to Shibboleth.

That's what Shibboleth was created for, of course.

> - mod_proxy_jwt_auth will add Shibboleth environment variables to the
> token and sign them.  When signature verification is on then the
> backend server can be confident the header variables are not spoofed.

Your tip fails to explain why you'd not run Shibboleth on the web
server protecting the resource, but some other httpd module instead,
securing the traffic between the SAML SP and the resource web server
with another "protocol"?
-peter
--
For Consortium Member technical support, see https://wiki.shibboleth.net/confluence/x/coFAAg
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: [TIP] Apache module to authenticate a NativeSPApacheConfig to the backend app and sign attributes

Tom Noonan
> That's what Shibboleth was created for, of course.

And it does it very well!

> Your tip fails to explain why you'd not run Shibboleth on the web server protecting the resource

That's because my original post assumes someone not running the
traditional "Apache runs the backend" model already has their own
reasons to do so.  In a traditional configuration where Apache forks
the backend service then no, this tip doesn't apply.  An environment
where Apache and the backend service are isolated for some reason is
the case this tip is aimed at.

An example use case is a docker micro-service environment where Apache
and the backend server are in different docker containers.  Having
Apache as a standalone authenticating reverse proxy which connects to
a different backend http server (For example Puma, Sinatra, or Flask)
over TCP is useful in some environments, and this tip is intended to
simply point out a way to make this configuration more secure and
robust.  I'm not trying to advocate one method over the other, they
both have pros and cons unique to the individual deployment.
--Tom Noonan II


On Thu, May 3, 2018 at 1:03 PM, Peter Schober
<[hidden email]> wrote:

> * Tom Noonan <[hidden email]> [2018-05-03 18:22]:
>> In this configuration the backend server still requires
>> authentication (from Apache) to serve content, but the SAML heavy
>> lifting is left to Shibboleth.
>
> That's what Shibboleth was created for, of course.
>
>> - mod_proxy_jwt_auth will add Shibboleth environment variables to the
>> token and sign them.  When signature verification is on then the
>> backend server can be confident the header variables are not spoofed.
>
> Your tip fails to explain why you'd not run Shibboleth on the web
> server protecting the resource, but some other httpd module instead,
> securing the traffic between the SAML SP and the resource web server
> with another "protocol"?
> -peter
> --
> For Consortium Member technical support, see https://wiki.shibboleth.net/confluence/x/coFAAg
> To unsubscribe from this list send an email to [hidden email]
--
For Consortium Member technical support, see https://wiki.shibboleth.net/confluence/x/coFAAg
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: [TIP] Apache module to authenticate a NativeSPApacheConfig to the backend app and sign attributes

Peter Schober
* Tom Noonan <[hidden email]> [2018-05-03 19:28]:
> An example use case is a docker micro-service environment where
> Apache and the backend server are in different docker containers.

You could also run shibd on the docker host (or on another
container) and share its unix domain socket with the (other) container
running httpd+mod_shib.

> Having Apache as a standalone authenticating reverse proxy which
> connects to a different backend http server (For example Puma,
> Sinatra, or Flask) over TCP is useful in some environments

OK.

Personally I wouldn't see those as -- or use their embedded -- HTTP
servers, instead I'd use uwsgi as application server and connect to
that from Apache httpd (running mod_shib) using mod_proxy_uwsgi.

Works great for Python, Perl, Rack (incl Sinatra) apps or anything
else uwsgi has support for (so not node.js and not Java, for which
there's Jetty/Tomcat, of course.)
For PHP I'd use PHP-FPM as separate fcgi server and connect to its
unix domain socket (or TCP socket) from httpd (running mod_shib) using
mod_proxy_fcgi.
In all of those cases the application or framework doesn't have to
know anything about SAML, runs as unpriviledged separate user
(possibly in another container), and in none of these cases do you
have to proxy HTTP from httpd.

Cheers,
-peter
--
For Consortium Member technical support, see https://wiki.shibboleth.net/confluence/x/coFAAg
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: [TIP] Apache module to authenticate a NativeSPApacheConfig to the backend app and sign attributes

Peter Schober
In reply to this post by Tom Noonan
* Tom Noonan <[hidden email]> [2018-05-03 18:22]:
> - mod_proxy_jwt_auth will add Shibboleth environment variables to
> the token and sign them.  When signature verification is on then the
> backend server can be confident the header variables are not
> spoofed.

So no confidentiality (encryption)?
How about key rollover for the signing key, with potentially dozens
(or more) of JWT "clients"?
-peter
--
For Consortium Member technical support, see https://wiki.shibboleth.net/confluence/x/coFAAg
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: [TIP] Apache module to authenticate a NativeSPApacheConfig to the backend app and sign attributes

Pete Birkinshaw-2
In reply to this post by Tom Noonan
Thanks, this is interesting - there are situations where this could be useful for me, such as when running apps on backend containers via smart proxies like Traefik. More as glue within one distributed service, rather than as a general proxy, but still looks like a rather neat thing to add to the toolbox.

Cheers!

Pete

-- 
Pete Birkinshaw, Founder 
Digital Identity Ltd | http://www.digitalidentity.ltd.uk 
Registered in England and Wales No. 7121888 

On 3 May 2018 at 17:20:45, Tom Noonan ([hidden email]) wrote:

I'd like to highlight an Apache2 module which makes a
NativeSPApacheConfig authenticating proxy configuration which proxies
to a backend service that is not launched by Apache more robust.


--
For Consortium Member technical support, see https://wiki.shibboleth.net/confluence/x/coFAAg
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: [TIP] Apache module to authenticate a NativeSPApacheConfig to the backend app and sign attributes

Pete Birkinshaw-2
In reply to this post by Peter Schober
(I should have learned to read an entire thread before replying by now…)

I wasn’t aware of Ruby's Rack being compatible with mod_proxy_uwsgi either, so that’s another useful tool to have available - thanks.

In most cases now I’m plumbing things together with HTTP - it’s less efficient, and the issue of trusting/protecting headers is definitely a problem (hence this discussion) but it’s simple and universal - there’s a huge ecosystem of parts you can loosely couple together. The raw speed of some modern HTTP frameworks now makes up for some of the inefficiencies of the protocol.

Of course, you can then end up with a large number of loosely-coupled bits to manage...

Pete

-- 
Pete Birkinshaw, Founder 
Digital Identity Ltd | http://www.digitalidentity.ltd.uk 
Registered in England and Wales No. 7121888 

On 4 May 2018 at 10:24:05, Peter Schober ([hidden email]) wrote:


Personally I wouldn't see those as -- or use their embedded -- HTTP
servers, instead I'd use uwsgi as application server and connect to
that from Apache httpd (running mod_shib) using mod_proxy_uwsgi.


--
For Consortium Member technical support, see https://wiki.shibboleth.net/confluence/x/coFAAg
To unsubscribe from this list send an email to [hidden email]

--
For Consortium Member technical support, see https://wiki.shibboleth.net/confluence/x/coFAAg
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: [TIP] Apache module to authenticate a NativeSPApacheConfig to the backend app and sign attributes

Tom Noonan
In reply to this post by Peter Schober
> So no confidentiality (encryption)?

No, no encryption, that's outside the scope of JWTs.  JWTs are
basically simple envelops designed to securely represent claims
between parties in a URL-safe fashion.  They are just base64 encoded
JSON for the JWT header and the claim payload, with an optional
signature that can be used to ensure the data came from the expected
source.  If confidentially is desired the recommendation is to encrypt
the connection, using https in this example, so all the data is
encrypted.  (I can't quickly find this recommendation in writing, but
it's the consensus I've gathered from research and presentations on
JWTs.)  Encrypting the traffic between processes isn't really a JWT
concern anyway, as if confidentially is needed between the proxy and
the backend server then that should be set up regardless of using JWTs
or not.  So connection encryption and confidentiality is something
that would need to be taken into account and resolved regardless of
using mod_proxy_jwt_auth.

> How about key rollover for the signing key, with potentially dozens (or more) of JWT "clients"?

This is something that would need to be solved for the needs of the
deployment and environment.  This isn't much different then rolling
SSL keys when using client SSL certificates for authorization.  JWTs
themselves don't have any rollover mechanism, they're just signed with
the key given.  In an environment where shib and the backend server(s)
are loosely coupled then this may be a challenge, if the certificates
don't match with signing on then the backend server should reject the
connection.  How to solve this depends on the deployment and tools in
use.  The backend application could be programmed to check the JWTs
against multiple keys, allowing for multiple signing keys to be live
without downtime.  Tools like Ansible/Chef/Puppet could be used to
roll the keys rapidly so only a small number of connections fail
during rollover.  In our environment we tightly couple Shib to the
backend, despite using HTTP over TCP between Apache and the backend,
so we just have our deployment tool generate a keypair for the
container configuration when we deploy.

These are all great things to call out and need to be considered,
thanks for mentioning them.  When deciding to use this tool the cost
of this complexity needs to be taken into account vs other solutions.
As mentioned in other posts there are other ways to solve the concerns
this module addresses, such as having Apache fork the backend and/or
using Unix sockets to prevent the backend server from accepting
connections in an insecure fashion.  I believe mod_proxy_jwt_auth is
useful when proxying to the backend over any TCP protocol as it allows
the backend app to ensure the request came from the expected Apache
server, not from some other unexpected process hitting the listener.
When using mod_proxy_jwt_auth I expect then deploying engineer to have
their own reasons for wanting to use TCP between Apache and the
backend where the negatives of key management and confidentially are
outweighed by their environment-specific concerns.  mod_proxy_jwt_auth
is intended to help make that configuration more secure.
--Tom Noonan II


On Fri, May 4, 2018 at 5:22 AM, Peter Schober
<[hidden email]> wrote:

> * Tom Noonan <[hidden email]> [2018-05-03 18:22]:
>> - mod_proxy_jwt_auth will add Shibboleth environment variables to
>> the token and sign them.  When signature verification is on then the
>> backend server can be confident the header variables are not
>> spoofed.
>
> So no confidentiality (encryption)?
> How about key rollover for the signing key, with potentially dozens
> (or more) of JWT "clients"?
> -peter
> --
> For Consortium Member technical support, see https://wiki.shibboleth.net/confluence/x/coFAAg
> To unsubscribe from this list send an email to [hidden email]
--
For Consortium Member technical support, see https://wiki.shibboleth.net/confluence/x/coFAAg
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

RE: [TIP] Apache module to authenticate a NativeSPApacheConfig to the backend app and sign attributes

Cantor, Scott E.
> (I can't quickly find this recommendation in writing,
> but it's the consensus I've gathered from research and presentations on
> JWTs.)  Encrypting the traffic between processes isn't really a JWT concern
> anyway, as if confidentially is needed between the proxy and the backend
> server then that should be set up regardless of using JWTs or not.  So
> connection encryption and confidentiality is something that would need to
> be taken into account and resolved regardless of using
> mod_proxy_jwt_auth.

The community in question is allergic to crypto to begin with, but the same spec that governs signing JSON addresses encryption (JOSE). You can't have meaningful confidentiality with a transport layer channel unless you bind the channel to the authentication that's done, otherwise you're open to MITM attacks. Message encryption is important in most scenarios that involve message signing/authentication.

Cool work, BTW.

-- Scott

--
For Consortium Member technical support, see https://wiki.shibboleth.net/confluence/x/coFAAg
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: [TIP] Apache module to authenticate a NativeSPApacheConfig to the backend app and sign attributes

Peter Schober
In reply to this post by Tom Noonan
* Tom Noonan <[hidden email]> [2018-05-03 19:28]:
> An environment where Apache and the backend service are isolated for
> some reason is the case this tip is aimed at.

I just realized we actually have deployed a service that operates in
this exact way, where (our) httpd+shib ("frontend") performs
authn+authz and then HTTP reverse proxies everything (with attributes
sent as custom HTTP request headers) to a remove server ("backend"),
run by another party (our Federal Ministry of the Interior).

In that case we've been using TLS to mutually authenticate the
frontend and backend, with the proxy having its own key pair, cf.
http://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslproxymachinecertificatefile

Over both "nothing" and using JWT w/o TLS that provides: mutual
authentication (here with a private CA), seamless key roll-over on
both sides, confidentiality of the transport.

(Not surprisingly in this specific case the CA was imposed by the
owner of the proxied resource, so at least it isn't mine to operate,
merely to renew client certs once in a while.)

Just to +1 the "TIMTOWTDI"...

-peter
--
For Consortium Member technical support, see https://wiki.shibboleth.net/confluence/x/coFAAg
To unsubscribe from this list send an email to [hidden email]