Вопрос или проблема
У меня есть bash-скрипт, который выполняет вход в мою Bitwarden-экземпляр с помощью CLI bw
следующим образом:
test.sh:
#!/usr/bin/sh
set -e -o pipefail
bw logout --quiet || true
BW_CLIENTID=$(cat ./credentials.json | jq -r '.client_id') \
BW_CLIENTSECRET=$(cat ./credentials.json | jq -r '.client_secret') \
bw login --apikey
Файл ./credentials.json
имеет следующие права:
-rw-r--r-- 1 root root 169 Jun 10 2023 credentials.json
Запуск этого скрипта от имени обычного пользователя работает нормально, но иногда мне нужно запускать его от имени root. Я заметил, что на некоторых системах команда bw
не читает встроенные переменные окружения правильно при запуске только с sudo
, она работает только с sudo -E
, так что:
./test.sh # всегда работает
sudo ./test.sh # работает на некоторых машинах, но не на всех
sudo -E ./test.sh # всегда работает
Когда работает, я получаю вывод:
You are logged in!
А когда не работает, я получаю:
client_id or client_secret is incorrect. Try again.
Я говорю “правильно”, потому что, похоже, он каким-то образом читает переменные, потому что если я удалю одну из переменных окружения, например:
BW_CLIENTID=$(cat /mnt/keys/vaultwarden.json | jq -r '.client_id') \
bw login --apikey
Меня вместо этого попросят ввести секрет клиента (или client id, если я удалю BW_CLIENTID
). Так что по какой-то причине значения в переменных окружения не читаются правильно без опции -E
, но они, похоже, там есть.
Я пытался создать тест с помощью общего скрипта следующим образом:
foo.sh:
#!/usr/bin/sh
set -e
FOO=$(cat ./data.json | jq -r '.my_prop') \
BAR=$(cat ./data.json | jq -r '.other_prop') \
./bar.sh
bar.sh:
#!/usr/bin/sh
set -e
echo "foo: '$FOO'"
echo "bar: '$BAR'"
Но запуск любого из них на любой из моих систем работает, все они выдают ожидаемый вывод (содержимое my_prop
и other_prop
в data.json
), и я не вижу разницы между напечатанным значением для любого варианта:
./foo.sh
sudo ./foo.sh
sudo -E ./foo.sh
Я тестировал на нескольких системах, это смесь систем Ubuntu и Arch, пока без -E
он не работает на всех системах Ubuntu и некоторых Arch, и работает без -E
только на одной Arch системе.
Мои главные вопросы: есть ли способ настроить sudo
на всегда запускаться с -E
или что-то подобное? И есть ли разница в форматировании при использовании опции -E
? (учетные данные могут содержать странные символы, но я не понимаю, почему опция -E
должна делать разницу)
Я видел, что файл /etc/sudoers
позволяет делать что-то вроде:
Defaults env_keep += "HOME"
Но все такие строки закомментированы во всех файлах /etc/sudoers
(на всех системах, включая работающую), и там нет дополнительных файлов в /etc/sudoers.d/
. Я также пробовал добавлять BW_CLIENTID
и BW_CLIENTSECRET
таким образом, но это не имело эффекта:
Defaults env_keep += "BW_CLIENTID"
Defaults env_keep += "BW_CLIENTSECRETS
Но могут быть другие места или настройки?
Примечание: я предполагаю, что это может быть просто какой-то нюанс CLI
bw
, из-за которого он не может правильно улавливать переменные окружения на некоторых системах без-E
, но мне хотелось бы знать, есть ли настройки, которые я мог бы начать исследовать на своих собственных системах. Тем не менее, я был бы заинтересован в любых подсказках по этому поводу.
Ответ или решение
Существует проблема, связанная с управлением переменными окружения при выполнении команд с помощью sudo
в Linux-системах, которая может варьироваться от системы к системе. В данном контексте эту проблему можно рассмотреть в три этапа: теоретическое объяснение, практический пример и применение полученных знаний.
Теоретическая часть
Сначала необходимо понять, как работает sudo
. Команда sudo
используется для выполнения команд от имени другого пользователя, обычно суперпользователя (root). По умолчанию sudo
сбрасывает большинство переменных окружения для повышения безопасности, пропуская только минимально необходимые для корректного исполнения команд. Однако, с помощью опции -E
можно сохранить текущие переменные окружения и передать их в команду, выполняемую под sudo
.
Это различие часто становится причиной проблем в скриптах, где используется передача безопасных данных через переменные окружения. В зависимости от конфигурации системы или специфик исполнения, sudo
может не передать некоторые или все переменные в урок-скрипт при отсутствующем -E
.
Пример
Рассмотрим предоставленный сценарий. Имеется bash-скрипт, который использует bw
CLI для входа в Bitwarden, где переменные окружения BW_CLIENTID
и BW_CLIENTSECRET
определяются inline. В обычном режиме скрипт выполняется корректно, однако при запуске с sudo
без -E
на некоторых системах возникают ошибки аутентификации.
Для сравнения, другой набор скриптов, foo.sh
и bar.sh
, работающие с другими JSON-данными, всегда выполняются корректно. Это различие может быть связано с обработкой bw
CLI переменных окружения или с особенностями выполнения sudo
на разных системах.
Практическое применение
Для достижения стабильного результата, важно понимать и управлять переменными окружения в контексте sudo
. В данном случае, sudo -E ./test.sh
всегда срабатывает, так как переменные окружения в неизменном виде передаются скрипту. Чтобы навсегда решить проблему, можно предпринять несколько шагов:
-
Изменение логики скрипта: Использовать опцию
-E
в командеsudo
всегда, когда требуется передать переменные окружения. -
Настройка
sudoers
: Можно модифицировать файл/etc/sudoers
для сохранения определенных переменных окружения при использованииsudo
. Добавление строкиDefaults env_keep += "BW_CLIENTID BW_CLIENTSECRET"
будет полезным шагом для автоматической передачи этих переменных. -
Альтернативные методы передачи: Применение конфигурационных файлов или других механизмов передачи чувствительных данных может уменьшить зависимость от переменных окружения.
Важно помнить, что поведение sudo
может зависеть от множества настроек и конфигураций, включая отличия между версиями дистрибутивов Linux и особенностями конфигурации конкретных систем. В случаях, аналогичных описанным, рекомендуется тщательно проверять конфигурацию системы и, при необходимости, проконсультироваться с документацией и техническими ресурсами.
Надеюсь, предоставленная информация будет полезной для эффективного решения данной проблемы и позволит избежать лишних проблем в будущем при управлении и передаче переменных окружения в скриптах.