Using SSL client certificate in a Pyramid application

34 views
Skip to first unread message

Thierry Florac

unread,
Nov 15, 2023, 9:13:39 AM11/15/23
to pylons-...@googlegroups.com
Hi,
My problem is probably quite simple: I would like to be able, in a Pyramid application, to create a custom security policy which could use an SSL client certificate as a request credential to handle authentication (authorized certificates being referenced in a database or stored in a specific server directory).
This application is then supposed to be published via mod_wsgi in an Apache server located behind an HAProxy.
I tried to search here and there but didn't find any information about this...
Any hint?

Best regards,
Thierry

Theron Luhn

unread,
Nov 15, 2023, 12:43:11 PM11/15/23
to 'Jonathan Vanasco' via pylons-discuss
I’m unsure what this “request credential” is.  Are you talking about TLS Mutual Auth?

— Theron



--
You received this message because you are subscribed to the Google Groups "pylons-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pylons-discus...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pylons-discuss/CAPX_VWBosR7p%3DLb%2BzEXWKuwuuENy6CORPrVpHaRMU9qWV4uW4g%40mail.gmail.com.

Thierry Florac

unread,
Nov 15, 2023, 1:06:23 PM11/15/23
to pylons-...@googlegroups.com
Hi Theron,

I'm not sure of the exact naming of this!
The common idea behind it is just to use an SSL client certificate as a credential to authenticate an incoming request; this is generally used to authenticate a remote application more than a common user...

Regards,

tonthon

unread,
Nov 15, 2023, 1:55:17 PM11/15/23
to pylons-...@googlegroups.com
Hi Thierry,

You'll have to define a way to send the certificate through http/https calls since I don't think there is a normalized way to do that.

Once you've defined that, the certificate can be retrieved server side and validated like you would do with a bearer token for example.

Best Regards

      
Gaston Tjebbes

Delta Regeer

unread,
Nov 15, 2023, 2:25:52 PM11/15/23
to pylons-...@googlegroups.com
mod_ssl can stuff the information about the mTLS information into server environment variables. If you are using mod_wsgi you should be able to retrieve those. mod_ssl will validate the certificate is valid, and place the information (such as subject name) in the environment and you can use that in your Pyramid application by pulling it out of the environ.


You can then write a Pyramid authentication provider that validates the information in the environment.


Michael Merickel

unread,
Nov 17, 2023, 12:28:11 AM11/17/23
to pylons-...@googlegroups.com
Another example is that Envoy as a proxy supports adding the x-forwarded-client-cert header to your requests after it validates it.


- Michael

On Nov 15, 2023, at 13:25, Delta Regeer <xist...@0x58.com> wrote:

mod_ssl can stuff the information about the mTLS information into server environment variables. If you are using mod_wsgi you should be able to retrieve those. mod_ssl will validate the certificate is valid, and place the information (such as subject name) in the environment and you can use that in your Pyramid application by pulling it out of the environ.

Jonathan Vanasco

unread,
Nov 17, 2023, 11:02:54 AM11/17/23
to pylons-discuss
I do a lot of work with SSL Certs.  If you are using publicly trusted client certificates (i.e. LetsEncrypt, Digisign, etc), then you basically just need to do what Michael suggested - ensure your gateway or server populates the headers or environment variables with the information for the client.  Most implementations for that stuff will also insert a secret-signed header field to ensure the client did not try and stuff headers themselves.  You'd then need to validate the certificate again within python (see workaround #3 below)

I think this is going to be a bit of a headache if you are using untrusted CAs for the client certificates (ie. you control the CA and allocate the certs to your clients/partners) and trying to implement the sort of policy that PostgreSQL and other systems offer with client verification.

The complexity and level of work required come down to the following factors:

* Who will issue the client certificates (a public trusted CA or your own private CA)
* How much validation can you split between the gateway/server and Python (based on application design and business logic constraints), and where can the errors pop-up?

If you are talking about custom CA certs, the two approaches I know of for this sort of stuff:

1- (Easy for developer, harder for client) The client application stuffs the certificate into a header.  Everything happens as normal Pyramid app.  You just write pyramid code to require and validate the certificate header.  This isn't actually mTLS, but uses the client certificate similar to ssl keychains.

2. (Hard for developer, easy for client) Actually use TLS Mutual Auth, which is what Theron first brought up.  With mTLS, the client certificate is presented and validated during the TLS handshake - which means you would need to configure the gateway or mod_wsgi to handle the validation.

The large complexity of #2 is that many web servers / gateways can only be configured with a single client CA or a static client CA store - so building this as scalable to multiple clients may not necessarily be possible.

The three workarounds I can think of are:
1- Don't terminate TLS or validate the client certificate on the gateway, instead pass it all back to a python server like Waitress and see if you can handle everything via middleware to process the SSL connection.

2- Terminate TLS on OpenResty(nginx) and use a Lua script to handle the client validation.  Then you can proxy that back to mod_wsgi.  I opensourced our dynamic SSL certificate tool for OpenResty here - https://github.com/aptise/lua-resty-peter_sslers - it does not do client certificates, but IMHO is a good reference for what you want to accomplish.    it looks like OpenResty has some builtin stuff for this, but if not - those are the correct hooks.  

3- Terminate TLS on the gateway but make it very lax for the client certificate to pass - basically just checking to see if the certificate is valid and from the CA.  Then validate the client a second time in middleware/tween to ensure the certificate is active and allowed.  

Michael Merickel

unread,
Nov 17, 2023, 2:30:12 PM11/17/23
to pylons-...@googlegroups.com
You don’t need a signed header. You just need to make sure your proxy is configured to remove that header from an incoming request and only put validated data into it before sending it to your app. This is standard for other headers set by your proxy as well. Definitely never trust a header without checking those properties of your deployment though. 

- Michael

On Nov 17, 2023, at 10:02, Jonathan Vanasco <jvan...@gmail.com> wrote:


--
You received this message because you are subscribed to the Google Groups "pylons-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pylons-discus...@googlegroups.com.

Jonathan Vanasco

unread,
Nov 20, 2023, 7:17:01 PM11/20/23
to pylons-discuss
100% agree with Michael's comments about signed headers.  When dealing with credentials, a lot of people distrust proxies and testing them - so on top of removing all headers, anything added will be signed (or the aggregate signed) with a low-cost method, which can easily be tested.  
Reply all
Reply to author
Forward
0 new messages