Откажитесь от привилегий root для определенных операций в Python

В моем Python script я выполняю несколько операций, требующих привилегий root. Я также создаю и записываю файлы, которые я не хочу использовать исключительно от root, но от пользователя, который запускает мой script.

Обычно я запускаю свой script с помощью sudo. Есть ли способ сделать это?

Ответ 1

Вы можете переключаться между uid с помощью os.seteuid(). Это отличается от os.setuid() тем, что вы можете вернуться к привилегии root, когда они вам понадобятся.

Например, запустите в качестве пользователя root:

import os

open('file1', 'wc')

# switch to userid 501
os.seteuid(501)
open('file2', 'wc')

# switch back to root
os.seteuid(0)
open('file3', 'wc')

Это создает file1 и file3 как root, но file2 как пользователь с uid 501.

Если вы хотите определить, какой пользователь вызывает ваш script, sudo устанавливает две переменные среды:

SUDO_USER
SUDO_UID

Соответственно имя пользователя и uid пользователя, который вызвал sudo. Таким образом, вы можете использовать int(os.environ['SUDO_UID']) для использования с os.seteuid().

Ответ 2

http://linux.die.net/man/8/sudo quote:
Реальные и эффективные uid и gid настроены так, чтобы они соответствовали целевому пользователю

Итак, ваш единственный способ узнать, какой пользователь использовать, - это прочитать целевого пользователя либо из конфигурационного файла, либо из опции cmdline, либо каким-то образом из эвристического предположения.

Хорошей идеей является так называемое освобождение прав: Начните с привилегий root, затем сделайте то, за что вы их запустили. Затем стать менее привилегированным пользователем.

Для этого вы должны использовать модуль os: http://docs.python.org/2/library/os.html#os.setuid

Ответ 3

Я обнаружил, что использование os.seteuid и os.setegid фактически не отменяет привилегии root. После их вызова я все еще мог делать то, что требовало привилегий от root. Решение, которое я нашел, что работало, заключалось в том, чтобы вместо os.setresuid и os.setresgid:

sudo_uid = int(os.getenv("SUDO_UID"))
sudo_gid = int(os.getenv("SUDO_GID"))

# drop root privileges
os.setresgid(sudo_gid, sudo_gid, -1)
os.setresuid(sudo_uid, sudo_uid, -1)

subprocess.call("mkdir /foo1", shell = True) # should fail

# regain root privileges
os.setresgid(0, 0, -1)
os.setresuid(0, 0, -1)

subprocess.call("mkdir /foo2", shell = True) # should succeed