Skip to content

Instantly share code, notes, and snippets.

@jmvrbanac
Last active August 26, 2023 18:13
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jmvrbanac/089540b255d6b40ca555c8e7ee484c13 to your computer and use it in GitHub Desktop.
Save jmvrbanac/089540b255d6b40ca555c8e7ee484c13 to your computer and use it in GitHub Desktop.
Capture Client Certificate CN from Gunicorn
bind: 0.0.0.0:8000
workers: 1
worker_class: "example.worker:CustomWorker"
timeout: 30
ca_certs: ca.crt
certfile: server.crt
keyfile: server.key
cert_reqs: 2
do_handshake_on_connect: true
from gunicorn.workers.sync import SyncWorker
class CustomWorker(SyncWorker):
def handle_request(self, listener, req, client, addr):
subject = dict(client.getpeercert().get('subject')[0])
headers = dict(req.headers)
headers['X-USER'] = subject.get('commonName')
req.headers = list(headers.items())
super(CustomWorker, self).handle_request(listener, req, client, addr)
@botsman
Copy link

botsman commented May 6, 2020

Very useful.
Thank you!

@uedvt359
Copy link

extracting the common name like shown here did not work for us w/ gunicorn 19.9 or 20.0 and python 3.6. this did:

class CustomWorker(SyncWorker):
    def handle_request(self, listener, req, client, addr):
        subject = client.getpeercert().get('subject')
        commonName = next( value for ((key,value),) in subject if key == "commonName" )

        headers = dict(req.headers)
        headers['X-USER'] = commonName
        req.headers = list(headers.items())

        super(CustomWorker, self).handle_request(listener, req, client, addr)

@rokene
Copy link

rokene commented Aug 9, 2020

Awesome, thanks! Slight change on my end to get it to work for me.

Python 3.8 and gunicorn 20.0.4

worker_class: "example.worker:CustomWorker" -> worker_class = "example.worker.CustomWorker"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment