LINUX.ORG.RU
ФорумAdmin

Получить переменную окружения пользователя из под root

 , ,


0

1

Здравствуйте.

Подскажите, как из под root получить переменную окружения пользователя?

Немного контекста. Есть сервис VPN, который при запуске, для аутентификации(логин, пароль, отп) ходит в пользователельское хранилище паролей(pass) и получает необходимые данные. Для расшифрования паролей используется gpg-агент, который хранит ключи в памяти некоторое время, после которого он их забывает. Для обновления ключей используется программа pinentry, но ей для вызова диалогового окна нужна переменная окружения XAUTHORITY. Собственно остюда и вопрос, как метнуться от имени сервиса к пользователю и получить эту переменную окружения?

Обновление ключа не работает: su rav -c 'gpg --homedir ~rav/.gnupg/ --decrypt ~rav/.password-store/LDAP.gpg 2>/dev/null'

Обновление ключа работает: su rav -c 'XAUTHORITY=/tmp/xauth_zjilik gpg --homedir ~rav/.gnupg/ --decrypt ~rav/.password-store/LDAP.gpg 2>/dev/null'



Последнее исправление: torm7 (всего исправлений: 2)

Нет «переменных окружения пользователя», есть переменные окружения конкретного процесса. У каждого процесса - свои, определяются при его запуске.

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

Системный сервис никакие диалоговые окна создавать не должен.

Кто эту программу запускает и как?

Обновление ключа работает

Так работает или не работает? В чём проблема?

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)
Ответ на: комментарий от firkax

Системный сервис никакие диалоговые окна создавать не должен.

Формально сервис идет к пользователю и от его имени запускает диалоговое окно.

Кто эту программу запускает и как?

Я же приложил два примера, давайте сделаю 4:

  • Из под пользователя:
    • gpg --homedir ~rav/.gnupg/ --decrypt ~rav/.password-store/LDAP.gpg 2>/dev/null - диалоговое окно открывается
    • XAUTHORITY=/tmp/xauth_zjilik gpg --homedir ~rav/.gnupg/ --decrypt ~rav/.password-store/LDAP.gpg 2>/dev/null - диалоговое окно открывается
  • Из под root:
    • su rav -c 'gpg --homedir ~rav/.gnupg/ --decrypt ~rav/.password-store/LDAP.gpg 2>/dev/null' - диалоговое окно не открывается
    • su rav -c 'XAUTHORITY=/tmp/xauth_zjilik gpg --homedir ~rav/.gnupg/ --decrypt ~rav/.password-store/LDAP.gpg 2>/dev/null' - диалоговое окно открывается

Так работает или не работает? В чём проблема?

Надеюсь я понятно описал как работает, а как не работает

torm7
() автор топика
Ответ на: комментарий от torm7

Формально сервис идет к пользователю и от его имени запускает диалоговое окно.

Так и запускай его от пользователя, все переменные будут на месте и не будет никакой возни.

Надеюсь я понятно описал как работает, а как не работает

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

firkax ★★★★★
()
Ответ на: комментарий от firkax

Так и запускай его от пользователя, все переменные будут на месте и не будет никакой возни.

Я еще не видел VPN’ов, запускающихся чисто от пользователя

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

XAUTHORITY=/tmp/xauth_zjilik - это динамически меняющееся значение. Что бы его получить, надо сходить к пользователю и посмотреть переменные окружения.

torm7
() автор топика
Ответ на: комментарий от torm7

Вот это вот как достать от пользователя?

в каком смысле достать? как иксы стартуешь? я например использую sx(аналог xinit), так что оно мне само создает этот файл и потом уже к нему обращаюсь, у меня так рутовый сервис посылает сообщения через dunst пользователю о разряде батареи. так что смотри кто и где у тебя создает этот файл

https://github.com/Earnestly/sx/blob/master/sx

anonymous
()

диалоговое окно не открывается

переменную дисплея тоже наверно надо передавать env DISPLAY=:0 XAUTHORITY=/home/$USER/.Xauthority команда, как-то так вроде

anonymous
()
Ответ на: комментарий от firkax

ps axuww | grep Xorg

[rav@nixos:~]$ ps axuww | grep Xorg
rav         9580  0.0  0.0   6692  2560 pts/1    S+   20:44   0:00 grep Xorg

переменную дисплея тоже наверно надо передавать

нет, я же писал как работает, а как нет. XAUTHORITY=/home/$USER/.Xauthority - это угадайка, такой вариант не подходит. Тем более у меня этого файла нет.

torm7
() автор топика

Не знаю, может эти данные как то помогут:

[rav@nixos:~]$ xauth list
nixos/unix:0  MIT-MAGIC-COOKIE-1  d71ed38404a4b44537fb29d39f97371d
#ffff##:0  MIT-MAGIC-COOKIE-1  d71ed38404a4b44537fb29d39f97371d

[rav@nixos:~]$ xauth info
Authority file:       /tmp/xauth_dieOeN
File new:             no
File locked:          no
Number of entries:    2
Changes honored:      yes
Changes made:         no
Current input:        (argv):1

[rav@nixos:~]$ env | grep XAUTHORITY
XAUTHORITY=/tmp/xauth_dieOeN
torm7
() автор топика

Покопался еще чуток, нашел что похоже в первый раз XAUTHORITY заезжает отсюда:

[root@nixos:~]# systemctl status session-2.scope
● session-2.scope - Session 2 of User rav
     Loaded: loaded (/run/systemd/transient/session-2.scope; transient)
  Transient: yes
     Active: active (running) since Fri 2024-04-05 21:04:58 MSK; 1h 28min ago
         IP: 0B in, 0B out
         IO: 24.0M read, 1.3M written
      Tasks: 22
     Memory: 57.2M
        CPU: 1.242s
     CGroup: /user.slice/user-1000.slice/session-2.scope
             ├─2218 /nix/store/j7cjgz1ls9h0nsjvs7r8smzfxbmxqqwl-sddm-0.20.0/libexec/sddm-helper --socket /tmp/sddm-auth-06895ebd-d283-467e-89e2-da0776d59c5a --id 1 --start /nix/store/l813z7s64anjxsy8q01l2z51q6fy2h8b-plasma-workspace-5.27.10/bin/startp>
             ├─2297 /nix/store/6g15kzn8krpql4biysq2gbgkfx40ramp-kwallet-5.113.0-bin/bin/kwalletd5 --pam-login 13 14
             └─2320 /nix/store/l813z7s64anjxsy8q01l2z51q6fy2h8b-plasma-workspace-5.27.10/bin/startplasma-x11

Конкретно от этого процесса:

[root@nixos:~]# cat /proc/2320/environ | tr '\0' '\n' | grep XAUTHORITY
XAUTHORITY=/tmp/xauth_dieOeN

Вопрос, как оно заезжает туда?

torm7
() автор топика

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

eval "$(systemctl -M <USER>@.host --user show-environment | grep -E '^VAR_NAME=')"

Но это грязный костыль, не делай так.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от torm7

Вопрос, как оно заезжает туда?

Тот, кто запускает X-сервер, эти переменные и устанавливает. В твоём случае — SDDM (точнее, процесс лидера графической сессии).

А в более человеческих системах оно заезжает ещё и сюда:

$ cat /etc/X11/xinit/xinitrc.d/50-systemd-user.sh
#!/bin/sh
#  SPDX-License-Identifier: LGPL-2.1-or-later
#
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

systemctl --user import-environment DISPLAY XAUTHORITY

if command -v dbus-update-activation-environment >/dev/null 2>&1; then
    dbus-update-activation-environment DISPLAY XAUTHORITY
fi
intelfx ★★★★★
()
Ответ на: комментарий от intelfx

Но это грязный костыль, не делай так.

Зато рабочий. А как его правильно вытаскивать? Кстати как оказалось одного XAUTHORITY мало для нормального запуска pinentry от сервиса, видимо окружение сервиса systemd и окружения процессов root гораздо сильнее отличаются чем я думал.

su без -l наследует часть окружения того пользователя, который её вызвал.

Спасибо поправил

torm7
() автор топика
Ответ на: комментарий от torm7

Получился сервис, который толкает такой скрипт:

#!/nix/store/r9h133c9m8f6jnlsqzwf89zg9w0w78s8-bash-5.2-p15/bin/bash
set -e
MESSAGE=$(cat /run/systemd/ask-password/ask.* | grep 'Message=' | cut -b9-)
SOCKET=$(cat /run/systemd/ask-password/ask.* | grep 'Socket=' | cut -b8-)
XAUTHORITY=$(systemctl -M rav@.host --user show-environment | grep -E '^XAUTHORITY=')
echo $MESSAGE
echo $SOCKET
echo $XAUTHORITY
case "$MESSAGE" in
  "Enter Auth Username:" ) echo +$(echo "$(su - rav -c "XAUTHORITY=$XAUTHORITY gpg --homedir ~rav/.gnupg/ --decrypt ~rav/.password-store/LDAP.gpg 2>/dev/null")" | grep "login:" | cut -b8-) | socat - UNIX-SENDTO:$SOCKET
  ;;
  "Enter Auth Password:" ) echo +$(echo "$(su - rav -c "XAUTHORITY=$XAUTHORITY gpg --homedir ~rav/.gnupg/ --decrypt ~rav/.password-store/LDAP.gpg 2>/dev/null")" | head -n 1) | socat - UNIX-SENDTO:$SOCKET
  ;;
  "CHALLENGE: Enter OTP token" ) echo +$(oathtool --totp -b "$(echo $(su - rav -c "XAUTHORITY=$XAUTHORITY gpg --homedir ~rav/.gnupg/ --decrypt ~rav/.password-store/OpenVPN.gpg 2>/dev/null") | grep "CloudVPN" | cut -b54-)") | socat - UNIX-SENDTO:$SOCKET
  ;;
esac
torm7
() автор топика
Ответ на: комментарий от torm7

Естественно. TERM же выставляется конкретно взятым терминалом/эмулятором терминала. А вообще pgrep -u USERNAME -n bash в помощь - скорее всего, там будет нужный тебе XAUTHORITY.

kawaii_neko ★★★★
()
Ответ на: комментарий от torm7

Я ж тебе говорил, что нет «переменных юзера» и везде будут переменные конкретного процесса. И эта «systemctl show-environment» тоже показывает переменные какого-то процесса, несмотря на название команды.

firkax ★★★★★
()
Ответ на: комментарий от firkax

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

Тема простая, пользователю дали логин, пароль, ОТП. Он сложил это в менеджер паролей. Менеджер паролей это процесс, который запускается для каждого пользователя свой. OpenVPN это системный сервис, который должен дойти до пользователя получить из менеджера паролей данные и предоставитьт этому пользователю диалоговое окно, в случае необходимости. Но как выяснилось для диалога системный сервис должен не только пнуть команду, но и передать этой команде некоторые переменные окружения пользовательского процесса. Я кстати досих пор ещё не до конца понял какие. strace говорит, но нет однозначного сопоставления между environment и тем что попадает софту

torm7
() автор топика
Последнее исправление: torm7 (всего исправлений: 1)