Содержание


Как получить максимальный эффект от sudo

Comments

Sudo - это утилита, с помощью которой системные администраторы могут разрешить пользователям или группам выполнять команды от имени другого пользователя. Другими словами, можно делегировать привилегии пользователя на выполнение команд, не раскрывая при этом его пароля. Пользователь root для этого должен добавить записи sudo в файл /etc/sudoers file. Этот файл следует редактировать с помощью команды visudo. При делегировании прав всегда должен присутствовать элемент доверия. Давайте развеем миф: sudo используется не просто для того, чтобы разрешить пользователям выполнять определенные команды. В основном она используется для того, чтобы делегировать другому пользователю полномочия запускать приложение или выполнять программу от имени ее (его) владельца. Если у вас уже установлена sudo, то установка новой версии не перезапишет ваш существующий файл sudoers. Но, тем не менее, как всегда перед началом работы, сделайте резервную копию файла /etc/sudoers и прочтите инструкцию по обновлению программы.

Устанавливаем sudo

Загрузите последнюю версию sudo.

В данной статье я использовал версию sudo 1.7.2. Если вы работаете в AIX® 5.3, убедитесь, что у вас есть текущая (а именно 4.0.0) версия gcc.

# export LIBPATH=/usr/lib
# ./configure --with-aixauth
# make
# make install

Чтобы проверить версию программы, просмотреть параметры сборки и текущую конфигурацию, выполните от имени пользователя root следующую команду:

# sudo -V 
Sudo version 1.7.2
Sudoers path: /etc/sudoers
Authentication methods: 'aixauth'

< остальной вывод команды не показан>

По умолчанию:

  • sudo находится в /usr/local/bin. Используйте ее, чтобы выполнять команды с полномочиями другого пользователя.
  • Команда visudo находится в /usr/local/sbin. Используйте ее для редактирования файла sudoers.
  • Файл sudoers находится в каталоге /etc. В этом файле хранятся записи о том, кто и для чего может использовать sudo.

Файл sudoers

Файл /etc/sudoers (широко известный как просто sudoers) определяет, кто и для чего может использовать sudo. Модифицировать находящиеся в нем данные может пользователь root или какой-либо другой пользователь с привилегиями пользователя root. В простейшем случае запись в файле sudoers выглядит так:

<user> <host> = <user to alias> <password required> < command to run>

Чтобы просмотреть, какие команды пользователь может выполнять с помощью sudo и какие для него имеются ограничения, выполните от имени пользователя команду:

sudo -l

Для выполнения команды sudo в общем случае используется следующий формат:

sudo -u < user to run as> <command to run>

Настраиваем журналирование

Все команды, выполняемые посредством sudo, заносятся в файл журнала /var/adm/messages с помощью syslog, уровень детализации которого можно настроить с помощью правила в файле /etc/syslog.conf:

*.debug   /var/adm/messages

Однако я считаю, что для журналирования команд sudo следует использовать отдельный файл журнала. Так было бы проще просматривать и анализировать выполняемые команды sudo. К тому же, в таком случае, несомненно, было бы легче отслеживать ошибки при работе с sudo. Создайте файл /var/adm/sudo.log и поместите в файл /etc/sudoers следующую запись:

Defaults logfile=/var/adm/sudo.log
Defaults !syslog

Теперь все события sudo, выполненные успешно или с ошибками, будут заноситься в журнал /var/adm/sudo.log.

Управление файлом sudoers

С течением времени в вашем файле sudoers будет появляться все больше записей, что вполне ожидаемо. Это может происходить из-за установки на сервер дополнительных приложений или делегирования текущих задач для разделения ответственности. Во многих записях могут встречаться опечатки. Поэтому имеет смысл сделать для пользователя root более удобное управление файлом sudoers. Давайте рассмотрим два способа или, по крайней мере, хороших шаблона действий, чтобы этого добиться. Если у вас есть много статических записей (т.е. одних и тех же команд, используемых на каждой машине с sudo), поместите их в отдельный файл sudoers, к которому можно будет обращаться с помощью директивы include.

Ведение записей для каждого пользователя по отдельности может занимать много времени при добавлении или изменении записей. При большом количестве пользователей хорошей практикой является разделение пользователей на группы. Можно создать обычную группу пользователей AIX и работать с этой группой в файле sudoers.

Давайте теперь рассмотрим эти два метода более подробно.

Подключаем файлы

В компьютерных системах крупных предприятий сопровождение файла sudoers является важной задачей, которую необходимо выполнять на регулярной основе. Облегчить эту рутинную работу можно, реорганизовав файл sudoers. Первый способ сделать это - извлечь из файла статические записи, в которых одни и те же команды выполняются на разных машинах, чтобы их можно было повторно использовать. Как и в системе аудита и безопасности, системе резервного копирования storix или отчетах о производительности, в sudo теперь можно использовать директивы include. Основной файл sudoers будет содержать только локальные записи, в то время как файл, подключаемый с помощью include, едва ли потребует редактирования, так как он содержит статические записи. Когда программа visudo встречает директиву include, она сканирует подключаемый файл, и потом продолжает сканирование основного файла sudoers. В реальности это выглядит так: когда вы выходите из visudo, поработав с основным файлом, открывается подключенный файл. После выхода из подключенного файла вы вернетесь в оболочку AIX. Можно иметь более одного подключаемого файла, но я не могу представить себе причину, по которой вам это может понадобиться.

Дадим подключаемому файлу sudoers имя sudo_static.<hostname>. В данных примерах в качестве hostname я использую rs6000. Сделайте в основном файле sudoers следующую запись:

#include /etc/sudo_static.rs6000

Затем добавьте несколько записей в файл /etc/sudo_static.rs6000. Вам необязательно заполнять все директивы и разделы файла. Если файл содержит записи там, где они не нужны, не подключайте его. Например, мой файл include содержит только следующий текст и ничего больше.

bravo     rs6000 = (root) NOPASSWD: /usr/opt/db2_08_01/adm/db2licd -end
bravo     rs6000 = (root) NOPASSWD: /usr/opt/db2_08_01/adm/db2licd
bravo     rs6000 = (db2inst) NOPASSWD: /home/db2inst/sqllib/adm/db2start
bravo     rs6000 = (db2inst) NOPASSWD: /home/db2inst/sqllib/adm/db2stop force

Когда вы запускаете visudo, сохраняете файл и выходите из него, visudo предложит вам нажать Enter, чтобы отредактировать подключенный файл sudoers. После того как вы отредактируете подключенный файл, sudo, как и при работе с основным файлом, проверит его на наличие синтаксических ошибок. Отредактировать подключенный файл также можно напрямую с помощью команды:

visudo -f /etc/sudo_static.rs6000

.

Использование групп

В файле sudoers можно работать с группами пользователей AIX. Это делает управление файлом sudoers более удобным и сокращает количество записей для каждого пользователя. При реорганизации файла sudoers для работы с группами, возможно, вам придется создать новые группы AIX и включить в них пользователей, которым разрешено использовать одни и те же команды sudo. Для использования групп просто используйте в записи префикс '%'. Допустим, у нас есть группы devops и devuat, в которые входят следующие пользователи:

# lsgroup -f -a users devops

devops:
        users=joex,delta,charlie,tstgn

 # lsgroup -f -a users devuat
devuat:
        users=zebra,spsys,charlie

Пользователям группы devops нужно разрешить выполнять команду /usr/local/bin/data_ext.sh с полномочиями пользователя dbdftst.

Пользователям группы devuat нужно разрешить выполнять команды:/usr/local/bin/data_mvup.sh, /usr/local/bin/data_rep.sh с полномочиями пользователя dbukuat.

Для этого можно создать в файле sudoers следующие записи:

%devops rs6000 =  (dbdftst) NOPASSWD: /usr/local/bin/data_ext.sh
%devuat rs6000 =  (dbukuat) /usr/local/bin/data_mvup.sh
%devuat rs6000 =  (dbukuat) /usr/local/bin/data_rep.sh

Заметьте, что согласно этим записям пользователям группы devops не нужно будет вводить пароль для выполнения команды /usr/local/bin/data_ext.sh, в то время как пользователи группы devuat должны будут вводить свой пароль. Пользователь "charlie" входит в обе эти группы (devops и devuat), поэтому он может выполнять все перечисленные выше команды.

Тайм-ауты в sudo

В sudo есть система временных "билетов", которая умеет определять, как много времени прошло с момента выполнения последней команды sudo. В течение определенного периода времени пользователь может "по билету" повторно выполнить команду, не вводя при этом пароль (т.е. свой собственный пароль). По истечении этого времени пользователю при перезапуске команды снова нужно будет вводить пароль. Если пользователь вводит правильный пароль, то выполняется команда и отсчет времени начинается заново. Эти тайм-ауты не используются, если в файле sudoers в записи указана опция NOPASSWD. По умолчанию тайм-аут составляет 5 минут. Поменять значение по умолчанию можно, добавив запись в файл sudoers. Например, задать пользователю "bravo" для выполнения всех команд тайм-аут 20 минут можно следующим образом:

Defaults:bravo timestamp_timeout=20

Чтобы удалить билет, пользователю следует выполнить команду:

$ sudo -k

После удаления билета пользователю при выполнении команды sudo будет предложено ввести пароль.

Не задавайте значение тайм-аута для всех пользователей, так как это может привести к проблемам, особенно при выполнении серии задач, если по каким-либо причинам задачи выполняются дольше, чем обычно. Чтобы выключить использование тайм-аутов, задайте переменной timestamp_timeout значение -1. Временные билеты размещаются в директории /var/run/sudo и называются по имени соответствующего пользователя.

Пользовательские переменные

Как обсуждалось ранее, sudo удаляет потенциально опасные системные переменные. Чтобы проверить, какие переменные сохранились, а какие были удалены, используйте команду sudo -V. Эта команда выведет список удаленных и сохраненных. То, что удаляется переменная LIBPATH, конечно же, неудобно. Есть два способа обойти это: можно написать оберточный сценарий или указать нужные переменные окружения в командной строке. Рассмотрим сначала вариант с оберточным сценарием. Предположим, у нас есть приложение, которое останавливает и запускает процесс DB2®. Можно написать сценарий, который будет оставлять переменные окружения невредимыми. Обратите внимание на листинг 1 rc.db2. Здесь, чтобы оставить переменные окружения нетронутыми, мы выполняем файл профиля пользователя

 . /home/$inst/sqllib/db2profile

в котором, в свою очередь, экспортируются значения переменных окружения LIBPATH и DB2.

Для законченности приведем записи, которые следует добавить в файл sudoers, чтобы можно было выполнять данные команды, сохраняя значения всех системных переменных окружения:

bravo     rs6000 = (dbinst4) NOPASSWD: /home/dbinst4/sqllib/adm/db2start
bravo     rs6000 = (dbinst4) NOPASSWD: /home/dbinst4/sqllib/adm/db2stop force
bravo     rs6000 = (dbinst4) NOPASSWD: /usr/local/bin/rc.db2 stop db2inst4
bravo     rs6000 = (dbinst4) NOPASSWD: /usr/local/bin/rc.db2 start db2inst4

Обратите внимание, что в этом примере пользователь "bravo" может выполнять указанные выше команды с привилегиями пользователя "dbinst4." Выполняемые команды выглядят так:

sudo -u dbinst4 /usr/local/bin/rc.db2 stop db2inst4
sudo -u dbinst4 /usr/local/bin/rc.db2 start db2inst4
Листинг 1. rc.db2
#!/bin/sh
# rc.db2
# stop/start db2 instances

# проверяем, запущен ли процесс db2 
db2_running(){state=`ps -ef |grep db2sysc 
                    |grep -v grep| awk '$1=="'${inst}'" { print $1 }'`
if [ "$state" = "" ] 
then 
    return 1 
else 
    return 0 
fi}

usage ()

{
echo "`basename $0` start | stop <instance>"
}

# останавливаем db2 
stop_db2 ()
{
echo "stopping db2 instance as user $inst" 
    if [ -f /home/$inst/sqllib/db2profile ]; then 
        . /home/$inst/sqllib/db2profile 
else 
    echo "Cannot source DB2..exiting" 
exit 1
fi 
    /home/$inst/sqllib/adm/db2stop force
}

# запускаем db2
start_db2 ()
{
echo "starting db2 instance as user $inst" 
    if [ -f /home/$inst/sqllib/db2profile ]; then 
        . /home/$inst/sqllib/db2profile 
else 
    echo "Cannot source DB2..exiting" 
exit 1
fi
/home/$inst/sqllib/adm/db2start
} 

# проверяем, что в сценарий передано 2 параметра
if [ $# != 2 ]
then 
    usage 
    exit 1
fi

inst=$2 

case "$1" in 
Start|start) 
    if db2_running  
        then  
        echo "db2 instance $inst appears to be already running"
         exit 0 
    else 
        echo " instance not running as user $inst..attempting to start it" 
        start_db2 $inst

        fi
        ;; 
Stop|stop) 
    if db2_running 
        then 
        echo "instance running as $inst..attempting to stop it"
        stop_db2 $inst 
    else 
        echo "db2 instance $inst appears to be not running anyway" 
        exit 0 
    fi 
    ;; 
*) usage  
;;
esac

Другим способом сохранить системные переменные окружения является использование директивы Defaults !env_reset. Укажите ее в файле sudoers:

Defaults !env_reset

Затем укажите в командной строке имена и значения переменных окружения:

$ sudo LIBPATH=″/usr/lib:/opt/db2_09_05/lib64″ -u delta /usr/local/bin/datapmp

Если бы у вас не было записи !env_reset, то при выполнении этой команды sudo выдал бы следующую ошибку:

sudo: sorry, you are not allowed to set the following environment variables: LIBPATH
(извините, вы не можете задать значения следующих переменных окружения: LIBPATH)

Если вы обнаружите, что sudo также удаляет и другие переменные окружения, вы можете указать эти переменные в файле sudoers, чтобы sudo сохранил эти переменные невредимыми (с помощью директивы env_keep +=). Например, предположим, sudo удаляет из одного из моих сценариев переменные DSTAGE_SUP и DSTAGE_META. Чтобы защитить эти переменные, я могу добавить в файл sudoers следующие записи:

Defaults env_keep += "DSTAGE_SUP"
Defaults env_keep += "DSTAGE_META"

Обратите внимание, что я указываю имя переменной, а не ее значение. Значения уже содержатся в моем сценарии, например:

export DSTAGE_SUP=/opt/dstage/dsengine; export DSTAGE_META=/opt/dstage/db2

Теперь при выполнении этого сценария с помощью sudo, значения указанных выше переменных окружения будут сохраняться.

Заботимся о безопасности переменной path для команд sudo

В файле sudoers можно изменять значение по умолчанию переменной PATH с помощью директивы secure_path. Эта директива указывает, где при запуске sudo следует искать исполняемые файлы и команды. Этот параметр пытается явно ограничить области, команды из которых можно выполнять в sudo, что, безусловно, хорошо с точки зрения безопасности. Используйте следующую директиву в файле sudoers, чтобы указать безопасный путь, по которому sudo следует искать команды:

Defaults secure_path="/usr/local/sbin:/usr/local/bin:/opt/freeware/bin:/usr/sbin"

Добавляем ограничения

Sudo позволяет добавлять пользователям ограничения на выполнение определенных команд. Предположим, имеется группа по имени dataex, в которую входят пользователи "alpha", "bravo" и "charlie". Эта группа может с помощью sudo выполнять команду /usr/local/bin/mis_ext *, в которой звездочка обозначает передаваемые в сценарий параметры. Однако пользователю "charlie" не разрешается выполнять этот сценарий с параметром import. Подобные ограничения можно задавать с помощью '!' - оператора логического НЕ. Вот что можно указать в файле sudoers:

 %dataex rs6000 = (dbmis) NOPASSWD: /usr/local/bin/mis_ext *
 charlie rs6000 = (dbmis) NOPASSWD: !/usr/local/bin/mis_ext import

Обратите внимание, что записи с логическим оператором НЕ указываются после обычных записей. Можно указывать несколько подобных записей на одной строке, разделяя их запятыми:

charlie rs6000 = (dbmis) NOPASSWD: /usr/local/bin/aut_pmp *

charlie rs6000 = (dbmis) NOPASSWD: !/usr/local/bin/aut_pmp create,
!/usr/local/bin/aut_pmp delete, !/usr/local/bin/aut_pmp amend

Настраиваем команды sudo для посетителей

Настройку sudo на удаленных машинах в сети крупного предприятия лучше всего делать с помощью сценария ssh от имени пользователя root, причем нужно настроить авторизацию без пароля, с помощью ssh-ключей. Давайте рассмотрим пример. Допустим, на одной из ваших удаленных машин случился аппаратный сбой (отказ жесткого диска или памяти), и на место должен прибыть инженер IBM® для замены сломавшегося оборудования. В подобных случаях для выполнения задачи инженеру может потребоваться пароль пользователя root. Одним из способов предоставить инженеру доступ с правами пользователя root является sudo. При этом желательно сообщить инженеру пароль еще до визита. В листинге 2 показан пример того, как можно реализовать такую конфигурацию. Здесь мы в цикле обходим список машин, с которыми будет работать инженер. (В общем случае у вас будет текстовый файл со списком машин, из которого вы будете читать записи в цикле while.) С помощью 'here document', мы создаем резервную копию файла sudoers и затем добавляем в него такую запись:

# -- ibmeng sudo root
ibmeng host1 = (root) NOPASSWD:ALL

Затем мы создаем пользователя "ibmeng" и с помощью команды chpasswd задаем ему пароль. В данном примере это ibmpw. Затем в его профиль добавляется сообщение, которое проинформирует пользователя, как ему с помощью sudo получить доступ к учетной записи root. После входа в систему инженер увидит сообщение:

IBM Engineer, to access root account type: sudo -u root su -

Конечно же, после визита инженера учетную запись ibmeng следует заблокировать.

Листинг 2. dis_ibm
#!/bin/sh
# dis_ibm
dest_hosts='host1 host2 host3 host4'

for host in $dest_hosts
do
echo "doing [$host]"

$ssh -T -t -l root $host<<'mayday'
host=`hostname`
cp /etc/sudoers /etc/sudoers.bak

    if [ $? != 0 ]
    then
    echo "error: unable to cp sudoers file"
    exit 1
    fi
echo "# -- ibmeng sudo root\nibmeng $host = (root) NOPASSWD:ALL">>/etc/sudoers

mkuser su=false ibmeng
if [ $? = 0 ]
    then
    echo "ibmeng:ibmpw" | chpasswd -c
    else
    echo "error: unable to create user ibmeng and or passwd"
    exit 1
fi
    chuser gecos='IBM engineer acc' ibmeng
if [ -f /home/ibmeng/.profile ]
    then
    echo "echo \"IBM Engineer, to access root account type: sudo -u root su -"\"
>>/home/ibmeng/.profile
fi
mayday
done

Заключение

Sudo позволяет контролировать, кто, с какими привилегиями и какие команды может выполнять. Но вы должны уметь разбираться во всех возможностях файла sudoers, чтобы при работе с ним полностью осознавать возможные последствия и ответственность.


Ресурсы для скачивания


Похожие темы

  • Ознакомьтесь с оригиналом статьи: "Make sudo work harder" (EN, developerWorks, октябрь 2009 г.).
  • Загрузите sudo и узнайте о нем больше.

Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=AIX и UNIX
ArticleID=678552
ArticleTitle=Как получить максимальный эффект от sudo
publish-date=11072011