Рекомендуется запускать службу Linux от имени другого пользователя

StackOverflow https://stackoverflow.com/questions/394984

  •  23-08-2019
  •  | 
  •  

Вопрос

Службы по умолчанию запускаются как root во время загрузки на моем RHEL box.Если я правильно помню, то же самое верно и для других дистрибутивов Linux, которые используют сценарии инициализации в /etc/init.d.

Как вы думаете, какой лучший способ вместо этого запустить процессы от имени (статического) пользователя по моему выбору?

Единственный метод, к которому я пришел, состоял в том, чтобы использовать что-то вроде:

 su my_user -c 'daemon my_cmd &>/dev/null &'

Но это кажется немного неопрятным...

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

Редактировать: Я должен был сказать, что процессы, которые я запускаю в этом экземпляре, являются либо скриптами Python, либо программами Java.Я бы предпочел не писать собственную оболочку вокруг них, поэтому, к сожалению, я не могу вызвать setuid() установить идентификатор() как Черный предполагает.

Это было полезно?

Решение

В Debian мы используем start-stop-daemon утилита, которая обрабатывает pid-файлы, меняет пользователя, переводит демон в фоновый режим и многое другое.

Я не знаком с RedHat, но daemon утилита, которую вы уже используете (которая определена в /etc/init.d/functions, кстати.) упоминается везде как эквивалент start-stop-daemon, так что либо это также может изменить uid вашей программы, либо способ, которым вы это делаете, уже правильный.

Если вы поищете в сети, то найдете несколько готовых оберток, которые вы можете использовать.Некоторые из них могут быть даже уже упакованы в RedHat.Взгляните на daemonize, например.

Другие советы

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

  1. хоп правильно указывать мне назад на /etc/init.d/functionsdaemon функция уже позволяет вам установить альтернативного пользователя:

    daemon --user=my_user my_cmd &>/dev/null &
    

    Это реализуется путем обертывания вызова процесса с runuser - подробнее об этом позже.

  2. Джонатан Леффлер это правильно:в Python есть setuid:

    import os
    os.setuid(501) # UID of my_user is 501
    

    Я все еще не думаю, что вы можете setuid однако изнутри JVM.

  3. Ни то , ни другое su ни runuser изящно обработайте случай, когда вы просите запустить команду от имени пользователя, которым вы уже являетесь.Например.:

    [my_user@my_host]$ id
    uid=500(my_user) gid=500(my_user) groups=500(my_user)
    [my_user@my_host]$ su my_user -c "id"
    Password: # don't want to be prompted!
    uid=500(my_user) gid=500(my_user) groups=500(my_user)
    

Чтобы обойти это поведение su и runuser, Я изменил свой сценарий инициализации на что - то вроде:

if [[ "$USER" == "my_user" ]]
then
    daemon my_cmd &>/dev/null &
else
    daemon --user=my_user my_cmd &>/dev/null &
fi

Спасибо всем за вашу помощь!

Если вы намерены написать свой собственный демон, то я рекомендую вызвать setuid().Таким образом, ваш процесс может

  1. Используйте его привилегии root (напримероткройте файлы журнала, создайте файлы pid).
  2. Сбросьте его привилегии root в определенный момент во время запуска.

Просто чтобы добавить еще кое-что, на что следует обратить внимание:

  • Sudo в скрипте init.d никуда не годится, так как для него нужен tty ("sudo:извините, у вас должен быть tty для запуска sudo ")
  • Если вы демонизируете java-приложение, возможно, вам захочется рассмотреть Java Service Wrapper (который предоставляет механизм для установки идентификатора пользователя).
  • Другой альтернативой могло бы быть su --session-command=[cmd] [пользователь]

на виртуальной машине CENTOS (Red Hat) для svn-сервера:отредактированный /etc/init.d/svnserver чтобы изменить pid на что-то, что svn может написать:

pidfile=${PIDFILE-/home/svn/run/svnserve.pid}

и добавлена опция --user=svn:

daemon --pidfile=${pidfile} --user=svn $exec $args

Исходный pid - файл был /var/run/svnserve.pid.Демон не запустился, потому что писать туда мог только root.

 These all work:
/etc/init.d/svnserve start
/etc/init.d/svnserve stop
/etc/init.d/svnserve restart

Некоторые вещи, на которые следует обратить внимание:

  • Как вы упомянули, su запросит пароль, если вы уже являетесь целевым пользователем
  • Аналогично, setuid(2) завершится ошибкой, если вы уже являетесь целевым пользователем (в некоторых операционных системах).
  • setuid(2) не устанавливает привилегии или элементы управления ресурсами, определенные в /etc/limits.conf (Linux) или /etc/user_attr (Solaris)
  • Если вы идете по маршруту setgid(2) / setuid(2), не забудьте вызвать initgroups(3) - подробнее об этом здесь

Обычно я использую /sbin / su для переключения на соответствующего пользователя перед запуском демонов.

Почему бы не попробовать следующее в сценарии инициализации:

setuid $USER application_name

У меня это сработало.

Мне нужно было запустить приложение Spring .jar как сервис, и я нашел простой способ запустить его от имени конкретного пользователя:

Я сменил владельца и группу моего jar-файла на пользователя, от имени которого я хотел запускаться.Затем создал символическую ссылку на этот jar в init.d и запустил службу.

Итак:

#chown myuser:myuser /var/lib/jenkins/workspace/springApp/target/springApp-1.0.jar

#ln -s /var/lib/jenkins/workspace/springApp/target/springApp-1.0.jar /etc/init.d/springApp

#service springApp start

#ps aux | grep java
myuser    9970  5.0  9.9 4071348 386132 ?      Sl   09:38   0:21 /bin/java -Dsun.misc.URLClassPath.disableJarChecking=true -jar /var/lib/jenkins/workspace/springApp/target/springApp-1.0.jar
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top