Réglage REMOTE_USER pour Trac à Gunicorn derrière Nginx

Je veux exécuter Trac à Gunicorn, derrière Nginx. Nginx gère l'authentification de l'user via LDAP (qui fonctionne), mais je ne peux pas faire passer le REMOTE_USER à Trac.

Pour uWSGI, je configurerais Nginx comme ça (testé et fonctionne):

 uwsgi_param REMOTE_USER $remote_user; 

Pour Gunicorn, je n'ai pas trouvé de directive de configuration similaire. J'ai essayé de définir l'en-tête, mais cela ne semble rien changer:

 proxy_set_header REMOTE_USER $remote_user; 

Il y a une input dans le wiki Trac à ce sujet , notant que «le point d'input wsgi ne gère pas […] l'authentification» et une solution de contournement pour gérer l'authentification de base avec un file de mot de passe local, ce qui n'est pas ce dont j'ai besoin. Dois-je changer mon point d'input pour passer cet en REMOTE_USER tête REMOTE_USER à la bonne variable d'environnement? Actuellement, c'est juste ceci:

 import sys import os sys.stdout = sys.stderr os.environ['TRAC_ENV'] = '/path/to/my/trac' import trac.web.main application = trac.web.main.dispatch_request 

Étrange. J'ai travaillé en incluant ceci dans la configuration nginx comme vous l'avez mentionné

 proxy_set_header REMOTE_USER $remote_user; 

Ensuite, pour le file trac.wsgi, ceci

 import trac.web.main def application(environ, start_application): environ['REMOTE_USER'] = environ.get('HTTP_REMOTE_USER') return trac.web.main.dispatch_request(environ, start_application) 

remplace cela

 import trac.web.main application = trac.web.main.dispatch_request 

dans votre trac.wsgi

Apparemment, il y a quelque chose à propos de la procédure «HTTP_» qui gâche l'authentification de Trac

Je suppose que la même chose pourrait être accomplie en faisant la même chose à l'en-tête de requête "HTTP_AUTHORIZATION" mais je n'ai pas essayé. Donc je ne sais pas avec certitude, tout ce que je sais, c'est que ça fonctionne maintenant!

J'ai eu un problème similaire avec Mercurial; La réponse de byoungb, ci-dessus, est OK en principe, mais devrait utiliser X-Remote-User , pas REMOTE_USER dans proxy_set_header , puis HTTP_X_REMOTE_USER dans l'appel environ.get() .

Cependant, comme la plupart des users utilisent SSL et font une authentification de base, vous pouvez utiliser l'en-tête Authorization (qui arrive dans votre environnement comme HTTP_AUTHORIZATION ) comme suit:

 import base64, re def use_basic_auth(application): def auth_app(environ, start_response): auth = environ.get('HTTP_AUTHORIZATION') if auth: scheme, creds = re.split(r'\s+', auth) if scheme.lower() != 'basic': raise ValueError('Unknown auth scheme \"%s\"' % scheme) user, pword = base64.b64decode(creds).split(':', 1) environ['REMOTE_USER'] = user return application(environ, start_response) return auth_app 

Ensuite, vous pouvez écrire (pour Trac)

 application = use_basic_auth(trac.web.main.dispatch_request) 

ou, dans mon cas (pour Mercurial)

 application = use_basic_auth(hgweb(config)) 

Cela évidemment ne fonctionnera pas si vous utilisez autre chose que l'authentification HTTP Basic. Dans ce cas, vous pouvez soit faire ce que propose byoungb (même si vous utilisez un meilleur nom d'en-tête), ou vous pouvez déplacer l'authentification vers la fin de Python plutôt que de faire en sorte que nginx le fasse. L'inconvénient de ce dernier est que vous pourriez être plus vulnérable s'il y a un trou de security quelque part.