Shell script с root правами из PHP?

Задача:

с помощью приложения на PHP порождать некие процессы, работающие от конкретного (отличного от пользователя, от которого работает web-сервер) пользователя.

ПО:

Debian Linux

Apache

PHP


Сейчас, как вы можете догадаться, от apache отпочковываются процессы, работающие под его же пользователем, что естественно не есть гуд по нескольким причинам: 1) если понадобилось ребутнуть apache (или он не дай бог крэшнется сам), то упадут все процессы, порожденные от него 2) кривые права доступа для учетки www-data в связи с тем, что ей тоже нужны права на запуск экземпляров приложения, лежащего вне директории web-сервера. Хватит это терпеть, подумал я…

Решение:

Был написан shell script, который умеет запускать приложение от конкретного пользователя. Он был протестирован от root-а через консольку — работет. Через PHP выполняем shell_exec(), который запускает наш скрипт с некоторыми параметрами (условно, для простоты понимания, с сетевым портом, который будет слушать экземпляр приложения). Осталось разобраться с правами www-data на запуск скрипта от root-а. Ну так же ж есть sudo, подумал я… Вот тут-то и возникли сложности.

Реализация:

Положим, что бинарник приложения лежит (условно) тут /home/app/bin. Пользователь username, от которого мы собираемся запускать экземпляры, имеет полный доступ (rwx) как к директории так и к бинарнику.

Файлы web-сервера как и положено валяются где-то в /var/www. Apache работает от пользователя www-data.

Shell script лежит (условно) в /var/www/script.sh. Полные права доступа (rwx) к нему имеет только root, все остальные делать с ним ни чего не могут. Он тщательно проверяет входные параметры (существование пути, существование бинарника и другие проверки) и запускает экземпляр приложения следующей командой:
su -s /bin/bash -c "cd $APP_PATH; ./$APP_BIN $APP_PARAMS > /dev/null 2>&1 &" "$USER_NAME"
или условно
su -s /bin/bash -c "cd /home/app/; ./bin -p 27100 > /dev/null 2>&1 &" username


Остается позволить www-data запускать script.sh от root-а. Ставим sudo,

идем в /etc/sudoers и добавляем:
www-data ALL=(root) NOPASSWD: /var/www/script.sh


По ощущениям этого достаточно и по тем же ощущениям подозрения — слишком просто.

Теперь из PHP вызываем наш скрипт:
shell_exec("cd /var/www/; sudo ./script.sh -p 27100");


Не работает :(


Пробуем по другому (через консоль):
su -s /bin/bash www-data
cd /var/www/
sudo ./script.sh -p 27100


Появляется мало ожидаемое приглашение ввести пароль пользователя www-data:
[sudo] password for www-data:

А NOPASSWD на что? Да и вообще какого хрена пароль у www-data? :(

Собственно, что я делаю не так?


Понятное дело, что православность решения мягко говоря под сомнением, но пока хочется «добить» хотя бы его (силы-то и время уже потрачены). Другие решения придут (надеюсь) позднее с новым опытом.
  • Вопрос задан
  • 27478 просмотров
Решения вопроса 1
faustoFF
@faustoFF Автор вопроса
Проблема решилась. Во всем виновата собственная невнимательность. Моя опечатка в описании помогла мне найти опечатку в реальных конфигах в этом же месте (путь к скрипту в sudoers и реальный путь не совпадали) :) Теперь скрипт успешно отрабатывает из под www-data от root-а с рутовыми же правами.

Забавно, из-за собственной невнимательности сгенерировал такое обсуждение. Надеюсь кому-то это окажется полезным.
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
pawnhearts
@pawnhearts
во-первых, у вас указано /home/script.sh в sudoers, а лежит он в /var/www?

во-вторых, у sudo есть опция -u, зачем становиться рутом а оттуда вызывать su, если можно сразу из sudo запустить под нужным пользователем
Ответ написан
pawnhearts
@pawnhearts
и ещё, есть такая команда disown, попробуйте использовать её вместо ">/dev/null 2>&1 &"
Ответ написан
7workers
@7workers
bash скрипт соблюдает все права доступа, то, что вы смогли запустить script.sh от имени рута не значит, что всё что внутри script.sh будет выполняться от имени рута. Попробуйте ваш script.sh переделать так:

#!/bin/sh

foo() {

/bin/can /etc/passwd

}

export -f foo
su -c 'foo'
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
FunBox Москва
от 120 000 ₽
FunBox Санкт-Петербург
от 120 000 ₽
FunBox Екатеринбург
от 120 000 ₽