Python sudo что это
sudo 1.0.0
pip install sudo Copy PIP instructions
Released: Jun 2, 2020
Modular Python to execute any subprocess commands as another user(not necessarily superuser/root)
Navigation
Project links
Statistics
View statistics for this project via Libraries.io, or by using our public dataset on Google BigQuery
License: Mozilla Public License 2.0 (MPL 2.0)
Author: wesinator
Maintainers
Classifiers
Project description
python-sudo
Modular Python to execute any subprocess commands as another user (not necessarily superuser/root)
Usage:
This module does not take a user password for security and efficiency reasons (aiming for no user interaction to run).
Configure the sudoers file to allow running commands as another user (not necessarily the superuser):
sudo visudo :
Project details
Project links
Statistics
View statistics for this project via Libraries.io, or by using our public dataset on Google BigQuery
License: Mozilla Public License 2.0 (MPL 2.0)
Author: wesinator
Maintainers
Classifiers
Download files
Download the file for your platform. If you’re not sure which to choose, learn more about installing packages.
Использование sudo со скриптом Python
Имел эту же проблему.
Это произошло после того, как NuGet был использован для установки Ext.NET, у которого есть зависимость от Newtonsoft.JSON. Уже был файл Newtonsoft.JSON.dll в / bin (и, очевидно, ссылка на него в файле web.config), без проверки. Я начал процедуру установки пакета NuGet во время отладки (так что файл, вероятно, имел блокировку).
В окне ошибки времени выполнения он расскажет вам о трассировке стека, в какой части манифеста есть проблема, у меня была основная версия, поэтому я проверил версию пакета установки. и это была 1 основная версия. Найден исходный файл NuGet: «[fизический путь] /../ packages / Newtonsoft.Json. [Версия] / lib / [. Net version] /»
Оба манифеста и библиотека были там так скопированы
Надеюсь, это поможет
10 ответов
Пожалуйста, попробуйте модуль pexpect. Вот мой код:
Чтобы передать пароль в стандартный ввод sudo :
Примечание: вы, вероятно, могли бы сконфигурировать команду sudo или SUDO_ASKPASS без пароля вместо жесткого ввода пароля в исходном коде.
Скажите Попену, чтобы он читал stdin из PIPE.
Отправьте пароль на стандартную ТРУБУ процесса, используя его в качестве аргумента для передачи метода. Не забудьте добавить символ новой строки ‘\ n’ в конце пароля.
subprocess.Popen создает процесс и открывает трубы и прочее. То, что вы делаете:
Редактируйте /etc/sudoers для разрешите вашему пользователю использовать sudo без ввода пароля.
Все вышеперечисленное допускает привилегии root без пароля, ни одно из них не требует от вас жесткого пароля. Выберите любой подход, и я могу объяснить его более подробно.
Что касается , почему очень плохая идея жестко кодировать пароли, вот несколько хороших ссылок для дальнейшего чтения:
Не доверяйте SUDO, она может вас подвести
Всем доброго времени суток, в этой статье постараюсь описать некоторые способы обхода ограничений на исполнение команд в ОС Linux, советы по использованию которых можно часто встретить на различных форумах. Демонстрация будет проведена на примере задания Restricted shells с сайта Root-Me. Итак, начнём.
Пользователь ch14-1
Нас лишили возможности использовать ls, но мы можем отобразить содержимое любой директории используя echo:
Обычно, список бинарников разрешённых к запуску в rbash находится в так называемой домашней директории. В данном случае нам доступен vim, используя который мы можем выйти в нормальную оболочку. Запускаем vim и вводим команды:
Sudo разрешает нам запустить python, а учитывая его безграничные возможности это не совсем безопасно, и вот почему:
Вводим следующие команды:
Пользователь ch14-2
И попадаем на следующего пользователя, которому доступен архиватор tar.
Казалось бы, что в этом опасного? Однако tar, как и многие другие архиваторы, позволяет упаковывать и распаковывать файл сохраняя права доступа к нему. Создадим файл shell.c следующего содержания:
Компилируем и добавляем SUID бит:
Теперь распаковываем с сохранением прав используя sudo:
-rwsrwsrwx 1 app-script-ch14-3 app-script-ch14 7.2K Feb 14 22:39 shell
После запуска попадаем на следующий уровень:
Пользователь ch14-3
Снова проверяем sudo:
На этот раз уже лучше, по умолчанию, zip только упаковывает файлы, для распаковки нужен unzip, который мы запустить не можем, или можем?
Заглянув в man по zip‘у, находим там интересный параметр:
In cmd, <> is replaced by the name of the temporary archive, otherwise the name of the archive is appended to the end of the command. The return code is checked for success (0 on Unix)
Вот и ответ. Запускаем архивацию с последующим тестированием архива, а в качестве команды для проверки, указываем unzip, который распакует файл в текущую директорию, естественно с сохранением прав доступа:
Пользователь ch14-4
Смотрим, что ему доступно:
Ну тут всё просто, достаточно выполнить команду, описание которой можно легко найти в сети:
Пользователь ch14-5
Новый пользователь и новые ограничения:
GDB довольно мощный отладчик, и способов вызвать bash у него гораздо больше:
Первый это через встроенный Python:
Либо аналогично, как это делали с vim:
Пользователь ch14-6
Если вы думаете: «Что можно сделать через такой простой редактор как pico», то вероятно вы не знаете про его проверку орфографии, о которой кстати написано в man‘е. А сказано там следующее, что в качестве утилиты для проверки орфографии, мы можем указать всё что угодно. У нас уже есть отличный бинарник для запуска оболочки, нужно только придать ему соответствующие права. Для этого создадим файл spellbash.sh со следующим содержимым:
И запускаем pico, передав ему в качестве программы для проверки орфографии наш скрипт:
После успешной проверки орфографии и закрытия редактора, наш скрипт готов к запуску:
Пользователь ch14-7
-S program — Name of program to use for the encrypted connection. The program must understand ssh(1) options.
Ок, действия аналогичны прошлому уровню:
Пользователь ch14-8
Прямое исполнение команд оболочки. То что нам нужно, открываем man для любой команды, и вводим !/bin/bash:
Пользователь ch14-9
Так как прав выполнить подключение к внешнему серверу у нас нет, то нужен способ выполнить команду, ещё до установки соединения. И такая возможность есть, воспользуемся советом, описанным тут:
Получаем сообщение о том, что соединение сброшено, но это нем и не важно, ведь:
Пользователь ch14-10
Git так же предоставляет множество способов выполнить стороннюю команду, мы воспользуемся наиболее простым из них, который мы использовали с man:
Далее вводим !/bin/bash и попадаем на следующего пользователя:
Пользователь ch14-11
Вот мы и дошли до ещё одного распространённого совета, вместо vim использовать его ограниченную версию rvim и вот почему: Попробовав тот же способ, что использовался в самом начале для vim, получаем ошибку:
Но и тут есть лазейки… Просматривая список доступных команд, можно наткнуться на команды :python и :lua. Ограниченный от прямого исполнения команд rvim оказался не таким уж и безопасным.
Пользователь ch14-12
script запускает новую сессию, и полностью логирует всё в указанный файл, так что просто запускаем:
Пользователь ch14-13
Тут тоже ничего сложного, поэтому просто запускаем и снова попадаем в «начало»:
Пользователь ch14-14
На этот раз авторы учли ошибки, и убрали vim:
При выполнении команды, как можно догадаться появляется анимация локомотива и надпись
Посмотрим список команд, которые доступны:
Не густо, однако есть несколько способов получить содержимое файла .passwd, здесь будет только 1 из них, остальные оставлю вам на самостоятельный поиск. И так, просматривая help по каждой доступной команде, находим одну из них довольно интересной:
После недолгих поисков в сети примеров её использования, находим статью, которая как раз описывает способ чтения произвольного файла в переменную окружения, используя эту команду.
Воспользовавшись советом, выполняем:
И получаем искомый пароль.
Теперь, добавляя возможность запуска какой-либо программы в файл sudoers, не поленитесь и ознакомьтесь с полным её описанием, ведь возможно именно она станет основной дырой в безопасности.
Как установить Python и pip на Ubuntu
Пайтон — популярный язык программирования, который в большинстве дистрибутивов Linux установлен по умолчанию. У него есть несколько версий, которые имеют сильные различия между собой. Так что я расскажу, как установить различные версии Python и пакетного менеджера pip к нему в Ubuntu.
Проверка версии Python
По умолчанию минимальная установка Ubuntu уже включает в себя пакет Python. Посмотреть его версию можно с помощью пакетного менеджера.
Так же, если пакет установлен, то узнать версию Python можно через него самого.
В данном случае в ubuntu установлена версия 3.8.5. Обычно 3-я версия пайтона в системе именуется python3, а вторая просто python.
Кстати, а вы знаете, чем Ubuntu Server принципиально отличается от других Linux систем? Читайте мой обзор и сравнение — обзор ubuntu server и сравнение.
Установка Python
Может так быть, что в системе вообще не установлен python. Например, у каких-то провайдеров в их собственных кастомных образах. Они могут вырезать из них вообще все, что по их мнению там лишнее, чтобы уменьшить размер дистрибутива. В таком случае, установить python в ubuntu вам придется самостоятельно.
Рассмотрим сначала момент с установкой самой последней версии python. Сделать это проще всего с помощью пакетного менеджера apt:
Так вы установите самую свежую версию 3-го пайтона, которая присутствует в репозиториях дистрибутива. Чаще всего там будет достаточно свежая версия, так как данный язык программирования и среда исполнения очень распространены.
Установка из исходников
Если вам нужно что-то совсем свежее, то можно скомпилировать и установить python из исходников. Для этого идем на сайт python.org и переходим в раздел Downloads. Находим там самую свежую версию, скачиваем исходники и распаковываем.
Для установки python из исходников, нам понадобятся дополнительные системные пакеты. Устанавливаем их:
Теперь можно приступить к сборке:
Проверяем установленную из исходников версию:
Если у вас уже присутствуют другие версии пайтона в системе, то читайте ниже, как среди них выбрать ту, что будет использоваться по умолчанию.
Установка pip в Ubuntu
Вместе с python обычно используется пакетный менеджер для него. Давайте рассмотрим, как выглядит установка pip в Ubuntu. В зависимости от версии пайтона, устанавливается подходящая версия pip. Тут так же как и с самим интерпретатором версия пакета будет зависеть от версии самого языка. Если он 2-й версии, то ставится просто pip, если 3-й, то pip3.
Проверяем установленную версию pip:
Установленная версия pip соответствует присутствующей в системе версии python 3.8.
Установка пакетов python
Итак, pip мы установили, давайте теперь посмотрим, как с помощью этого пакетного менеджера устанавливать пакеты python. Никаких отличий от других пакетных менеджеров тут нет. Вот пример того, как устанавливается пакет pymysql для работы с базами данных mysql с помощью пайтона.
Посмотреть список установленных пакетов можно следующим образом:
А вот так вы можете узнать, какие файлы были установлены в систему, принадлежащие указанному пакету.
Удалить пакет с помощью pip можно следующим образом:
Вкратце по работе с pip все. Ничего сложного, все как обычно.
Обновить Python
Рассмотрим теперь тему с обновлением python в ubuntu. Тут может быть несколько вариантов.
Первый и третий варианты мы уже рассмотрели ранее. Обновление python до последней версии ничем не будет отличаться от чистой установки. В случае с пакетным менеджером apt, вам просто вместо install нужно будет указать upgrade.
Если в подключенных репозиториях ubuntu будет свежая версия python, то будет обновление до нее. Если нет, то ничего не произойдет. Останется текущая версия.
Обычное самые свежие версии python есть в отдельном репозитории deadsnakes. Подключим его:
А теперь попробуем поставить самую последнюю версию python из этого репозитория.
В итоге мы обновились до самой свежей версии python 3.9.1. При этом нам не пришлось ее собирать из исходников. Мы воспользовались установкой через пакетный менеджер, а значит нам будет проще обновляться в дальнейшем и поддерживать актуальную версию. Обновления будут приходить автоматически через apt.
Выбор по умолчанию
В описанных выше разделах мы установили как минимум 2 разные версии python3 — 3.8.5 и 3.9.1. Давайте теперь разберемся, какая их них будет выбираться по умолчанию.
В ubuntu указать дефолтную версию python, которая будет выбираться по умолчанию, можно с помощью команды update-alternatives. Вот как это выглядит:
Проверяем теперь дефолтную версию:
Так мы установили в системе по умолчанию версию python 3.8.5. А теперь изменим это на более свежую версию 3.9.1
В предложенном списке выбираем нужную нам версию пайтона, которая будет использоваться по умолчанию в нашей системе ubuntu.
Как запускать Python скрипты
С установкой и обновлением пайтона разобрались. Давайте теперь посмотрим, как нам запускать скрипты в системе. Ничего особенного для этого делать не надо. Достаточно указать бинарник интерпретатора и сам скрипт. Примерно так выглядит запуск python скрипта в ubuntu:
Скрипт будет запущен дефолтной версией пайтона. Если нужно запустить в какой-то конкретной версии, то делается это так:
Так же скрипты пайтона можно запускать напрямую в консоли. Для этого в самом начале скрипта нужно объявить окружение.
После этого достаточно сделать файл исполняемым и запустить прямо в консоли.
Если вы хотите запускать скрипт как службу, то вам придется добавить юнит в systemd. Делается это следующим образом. Создаем файл /lib/systemd/system/python.service :
После этого перечитываем конфигурацию systemd и запускаем скрипт на пайтоне как службу:
Так как мой скрипт не предполагает работу в режиме службы, то после выполнения он был завершен. Если же у вас там запрограммирована непрерывная работа, то он будет работать как служба через systemd.
Как удалить Python в Ubuntu
Если вам по какой-то причине необходимо удалить python с сервера ubuntu, то сделать это можно штатным образом через пакетный менеджер apt. Для того, чтобы узнать версию пакетов для удаления, можно вывести их список.
После этого, подставляя версию нужного пакета, удалить его:
Только будьте внимательны при удалении python из системы. Он очень много кем используется. При его удалении будет предложено удалить и все его зависимости. А это внушительный список пакетов, которые без пайтона не смогут работать.
К примеру, без пайтона не сможет работать netplan, с помощью которого настраивается сеть. Так что аккуратнее с удалением питона из системы.
Запуск Python в Docker
Ну и в завершении статьи про Python в Ubuntu, покажу, как можно еще его запускать без локальной установки непосредственно в саму систему. Вы можете запустить питона в докере. Для этого просто выберите необходимую вам версию Python и запустите Docker контейнер с ней.
В данном случае я быстро запустил свой скрипт в версии 3, используя контейнер python:3. Если мне то же самое нужно сделать во 2-й версии, то я просто использую другой контейнер.
Таким образом я могу запускать свой скрипт на любой версии python без необходимости его локальной установки. В приведенном примере контейнер будет автоматически остановлен и удален после выполнения скрипта. За это отвечает параметр —rm, который я указал.
Sudo Python Plugin API
sudo_plugin_python — Sudo Plugin API (Python)
DESCRIPTION
Starting with version 1.9, sudo plugins can be written in python. The API closely follows the C sudo plugin API described by sudo_plugin(5).
The supported plugins types are:
Python plugin support needs to be explicitly enabled at build time with the configure option “—enable-python”. Python version 3.0 or higher is required.
Sudo Python Plugin Base
A plugin written in Python should be a class in a python file that inherits from sudo.Plugin. The sudo.Plugin base class has no real purpose other than to identify this class as a plugin.
The only implemented method is a constructor, which stores the keyword arguments it receives as fields (member variables) in the object. This is intended as a convenience to allow you to avoid writing the constructor yourself.
Both the constructor and destructor are optional and can be omitted.
The customized Plugin class should define a few plugin-specific methods. When the plugin loads, sudo will create an instance of this class and call the methods. The actual methods required depent on the type of the plugin, but most return an “int” result code, as documented in sudo_plugin(@mansctsu@), that indicates whether or not the method was successful. The Python sudo module defines the following constants to improve readability:
Define | Value |
sudo.RC.OK | 1 |
sudo.RC.ACCEPT | 1 |
sudo.RC.REJECT | 0 |
sudo.RC.ERROR | -1 |
sudo.RC.USAGE_ERROR | -2 |
Instead of just returning sudo.RC.ERROR or sudo.RC.REJECT result code the plugin can also provide a message describing the problem. This can be done by raising one of the special exceptions:
This added message will be used by the audit plugins. Both exceptions inherit from sudo.PluginException
Python Plugin Loader
Example group provider plugin usage in the sudoers file:
The plugin arguments are as follows:
ModulePath The path of a python file which contains the class of the sudo Python plugin. It must be either an absolute path or a path relative to the sudo Python plugin directory: «/usr/local/libexec/sudo/python». ClassName (Optional.) The name of the class implementing the sudo Python plugin. If not supplied, the one and only sudo.Plugin that is present in the module will be used. If there are multiple such plugins in the module (or none), it will result in an error.
Policy plugin API
Policy plugins must be registered in sudo.conf(5). For example:
Currently, only a single policy plugin may be specified in sudo.conf(5).
A policy plugin may have the following member functions:
Implementing this function is optional. The default constructor will set the keyword arguments it receives as member variables in the object.
The constructor matches the open () function in the C sudo plugin API.
The function arguments are as follows:
user_env The user’s environment as a tuple of strings in “key=value” format. settings A tuple of user-supplied sudo settings in the form of “key=value” strings. version The version of the Python Policy Plugin API. user_info A tuple of information about the user running the command in the form of “key=value” strings. plugin_options The plugin options passed as arguments in the sudo.conf(5) plugin registration. This is a tuple of strings, usually (but not necessarily) in “key=value” format.
The sudo.options_as_dict () convenience function can be used to convert “key=value” pairs to a dictionary. For a list of recognized keys and their supported values, see the policy plugin open () documentation in sudo_plugin(5).
The check_policy () function is called by sudo to determine whether the user is allowed to run the specified command. Implementing this function is mandatory for a policy plugin.
The function arguments are as follows:
argv A tuple describing the command the user wishes to run. env_add Additional environment variables specified by the user on the command line in the form of a tuple of “key=value” pairs. The sudo.options_as_dict () convenience function can be used to convert them to a dictionary.
This function should return a result code or a tuple in the following format:
The tuple values are as follows:
rc The result of the policy check, one of the sudo.RC.* constants. sudo.RC.ACCEPT if the command is allowed, sudo.RC.REJECT if not allowed, sudo.RC.ERROR for a general error, or sudo.RC.USAGE_ERROR for a usage error. command_info_out Optional (only required when the command is accepted). Information about the command being run in the form of “key=value” strings.
To accept a command, at the very minimum the plugin must set in the command, runas_uid and runas_gid keys.
For a list of recognized keys and supported values, see the check_policy () documentation in sudo_plugin(5).
argv_out Optional (only required when the command is accepted). The arguments to pass to the execve(2) system call when executing the command. user_env_out Optional (only required when the command is accepted). The environment to use when executing the command in the form of a tuple of strings in “key=value” format. init_session
Perform session setup (optional). The init_session () function is called before sudo sets up the execution environment for the command before any uid or gid changes.
The function arguments are as follows:
user_pwd A tuple describing the user’s passwd entry. Convertible to pwd.struct_passwd or None if the user is not present in the password database.
This function should return a result code or a tuple in the following format:
The tuple values are as follows:
List available privileges for the invoking user.
The function arguments are as follows:
argv If not set to None, an argument vector describing a command the user wishes to check against the policy. is_verbose Flag indicating whether to list in verbose mode or not. user The name of a different user to list privileges for if the policy allows it. If None, the plugin should list the privileges of the invoking user. validate
For policy plugins that cache authentication credentials, this function is used to validate and cache the credentials (optional).
For policy plugins that cache authentication credentials, this function is used to invalidate the credentials (optional).
The function arguments are as follows:
remove If this flag is set, the plugin may remove the credentials instead of simply invalidating them. show_version
Display the plugin version information to the user. The sudo.log_info () function should be used.
The function arguments are as follows:
Called when a command finishes executing.
Works the same as the close () function in the C sudo plugin API, except that it only gets called if sudo attempts to execute the command.
The function arguments are as follows:
Policy plugin example
Sudo ships with an example Python policy plugin. To try it, register it by adding the following lines to /etc/sudo.conf :
Be aware, however, that you cannot enable the Python policy plugin in addition to another policy plugin, such as sudoers(5).
I/O plugin API
I/O plugins must be registered in sudo.conf(5). For example:
Sudo supports loading multiple I/O plugins. Currently only 8 python I/O plugins can be loaded at once.
An I/O plugin may have the following member functions:
Implementing this function is optional. The default constructor will set the keyword arguments it receives as member variables in the object.
The constructor matches the open () function in the C sudo plugin API.
The function arguments are as follows:
user_env The user’s environment as a tuple of strings in “key=value” format. settings A tuple of user-supplied sudo settings in the form of “key=value” strings. version The version of the Python I/O Plugin API. user_info A tuple of information about the user running the command in the form of “key=value” strings. plugin_options The plugin options passed as arguments in the sudo.conf(5) plugin registration. This is a tuple of strings, usually (but not necessarily) in “key=value” format.
The sudo.options_as_dict () convenience function can be used to convert “key=value” pairs to a dictionary. For a list of recognized keys and their supported values, see the I/O plugin open () documentation in sudo_plugin(5).
Receives the command the user wishes to run.
Works the same as the open () function in the C sudo plugin API except that:
The function arguments are as follows:
argv A tuple of the arguments describing the command the user wishes to run. command_info Information about the command being run in the form of “key=value” strings.
The sudo.options_as_dict () convenience function can be used to convert “key=value” pairs to a dictionary. For a list of recognized keys and their supported values, see the I/O plugin open () documentation in sudo_plugin(5).
Receive the user input or output of the terminal device and application standard input / output / error. See the matching calls in sudo_plugin(5).
The function arguments are as follows:
buf The input (or output) buffer in the form of a string.
The function should return a result code, one of the sudo.RC.* constants.
If sudo.RC.ERROR is returned, the running command will be terminated and all of the plugin’s logging functions will be disabled. Other I/O logging plugins will still receive any remaining input or output that has not yet been processed.
Called whenever the window size of the terminal changes. The function arguments are as follows:
line The number of lines of the terminal. cols The number of columns of the terminal. log_suspend
The function arguments are as follows:
signo The number of the signal that caused the command to be suspended or SIGCONT if the command was resumed. show_version
The function arguments are as follows:
Works the same as the close () function in the C sudo plugin API, except that it only gets called if sudo attempts to execute the command.
The function arguments are as follows:
I/O plugin example
Sudo ships a Python I/O plugin example. To try it, register it by adding the following lines to /etc/sudo.conf :
Audit plugin API
Audit plugins must be registered in sudo.conf(5). For example:
Sudo supports loading multiple audit plugins. Currently only 8 python audit plugins can be loaded at once.
An audit plugin may have the following member functions (all of them are optional):
The default constructor will set the keyword arguments it receives as member variables in the object.
The constructor matches the open () function in the C sudo plugin API.
The function arguments are as follows:
user_env The user’s environment as a tuple of strings in “key=value” format. settings A tuple of user-supplied sudo settings in the form of “key=value” strings. version The version of the Python Audit Plugin API. user_info A tuple of information about the user running the command in the form of “key=value” strings. plugin_options The plugin options passed as arguments in the sudo.conf(5) plugin registration. This is a tuple of strings, usually (but not necessarily) in “key=value” format. open
The function arguments are as follows:
submit_optind The index into submit_argv that corresponds to the first entry that is not a command line option. submit_argv The argument vector sudo was invoked with, including all command line options. close
Called when sudo is finished, shortly before it exits.
The function arguments are as follows:
Display the plugin version information to the user. The sudo.log_info () function should be used.
The function arguments are as follows:
This function is called when a command or action is accepted by the policy plugin. The function arguments are as follows:
This function is called when a command or action is rejected by the policy plugin. The function arguments are as follows:
This function is called when a plugin returns an error. The function arguments are as follows:
plugin_name The name of the plugin that accepted the command. plugin_type The type of plugin that accepted the command, currently sudo.PLUGIN_TYPE.POLICY or sudo.PLUGIN_TYPE.IO audit_msg An optional string describing the plugin error. If the plugin did not provide a description, it will be None command_info A vector of information describing the command. See the sudo_plugin(5) manual for possible values.
Audit plugin example
Sudo ships a Python Audit plugin example. To try it, register it by adding the following lines to /etc/sudo.conf :
It will log the plugin accept / reject / error results to the output.
Approval plugin API
Approval plugins must be registered in sudo.conf(5). For example:
Sudo supports loading multiple approval plugins. Currently only 8 python approval plugins can be loaded at once.
An approval plugin may have the following member functions:
Optional. The default constructor will set the keyword arguments it receives as member variables in the object.
The constructor matches the open () function in the C sudo plugin API.
The function arguments are as follows:
user_env The user’s environment as a tuple of strings in “key=value” format. settings A tuple of user-supplied sudo settings in the form of “key=value” strings. version The version of the Python Approval Plugin API. user_info A tuple of information about the user running the command in the form of “key=value” strings. plugin_options The plugin options passed as arguments in the sudo.conf(5) plugin registration. This is a tuple of strings, usually (but not necessarily) in “key=value” format. submit_optind The index into submit_argv that corresponds to the first entry that is not a command line option. submit_argv The argument vector sudo was invoked with, including all command line options. show_version
Display the version. (Same as for all the other plugins.)
This function is called after policy plugin’s check_policy has succeeded. It can reject execution of the command by returning sudo.RC.REJECT or raising the special exception:
with the message describing the problem. In the latter case, the audit plugins will get the description.
The function arguments are as follows:
command_info A vector of information describing the command that will run. See the sudo_plugin(5) manual for possible values. run_argv Argument vector describing a command that will be run. run_env The environment the command will be run with.
Approval plugin example
Sudo ships a Python Approval plugin example. To try it, register it by adding the following lines to /etc/sudo.conf :
It will only allow execution of commands in the «business hours» (from Monday to Friday between 8:00 and 17:59:59).
Sudoers group provider plugin API
A group provider plugin is registered in the sudoers(5) file. For example:
Currently, only a single group plugin can be registered in sudoers.
A group provider plugin may have the following member functions:
Implementing this function is optional. The default constructor will set the keyword arguments it receives as member variables in the object.
The function arguments are as follows:
args The plugin options passed as arguments in the sudoers file plugin registration. All the arguments are free form strings (not necessarily in “key=value” format). version The version of the Python Group Plugin API. query
The function arguments are as follows:
Group plugin example
Sudo ships a Python group plugin example. To try it, register it in the sudoers file by adding the following lines:
The example plugin will tell sudo that the user test is part of the non-unix group mygroup. If you add a rule that uses this group, it will affect the test user. For example:
Will allow user test to run sudo without a password.
Hook function API
The hook function API is currently not supported for plugins written in Python.
Conversation API
A Python plugin can interact with the user using the sudo.conv () function which displays one or more messages described by the sudo.ConvMessage class. This is the Python equivalent of the conversation () function in the C sudo plugin API. A plugin should not attempt to read directly from the standard input or the user’s tty (neither of which are guaranteed to exist).
The sudo.ConvMessage class specifies how the user interaction should occur:
sudo.ConvMessage member variables:
msg_type Specifies the type of the conversation. See the sudo.CONV.* constants below. msg The message to display to the user. The caller must include a trailing newline in msg if one is to be displayed. timeout Optional. The maximum amount of time for the conversation in seconds. If the timeout is exceeded, the sudo.conv () function will raise a sudo.ConversationInterrupted exception. The default is to wait forever (no timeout).
To specify the message type, the following constants are available:
See the sudo_plugin(5) manual for a description of the message types.
The sudo.conv () function performs the actual user interaction:
The function arguments are as follows:
message(s) One of more messages (of type sudo.ConvMessage), each describing a conversation. At least one message is required. on_suspend An optional callback function which gets called if the conversation is suspended, for example by the user pressing control-Z. The specified function must take a single argument which will be filled with the number of the signal that caused the process to be suspended. on_resume An optional callback function which gets called when the previously suspended conversation is resumed. The specified function must take a single argument which will be filled with the number of the signal that caused the process to be suspended.
The sudo.conv () function can raise the following exceptions:
sudo.SudoException If the conversation fails, for example when the conversation function is not available. sudo.ConversationInterrupted If the conversation function returns an error, e.g., the timeout passed or the user interrupted the conversation by pressing control-C.
Conversation example
Sudo ships with an example plugin demonstrating the Python conversation API. To try it, register it by adding the following lines to /etc/sudo.conf :
Information / error display API
To display information to the user, the sudo.log_info () function can be used. To display error messages, use sudo.log_error (). The syntax is similar to the Python print () function.
The function arguments are as follows:
string(s) One or more strings to display. sep An optional string which will be used as the separator between the specified strings. The default is a space character, (‘ ’). end An optional string which will be displayed at the end of the message. The default is a new line character (‘\n’).
Debug API
Debug messages are not visible to the user and are only logged debugging is explicitly enabled in sudo.conf(5). Python plugins can use the sudo.debug () function to make use of sudo ‘s debug system.
The debug options are in the form of multiple “subsystem@level” strings, separated by commas (‘,’). For example to just see the debug output of sudo.debug () calls, use:
See sudo_conf(5) for more details.
The most interesting subsystems for Python plugin development are:
plugin Logs each sudo.debug () API call. py_calls Logs whenever a C function calls into the python module. For example, calling the __init__ () function. c_calls Logs whenever python calls into a C sudo API function. internal Logs internal functions of the python language wrapper plugin. sudo_cb Logs when sudo calls into the python plugin API. load Logs python plugin loading / unloading events.
You can also specify “all” as the subsystem name to log debug messages for all subsystems.
The sudo.debug () function is defined as:
The function arguments are as follows:
level an integer, use one of the log level constants below message(s) one or more messages to log
sudo.conf name | Python constant | description |
crit | sudo.DEBUG.CRIT | only critical messages |
err | sudo.DEBUG.ERROR | |
warn | sudo.DEBUG.WARN | |
notice | sudo.DEBUG.NOTICE | |
diag | sudo.DEBUG.DIAG | |
info | sudo.DEBUG.INFO | |
trace | sudo.DEBUG.TRACE | |
debug | sudo.DEBUG.DEBUG | very extreme verbose debugging |
Alternatively, a plugin can use the built in logging module of Python as well. Sudo adds its log handler to the root logger, so by default all output of a logger will get forwarded to sudo log system, as it would call sudo.debug.
The log handler of sudo will map each Python log level of a message to the appropriate sudo debug level. Note however, that sudo debug system will only get the messages not filtered out by the Python loggers. For example, the log level of the python logger will be an additional filter for the log messages, and is usually very different from what level is set in sudo.conf for the sudo debug system.
Debug example
Sudo ships an example debug plugin by default. To try it, register it by adding the following lines to /etc/sudo.conf :
Option conversion API
The Python plugin API includes two convenience functions to convert options in “key=value” format to a dictionary and vice versa.
The function arguments are as follows:
options An iterable (tuple, list, etc.) of strings, each in “key=value” format. This is how the plugin API passes options and settings to a Python plugin.
The function returns the resulting dictionary. Each string of the passed in options will be split at the first equal sign (‘=’) into a key and value. Dictionary keys will never contain this symbol (but values may).
The function arguments are as follows:
options_dict A dictionary where both the key and the value are strings. Note that the key should not contain an equal sign (‘=’), otherwise the resulting string will have a different meaning. However, this is not currently enforced.
The function returns a tuple containing the strings in “key=value” form for each key and value in the options_dict dictionary passed in. This is how the plugin API accepts options and settings.
PLUGIN API CHANGELOG (Python)
LIMITATIONS
Only a maximum number of 8 python I/O plugins can be loaded at once. If /etc/sudo.conf contains more, those will be rejected with a warning message.
The Event API and the hook function API is currently not accessible for Python plugins.
SEE ALSO
AUTHORS
Many people have worked on sudo over the years; this version consists of code written primarily by:
Python plugin support is currently considered experimental.
SECURITY CONSIDERATIONS
All Python plugin handling is implemented inside the python_plugin.so dynamic plugin. Therefore, if no Python plugin is registered in sudo.conf(5) or the sudoers file, sudo will not load the Python interpreter or the Python libraries.
By default, a Python plugin can only import Python modules which are owned by root and are only writable by the owner. The reason for this is to prevent a file getting imported accidentally which is modifiable by a non-root user. As sudo plugins run as root, accidentally importing such file would make it possible for any user (having write access) to execute any code with administrative rights.
However, during development of a plugin this might not be very convenient. The sudo.conf(5) developer_mode option can be used to disable it. For example:
Please note that this creates a security risk, so it is not recommended on critical systems such as a desktop machine for daily use, but is intended to be used in development environments (VM, container, etc). Before enabling developer mode, ensure you understand the implications.