Разработка модулей control(8): различия между версиями

Материал из ALT Linux Wiki
м (→‎Вкратце: текущий размер (опечатка была?))
 
(не показано 10 промежуточных версий 4 участников)
Строка 1: Строка 1:
[[Category:Devel]]
[[Category:Devel]]
{{MovedFromFreesourceInfo|AltLinux/Sisyphus/devel/control}}
[[Категория:Безопасность]]


== 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>[http://sisyphus.ru/srpm/control control](8)</tt> -- фреймворк, написанный на обычном shell и позволяющий фиксировать и анализировать состояние системных объектов -- например, бинарников и файлов конфигурации (например, привилегированных утилит вроде <tt>su(8)</tt>). С его помощью получается удобным способом вносить переживающие обновление пакета или просто сложные изменения "одним росчерком"; для администраторского ознакомления рекомендуются <tt>control(8)</tt>, <tt>control-dump(8)</tt> и <tt>control-restore(8)</tt>.


=== Примеры для пользователя ===
=== Примеры для пользователя ===
Строка 24: Строка 23:


=== Вкратце ===
=== Вкратце ===
В библиотеку функций <tt>/etc/control.d/functions</tt> (размером 3947 ''байт'' на сейчас) входят используемые в <tt>/etc/control.d/facilities/*</tt> удобства:
В библиотеку функций <tt>/etc/control.d/functions</tt> (размером 3747 ''байт'' на сейчас) входят используемые в <tt>/etc/control.d/facilities/*</tt> удобства:


* new_fmode -- конструктор "рулилки правами";
* new_fmode — конструктор «рулилки правами»;
* new_subst -- ... "рулилки конфигом";
* new_subst — конструктор «рулилки конфигом»;
* new_help -- добавление человекопонимаемого комментария к режиму;
* new_help — добавление человекопонимаемого комментария к режиму;
* new_summary -- ...ко всему control-файлу.
* new_summary — добавление человекопонимаемого комментария ко всему control-файлу.


Следует понимать, что объекты получаются двунаправленные: работает как направление ''режим=>права'', так и обратное ему ''права=>режим''; как ''режим=>конфиг'', так и ''конфиг=>режим''. Таким образом возможно не только задавать, но и проверять права, что особенно важно при обновлении пакетов -- перед удалением предыдущей версии пакетными скриптами делается <tt>control-dump</tt>, а после разворачивания новой -- <tt>control-restore</tt>. При этом для избежания промежутков времени с понижением защищённости (если речь о регулировании прав на SUID/SGID binaries, например) в пакете следует задавать предельно жёсткую конфигурацию, которую возможно ослабить уже средствами <tt>control</tt> в %post.
Следует понимать, что объекты получаются двунаправленные: работает как направление ''режим=>права'', так и обратное ему ''права=>режим''; как ''режим=>конфиг'', так и ''конфиг=>режим''. Таким образом возможно не только задавать, но и проверять права, что особенно важно при обновлении пакетов — перед удалением предыдущей версии пакетными скриптами делается <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>... проще заглянуть в спеки, хотя если кто допишет, тоже спасибо''
''Кстати о пакетах — примеры можно посмотреть в альтовских <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>. На что -- решается отдельно.
зарегистрирует режим по имени «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>:
Вот с модификацией текстовых файлов сложнее — из аргумента, являющегося параметром для <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>.


=== Пример: <tt>su</tt> ===
=== Примеры ===
В качестве сподручного образца приведу поддержку <tt>control</tt> в <tt>su-0.60-alt24</tt> (исходный пакет -- [http://sisyphus.ru/srpm/SimplePAMApps/spec SimplePAMApps]).
==== cdrdao ====
В простом случае можно обойтись всего несколькими строками, как сделано в пакете {{pkg|cdrdao}} посредством файла {{path|/etc/control.d/facilities/cdrdao}}:
<pre>
#!/bin/sh


<tt>/etc/control.d/facilities/su</tt>:
. /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:


=== Ссылки ===
=== Ссылки ===
* [[control/TypicalErrors|Типичная ошибка]] при добавлении поддержки control(8)
* [[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))
* [[control/admin|Кратко о control(8]]) для админа
* 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

Ссылки