Самый простой способ переключить пользователя linux на веб-сервер (django) без sudo? - PullRequest
0 голосов
/ 23 февраля 2011

Цель: создать дружественный для пользователя веб-интерфейс для программы linux без всяких ssh (консольных) ужасных вещей.Я выбрал Python + Django + Apache.Проблема: пользователь должен войти в систему через браузер для пользователя Linux, а затем все запросы пользователя должны быть обработаны от имени этого пользователя Linux.К настоящему моменту сервер запускается от имени пользователя root, и когда пользователь входит в систему через браузер, пользователь root может переключиться на нужного пользователя, используя имя пользователя django:

uid = pwd.getpwnam(userName)[2]
os.setuid(uid)

, и может выполнять все функции django от имени соответствующего пользователя.


Проблема в том, что сервер должен быть запущен от имени пользователя root!Как я могу предоставить возможность нормально запускать сервер с обычными правами пользователя apache, предоставляя логин пользователю linux через браузер?(Просто получите имя пользователя и PWD из запроса POST Http и войдите в систему для соответствующего пользователя с помощью Python)?


Обновление: мне нужно сопоставить любого пользователя через Интернет с конкретным пользователем linux, чтобы дать ему его домашний каталогвыполнять определенную программу Linux только как этот конкретный пользователь!Я предполагаю, что что-то подобное реализовано в webmin?


Возможное решение: я мог бы выполнить su userName, но это не работает без терминала:

p = subprocess.Popen(["su", "test"], stdout = subprocess.PIPE, stdin = subprocess.PIPE, stderr = subprocess.STDOUT)
suOUT = p.communicate(input="test")[0]
print suOUT

Я только что получил:

su: должен запускаться с терминала

Ответы [ 2 ]

1 голос
/ 23 февраля 2011

Я не уверен, что «стандартные» подходы для решения этой проблемы. Тем не менее, это простой метод для сред с небольшим количеством пользователей, которые не включают sudo и не изменяют UID внутри веб-сервера (это может быть очень проблематичным для одновременного доступа нескольких пользователей. пользователей).

Запустить процесс демона для каждого пользователя, имеющего доступ к этому приложению. Этот процесс должен сам обслуживать веб-запросы для этого пользователя через FastCGI (заменять протокол по вашему выбору). У вашего веб-сервера должно быть какое-то сопоставление пользователя с номером порта. Затем перенаправьте запросы вашего шлюза на соответствующий процесс FastCGI на основе входа в систему, используемого пользователем Django.

Пример (использование перенаправлений internal по NGINX, при условии установки с FastCGI):

  1. Пользователь foo входит в веб-приложение Django
  2. Страница запросов пользователя /.../
  3. Приложение Django получает запрос на /.../ от пользователя foo
  4. Приложение Django возвращает настраиваемый заголовок HTTP X-Accel-Redirect, чтобы указать внутреннее перенаправление на /delegate/foo/.../.
  5. NGINX forwards находит местоположение /delegate/foo/, связанное с обработчиком FastCGI на порту 9000
  6. Обработчик FastCGI работает от имени пользователя foo и предоставляет доступ к содержимому в домашнем каталоге.

Вы можете заменить веб-сервер и протокол связи на комбинации по вашему выбору. Я использовал FastCGI здесь, потому что он позволяет писать и шлюз и обработчик как приложения Django. Я выбрал NGINX из-за функции перенаправления internal. Это предотвращает олицетворение путем прямого использования /delegate/foo/.../ URL-адресов пользователями, отличными от foo.

Обновление

Пример:

Если у вас есть модуль flup, вы можете запустить сервер FastCGI напрямую с помощью Django. Чтобы запустить приложение Django через FastCGI под определенной учетной записью пользователя, вы можете использовать:

sudo -u $user python /absolute/path/to/manage.py runfcgi host=127.0.0.1 port=$port

Замените $user на имя пользователя и $port на уникальный порт для этого пользователя (два пользователя не могут использовать один и тот же порт).

Предполагая конфигурацию NGINX, вы можете настроить ее следующим образом:

location /user/$user {
    internal;

    fastcgi_pass 127.0.0.1:$port;
    # additional FastCGI configuration...
}

Обязательно добавьте одну такую ​​директиву для каждой комбинации $user и $port выше.

Затем, из вашего внешнего приложения Django, вы можете проверить разрешения и прочее, используя:

@login_required
def central_dispatch_view ( request ):
    response = HttpResponse()
    response['X-Accel-Redirect'] = '/user/'+request.user.username
    return response

Отказ от ответственности: Это полностью не проверено, и спустя почти год после первоначального ответа, я не уверен, что это возможно, главным образом потому, что документация по XSendFile в NGINX указывает, что это должно работать с статическими файлами . Я больше не спрашивал, можно ли на самом деле выполнить внутреннее перенаправление NGINX из приложения FastCGI.

Альтернативный раствор: Лучший подход может включать не внутренние перенаправления, а использование авторизатора FastCGI. По сути, FastCGI - это программа, которую ваш веб-сервер запускает перед обработкой запроса. Затем вы можете обойти теневое внутреннее перенаправление и просто иметь авторизатор FastCGI, который проверяет, действительно ли запрос на доступ к /user/foo/ может быть получен от пользователя Django, вошедшего в систему как foo. Эта программа-авторизатор не сможет работать как приложение Django (поскольку это не цикл HTTP-запроса / ответа), но вы можете написать его, используя flup и получить доступ к настройкам Django.

1 голос
/ 23 февраля 2011

Вы можете включить пользователя wsgi в файл sudoers и ограничить количество команд и аргументов, которые он может запускать.Почему вы не можете использовать sudo?

, например:

Cmnd_Alias     TRUSTED_CMDS = /bin/su johndoe /some/command, \
                             /bin/su janedoe /some/command

my_wsgi_user   ALL = NOPASSWD: TRUSTED_CMDS

С точки зрения безопасности, вы должны предполагать, что пользователи имеют доступ к оболочке - я думаю, что это нормально для корпоративной интрасети, но недля общедоступного сайта.

Из python / django вы сможете звонить ['sudo', '/bin/su', 'johndoe', '/some/command'].

Другое решение, если вы действительно не можете использовать sudo (с NOPASSWD), это подключиться через ssh с помощьюучетные данные пользователя (пользователь, пароль) с paramiko.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...