Разработка модулей control(8): различия между версиями
м (→Вкратце: текущий размер (опечатка была?)) |
|||
(не показано 10 промежуточных версий 4 участников) | |||
Строка 1: | Строка 1: | ||
[[Category:Devel]] | [[Category:Devel]] | ||
[[Категория:Безопасность]] | |||
== control(8) == | == control(8) == | ||
<tt>control(8)</tt> — фреймворк, написанный на обычном shell и позволяющий фиксировать и анализировать состояние системных объектов — например, бинарников и файлов конфигурации (например, привилегированных утилит вроде <tt>su(8)</tt>). С его помощью получается удобным способом вносить переживающие обновление пакета или просто сложные изменения «одним росчерком»; для администраторского ознакомления рекомендуются <tt>control(8)</tt>, <tt>control-dump(8)</tt> и <tt>control-restore(8)</tt>. | |||
<tt> | |||
=== Примеры для пользователя === | === Примеры для пользователя === | ||
Строка 24: | Строка 23: | ||
=== Вкратце === | === Вкратце === | ||
В библиотеку функций <tt>/etc/control.d/functions</tt> (размером | В библиотеку функций <tt>/etc/control.d/functions</tt> (размером 3747 ''байт'' на сейчас) входят используемые в <tt>/etc/control.d/facilities/*</tt> удобства: | ||
* | * new_fmode — конструктор «рулилки правами»; | ||
* | * new_subst — конструктор «рулилки конфигом»; | ||
* | * new_help — добавление человекопонимаемого комментария к режиму; | ||
* | * new_summary — добавление человекопонимаемого комментария ко всему control-файлу. | ||
Следует понимать, что объекты получаются двунаправленные: работает как направление ''режим=>права'', так и обратное ему ''права=>режим''; как ''режим=>конфиг'', так и ''конфиг=>режим''. | Следует понимать, что объекты получаются двунаправленные: работает как направление ''режим=>права'', так и обратное ему ''права=>режим''; как ''режим=>конфиг'', так и ''конфиг=>режим''. Таким образом возможно не только задавать, но и проверять права, что особенно важно при обновлении пакетов — перед удалением предыдущей версии пакетными скриптами делается <tt>control-dump</tt>, а после разворачивания новой — <tt>control-restore</tt>. При этом для избежания промежутков времени с понижением защищённости (если речь о регулировании прав на SUID/SGID binaries, например) в пакете следует задавать предельно жёсткую конфигурацию, которую возможно ослабить уже средствами <tt>control</tt> в %post. | ||
''Кстати о | ''Кстати о пакетах — примеры можно посмотреть в альтовских <tt>su</tt>, <tt>ping</tt>, <tt>mtr</tt>, <tt>samba</tt>… проще заглянуть в спеки, хотя если кто допишет, тоже спасибо'' | ||
=== new_fmode(''name'', ''perms'', ''user'', ''group'') === | === new_fmode(''name'', ''perms'', ''user'', ''group'') === | ||
Для обеспечения двунаправленности ничего особенного не требуется, поэтому аргументы не нуждаются в особых | Для обеспечения двунаправленности ничего особенного не требуется, поэтому аргументы не нуждаются в особых разъяснениях — приведём пример: | ||
<pre>new_fmode restricted 700 root root</pre> | <pre>new_fmode restricted 700 root root</pre> | ||
зарегистрирует режим по имени | зарегистрирует режим по имени «restricted», характеризующийся правами <tt>0700 (-rwx------) root:root</tt>. На что — решается отдельно. | ||
=== new_subst(''name'', ''test'', ''set'') === | === new_subst(''name'', ''test'', ''set'') === | ||
Вот с модификацией текстовых файлов | Вот с модификацией текстовых файлов сложнее — из аргумента, являющегося параметром для <tt>subst(1)</tt> (<tt>sed(1)</tt>), не вывести тест, определяющий, что была применена именно эта замена. Поэтому тест приходится писать тоже человеку и в виде параметра для <tt>egrep(1)</tt>. Пример из <tt>/etc/control.d/facilities/su</tt>: | ||
<pre>new_subst public \ | <pre>new_subst public \ | ||
'^#auth[[:space:]]+required[[:space:]]+(/lib/security/)?pam_wheel\.so' \ | '^#auth[[:space:]]+required[[:space:]]+(/lib/security/)?pam_wheel\.so' \ | ||
's,^\(auth[[:space:]]\+required[[:space:]]\+\(/lib/security/\)\?pam_wheel\.so\),#\1,'</pre> | 's,^\(auth[[:space:]]\+required[[:space:]]\+\(/lib/security/\)\?pam_wheel\.so\),#\1,'</pre> | ||
Здесь <tt>public</tt> | Здесь <tt>public</tt> — опять же название состояния (режим), вторая строка (второй аргумент) — это тест, а третья — руководство по достижению заданного состояния. Опять же, файл, к которому применяются то и другое, здесь не фигурирует. | ||
=== new_help(''name'', ''text'') === | === new_help(''name'', ''text'') === | ||
Очевидно: режиму сопоставляется (закавыченный) текст, который будет выведен по команде <tt>/usr/sbin/control NAME help [MODE]</tt> (при отсутствии указания | Очевидно: режиму сопоставляется (закавыченный) текст, который будет выведен по команде <tt>/usr/sbin/control NAME help [MODE]</tt> (при отсутствии указания режима — все зарегистрированные). | ||
=== new_summary(''text'') === | === new_summary(''text'') === | ||
Ещё проще: единственный аргумент и сопоставляется команде <tt>control NAME summary</tt>. | Ещё проще: единственный аргумент и сопоставляется команде <tt>control NAME summary</tt>. | ||
=== | === Примеры === | ||
В | ==== cdrdao ==== | ||
В простом случае можно обойтись всего несколькими строками, как сделано в пакете {{pkg|cdrdao}} посредством файла {{path|/etc/control.d/facilities/cdrdao}}: | |||
<pre> | |||
#!/bin/sh | |||
< | . /etc/control.d/functions | ||
BINARY=/usr/bin/cdrdao | |||
new_fmode public 4710 root cdwriter | |||
new_fmode restricted 700 root root | |||
control_fmode "$BINARY" "$*" || exit 1 | |||
</pre> | |||
==== su ==== | |||
В качестве более сложного случая можно привести {{path|/etc/control.d/facilities/su}}: | |||
<pre>#!/bin/sh | <pre>#!/bin/sh | ||
Строка 100: | Строка 113: | ||
;; | ;; | ||
esac</pre> | esac</pre> | ||
Здесь <tt>-s</tt> задаёт режим по умолчанию, который стоит согласовать с содержимым пакета: | |||
<pre>%pre -n su | <pre>%pre -n su | ||
Строка 108: | Строка 123: | ||
Вот используемые макросы из ALT Linux RPM: | Вот используемые макросы из ALT Linux RPM: | ||
<tt>%pre_control</tt> | <tt>%pre_control</tt> | ||
<pre>if [ $1 -ge 2 ]; then | <pre>if [ $1 -ge 2 ]; then | ||
Строка 122: | Строка 138: | ||
=== Ссылки === | === Ссылки === | ||
* [[ | * [[ControlErrors|Типичные ошибки при добавлении поддержки control(8)]] | ||
* [https://bugzilla.altlinux.org/show_bug.cgi?id=3426 #3426] (использование макросов в .spec)) | * [https://bugzilla.altlinux.org/show_bug.cgi?id=3426 #3426] (использование макросов в .spec)) | ||
* | * http://packages.altlinux.org/ru/Sisyphus/srpms/control |
Текущая версия от 13:21, 24 мая 2016
control(8)
control(8) — фреймворк, написанный на обычном shell и позволяющий фиксировать и анализировать состояние системных объектов — например, бинарников и файлов конфигурации (например, привилегированных утилит вроде su(8)). С его помощью получается удобным способом вносить переживающие обновление пакета или просто сложные изменения «одним росчерком»; для администраторского ознакомления рекомендуются control(8), control-dump(8) и control-restore(8).
Примеры для пользователя
Например, команды control cdrecord public и control cdrecord restricted соответственно разрешают использование cdrecord для всех пользователей, либо только для членов группы cdwriter.
Запустив control без параметров, можно увидеть полный список средств (facilities) вместе с их текущим состоянием и набором допустимых состояний.
$ control su help public: Any user can execute /bin/su wheel: Any user can execute /bin/su, but only "wheel" group members can switch to superuser wheelonly: Only "wheel" group members can execute /bin/su restricted: Only root can execute /bin/su $ control mtr help public: Any user can execute /usr/bin/mtr netadmin: Only "netadmin" group members can execute /usr/bin/mtr restricted: Only root can execute /usr/bin/mtr
Тем не менее полезнейшая (особенно в пересчёте на объём кода) вещь не жалует документацией собственно желающего улучшить свой пакет или систему созданием (и использованием) control-файлов; давайте попробуем восполнить этот недостаток здесь.
Вкратце
В библиотеку функций /etc/control.d/functions (размером 3747 байт на сейчас) входят используемые в /etc/control.d/facilities/* удобства:
- new_fmode — конструктор «рулилки правами»;
- new_subst — конструктор «рулилки конфигом»;
- new_help — добавление человекопонимаемого комментария к режиму;
- new_summary — добавление человекопонимаемого комментария ко всему control-файлу.
Следует понимать, что объекты получаются двунаправленные: работает как направление режим=>права, так и обратное ему права=>режим; как режим=>конфиг, так и конфиг=>режим. Таким образом возможно не только задавать, но и проверять права, что особенно важно при обновлении пакетов — перед удалением предыдущей версии пакетными скриптами делается control-dump, а после разворачивания новой — control-restore. При этом для избежания промежутков времени с понижением защищённости (если речь о регулировании прав на SUID/SGID binaries, например) в пакете следует задавать предельно жёсткую конфигурацию, которую возможно ослабить уже средствами control в %post.
Кстати о пакетах — примеры можно посмотреть в альтовских su, ping, mtr, samba… проще заглянуть в спеки, хотя если кто допишет, тоже спасибо
new_fmode(name, perms, user, group)
Для обеспечения двунаправленности ничего особенного не требуется, поэтому аргументы не нуждаются в особых разъяснениях — приведём пример:
new_fmode restricted 700 root root
зарегистрирует режим по имени «restricted», характеризующийся правами 0700 (-rwx------) root:root. На что — решается отдельно.
new_subst(name, test, set)
Вот с модификацией текстовых файлов сложнее — из аргумента, являющегося параметром для subst(1) (sed(1)), не вывести тест, определяющий, что была применена именно эта замена. Поэтому тест приходится писать тоже человеку и в виде параметра для egrep(1). Пример из /etc/control.d/facilities/su:
new_subst public \ '^#auth[[:space:]]+required[[:space:]]+(/lib/security/)?pam_wheel\.so' \ 's,^\(auth[[:space:]]\+required[[:space:]]\+\(/lib/security/\)\?pam_wheel\.so\),#\1,'
Здесь public — опять же название состояния (режим), вторая строка (второй аргумент) — это тест, а третья — руководство по достижению заданного состояния. Опять же, файл, к которому применяются то и другое, здесь не фигурирует.
new_help(name, text)
Очевидно: режиму сопоставляется (закавыченный) текст, который будет выведен по команде /usr/sbin/control NAME help [MODE] (при отсутствии указания режима — все зарегистрированные).
new_summary(text)
Ещё проще: единственный аргумент и сопоставляется команде control NAME summary.
Примеры
cdrdao
В простом случае можно обойтись всего несколькими строками, как сделано в пакете cdrdao посредством файла /etc/control.d/facilities/cdrdao:
#!/bin/sh . /etc/control.d/functions BINARY=/usr/bin/cdrdao new_fmode public 4710 root cdwriter new_fmode restricted 700 root root control_fmode "$BINARY" "$*" || exit 1
su
В качестве более сложного случая можно привести /etc/control.d/facilities/su:
#!/bin/sh . /etc/control.d/functions CONFIG=/etc/pam.d/su BINARY=/bin/su new_subst public \ '^#auth[[:space:]]+required[[:space:]]+(/lib/security/)?pam_wheel\.so' \ 's,^\(auth[[:space:]]\+required[[:space:]]\+\(/lib/security/\)\?pam_wheel\.so\),#\1,' new_fmode public 4711 root root new_subst wheel \ '^auth[[:space:]]+required[[:space:]]+(/lib/security/)?pam_wheel\.so' \ 's,^#\(auth[[:space:]]\+required[[:space:]]\+\(/lib/security/\)\?pam_wheel\.so\),\1,' new_fmode wheelonly 4710 root wheel new_fmode restricted 700 root root new_help public "Any user can execute $BINARY" new_help wheel "Any user can execute $BINARY, but only \"wheel\" group members can switch to superuser" new_help wheelonly "Only \"wheel\" group members can execute $BINARY" new_help restricted "Only root can execute $BINARY" case "$*" in status|'') STATUS="`control_fmode "$BINARY" status`" || exit 1 if [ "$STATUS" = "public" ]; then control_subst "$CONFIG" status || exit 1 else test -z "$STATUS" || echo "$STATUS" fi ;; public|wheel) control_fmode "$BINARY" public || exit 1 control_subst "$CONFIG" "$*" || exit 1 ;; wheelonly|restricted) control_fmode "$BINARY" "$*" || exit 1 control_subst "$CONFIG" public || exit 1 ;; *) control_fmode "$BINARY" "$*" || exit 1 ;; esac
Здесь -s задаёт режим по умолчанию, который стоит согласовать с содержимым пакета:
%pre -n su %pre_control su %post -n su %post_control -s wheelonly su
Вот используемые макросы из ALT Linux RPM:
%pre_control
if [ $1 -ge 2 ]; then /usr/sbin/control-dump fi
%post_control
if [ $1 -ge 2 ]; then /usr/sbin/control-restore else for facility in ; do /usr/sbin/control "$facility" public done fi
Ссылки
- Типичные ошибки при добавлении поддержки control(8)
- #3426 (использование макросов в .spec))
- http://packages.altlinux.org/ru/Sisyphus/srpms/control