Configurando o REMOTE_USER para o Trac em Gunicorn, atrás do Nginx

4

Eu quero rodar o Trac em Gunicorn, atrás do Nginx. O Nginx manipula a autenticação do usuário via LDAP (que funciona), mas não consigo obter o REMOTE_USER passado para o Trac.

Para o uWSGI eu configuraria o Nginx assim (testado e funciona):

uwsgi_param REMOTE_USER $remote_user;

Para o Gunicorn, não consegui encontrar uma diretiva de configuração semelhante. Eu tentei configurar o cabeçalho, mas não parece mudar nada:

proxy_set_header REMOTE_USER $remote_user;

Existe uma entrada no wiki do Trac sobre isso , observando que "o ponto de entrada do wsgi não lidar com a autenticação ", e uma solução alternativa para lidar com a autenticação básica com um arquivo de senha local, que não é o que eu preciso. Preciso alterar meu ponto de entrada para passar esse REMOTE_USER header para a variável de ambiente correta? Atualmente é só isso:

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
    
por Jan Fabry 15.02.2012 / 11:04

2 respostas

5

Estranho. Eu tenho esse trabalho, incluindo o presente na configuração nginx como você mencionou

proxy_set_header REMOTE_USER $remote_user;

Então, para o arquivo 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)

substitui isso

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

no seu trac.wsgi

Aparentemente, há algo sobre o processo 'HTTP_' que confunde a autenticação do trac

Eu estou supondo que a mesma coisa provavelmente poderia ser realizada fazendo a mesma coisa apenas com o cabeçalho de solicitação 'HTTP_AUTHORIZATION', mas não tentei fazer isso. Então eu não sei com certeza, tudo que eu sei é que funciona agora!

    
por 24.05.2012 / 03:46
2

Eu tive um problema semelhante com o Mercurial; A resposta de byoungb, acima, é OK em princípio, mas deve estar usando X-Remote-User , não REMOTE_USER no proxy_set_header e, em seguida, HTTP_X_REMOTE_USER na chamada environ.get() .

No entanto, como a maioria das pessoas usa SSL e faz a autenticação básica, você pode usar o cabeçalho Authorization (que chega ao seu ambiente como HTTP_AUTHORIZATION ) da seguinte maneira:

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

Então você pode escrever (para o Trac)

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

ou, no meu caso (para o Mercurial)

application = use_basic_auth(hgweb(config))

Isso obviamente não funcionará se você estiver usando algo diferente da autenticação HTTP básica. Nesse caso, você poderia fazer o que byoungb sugere (embora usando um nome de cabeçalho melhor), ou você poderia mover a autenticação para o final das coisas do Python ao invés de fazer o nginx fazê-lo. A desvantagem deste último é que você pode ser mais vulnerável se houver algum buraco de segurança em algum lugar.

    
por 27.02.2013 / 10:42