Назад | Перейти на главную страницу

Установка REMOTE_USER для Trac в Gunicorn за Nginx

Я хочу запустить Trac в Gunicorn за Nginx. Nginx обрабатывает аутентификацию пользователей через LDAP (который работает), но я не могу получить REMOTE_USER перешел к Trac.

Для uWSGI я бы настроил Nginx следующим образом (проверено, работает):

uwsgi_param REMOTE_USER $remote_user;

Для Gunicorn мне не удалось найти аналогичную директиву конфигурации. Я пробовал установить заголовок, но вроде ничего не меняет:

proxy_set_header REMOTE_USER $remote_user;

Там есть запись в Trac wiki об этом, отмечая, что "точка входа wsgi не поддерживает [...] аутентификацию"и обходной путь для обработки базовой аутентификации с помощью локального файла паролей, который мне не нужен. Мне нужно изменить мою точку входа, чтобы пройти это REMOTE_USER заголовок в нужную переменную среды? В настоящее время это просто:

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

Странный. Я получил это, включив это в конфигурацию nginx, как вы упомянули

proxy_set_header REMOTE_USER $remote_user;

Затем для файла trac.wsgi это

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)

заменяет это

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

в вашем trac.wsgi

По-видимому, есть что-то в продолжающемся 'HTTP_', которое портит аутентификацию trac

Я предполагаю, что то же самое, вероятно, можно было бы сделать, сделав то же самое только с заголовком запроса HTTP_AUTHORIZATION, но я не пытался этого. Так что точно не знаю, знаю только то, что теперь это работает!

У меня была аналогичная проблема с Mercurial; Ответ byoungb, приведенный выше, в принципе в порядке, но следует использовать X-Remote-Userне REMOTE_USER в proxy_set_header, а потом HTTP_X_REMOTE_USER в environ.get() вызов.

Однако, поскольку большинство людей используют SSL, а затем выполняют обычную аутентификацию, вы можете использовать Authorization заголовок (который поступает в вашу среду как HTTP_AUTHORIZATION) следующим образом:

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

Тогда вы можете написать (для Trac)

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

или, в моем случае (для Mercurial)

application = use_basic_auth(hgweb(config))

Очевидно, это не сработает, если вы используете что-то, кроме базовой аутентификации HTTP. В этом случае вы можете либо сделать то, что предлагает byoungb (хотя и использовать более удачное имя заголовка), либо перенести аутентификацию на конец Python, а не заставлять nginx делать это. Обратной стороной последнего является то, что вы мощь быть более уязвимым, если где-то есть дыра в безопасности.