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

У меня есть сценарий Python, который будет делать много вещей, которые потребовали бы, чтобы полномочия корневого уровня, такие как движущиеся файлы в / и т.д., устанавливая с Кв. - добрались и так далее. Я в настоящее время имею:

if os.geteuid() != 0:
    exit("You need to have root privileges to run this script.\nPlease try again, this time using 'sudo'. Exiting.")

Действительно ли это - лучший способ сделать проверку? Есть ли другие лучшие практики?

64
задан martineau 7 January 2018 в 22:53
поделиться

5 ответов

По принципу "Легче попросить прощения, чем разрешения":

try:
    os.rename('/etc/foo', '/etc/bar')
except IOError as e:
    if (e[0] == errno.EPERM):
       print >> sys.stderr, "You need root permissions to do this, laterz!"
       sys.exit(1)

Если вы обеспокоены непортируемостью os.geteuid(), вам, вероятно, не стоит копаться в /etc.

27
ответ дан 24 November 2019 в 15:52
поделиться

Если вы действительно хотите, чтобы ваш код был надежным в широком разнообразии конфигураций Linux, я бы предложил вам рассмотреть угловые случаи, когда кто-то может использовать SELinux, или ACL файловой системы, или функции "capabilities", которые были в ядре Linux начиная с версии 2.2 или около того. Ваш процесс может быть запущен под какой-то оберткой, использующей SELinux или какую-то библиотеку возможностей Linux, например libcap2 libcap-ng, или fscaps или elfcap через что-то более экзотическое, например, замечательную и, к сожалению, недооцененную systrace систему Нильса Провоса.

Все это способы, с помощью которых ваш код может быть запущен от имени не root, но при этом вашему процессу может быть делегирован необходимый доступ для выполнения работы без EUID==0.

Поэтому я предлагаю вам подумать о том, чтобы писать свой код более по-питоновски, оборачивая операции, которые могут не сработать из-за прав доступа или других проблем, кодом обработки исключений. Если для выполнения различных операций вы выходите из системы (например, используя модуль subprocess), вы можете предложить префикс всех таких вызовов с sudo (например, в качестве опции командной строки, окружения или файла .rc). При интерактивном запуске вы можете предложить повторно выполнять любые команды, которые вызывают исключения, связанные с правами доступа, используя sudo (как вариант, только если вы найдете sudo в os.environ['PATH']).

В целом, это правда, что в большинстве систем Linux и UNIX администрирование по-прежнему осуществляется привилегированным пользователем "root". Однако это старая школа, и мы, как программисты, должны стараться поддерживать более новые модели. Попробовать свои операции и позволить обработке исключений сделать свою работу позволяет вашему коду работать под любой системой, которая прозрачно разрешает нужные вам операции, а знание и готовность использовать sudo является приятным штрихом (поскольку это, безусловно, самый распространенный инструмент для контролируемого делегирования системных привилегий).

7
ответ дан 24 November 2019 в 15:52
поделиться

Все зависит от того, насколько портативным должно быть ваше приложение. Если вы имеете в виду бизнес, мы должны предположить, что учетная запись администратора не всегда равна 0. Это означает, что проверки на euid 0 недостаточно. Проблема в том, что бывают ситуации, когда одна команда будет вести себя так, как если бы вы были пользователем root, а следующая завершилась ошибкой с отказом в разрешении (подумайте о SELinux и др.). Поэтому действительно лучше корректно завершать работу и проверять EPERM errno всякий раз, когда это уместно.

0
ответ дан 24 November 2019 в 15:52
поделиться

os.geteuid получает эффективный идентификатор пользователя, который вам нужен. , поэтому я не могу придумать лучшего способа выполнить такую ​​проверку. Единственное, что остается неуверенным, - это то, что в заголовке "root-like": ваш код проверяет наличие ровно root , нет в нем "нравится", и я действительно не знаю, что "root- вроде, но не root "будет означать - так что, если вы имеете в виду что-то отличное от" точно root ", возможно, вы сможете уточнить, спасибо!

63
ответ дан 24 November 2019 в 15:52
поделиться

Ответ на вторую часть вопроса

(извините, что поле для комментариев слишком маленькое)

Пол Хоффман, вы правы, я затронул только одну часть вашего вопроса, касающуюся интринсиков, но это не был бы достойный скриптовый язык, если бы он не мог работать с apt-get. Предпочтительная библиотека немного многословна, но она делает свою работу:

>>> apt_get = ['/usr/bin/apt-get', 'install', 'python']
>>> p = subprocess.Popen(apt_get, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> p.wait()
100                 # Houston, we have a problem.
>>> p.stderr.read()
'E: Could not open lock file /var/lib/dpkg/lock - open (13: Permission denied)'
'E: Unable to lock the administration directory (/var/lib/dpkg/), are you root?\n'

Но Popen является обобщенным инструментом и может быть обернута для удобства:

$ cat apt.py
import errno
import subprocess

def get_install(package):
    cmd = '/usr/bin/apt-get install'.split()
    cmd.append(package)
    output_kw = {'stdout': subprocess.PIPE, 'stderr': subprocess.PIPE}
    p = subprocess.Popen(cmd, **output_kw)
    status = p.wait()
    error = p.stderr.read().lower()
    if status and 'permission denied' in error:
        raise OSError(errno.EACCES, 'Permission denied running apt-get')
    # other conditions here as you require
$ python
>>> import apt
>>> apt.get_install('python')
Traceback ...
OSError: [Errno 13] Permission denied running apt-get

И теперь мы вернулись к обработке исключений. Я откажусь комментировать Java-подобную чрезмерную универсальность модуля подпроцесса.

3
ответ дан 24 November 2019 в 15:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: