пятница, 21 августа 2009 г.

sudo и регулярные выражения

Как известно, sudo(1) позволяет администратору разрешить некоторым пользователям запускать определенные команды от имени root-а или другого пользователя. Если файл /etc/sudoers - сетевой, то можно дополнительно ограничить и список хостов, с которых разрешено выполнение той или иной команды. Всё это описано в руководстве.

Для большей гибкости, в sudo предусмотрена поддержка метасимволов * и ?, а также диапазонов [...] и [!...]. Глядя на них может возникнуть желание написать что-то вроде
jonh_smith  ALL=/bin/rm /only/below/this/dir/*
или
jonh_smith    ALL=/bin/mkdir /only/below/this/dir/[a-zA-Z0-9_-]*
даже не взирая на то в руководстве sudoers(4) четко написано:
sudo allows shell-style wildcards ... Note that these are not regular expressions.
Таким образом, sudo не будет возражать против команды
sudo rm /only/below/this/dir/../../other/dir/*
поскольку формально звёздочка "съест" все символы включая / и .. Также у sudo не возникнет вопросов по поводу пары команд
sudo mkdir /only/below/this/dir/a
sudo mkdir /only/below/this/dir/a/../../../another@dir
т.к. фактически на принадлежность к диапазону проверяется только первый символ.

Если регулярные выражения всё же нужны, можно воспользоваться известным приёмом: написать скрипт-обёртку, вызывамый через sudo с произвольными аргументами, который уже сам средствами языка программирования выполнит сколь угодно сложные проверки и только затем запустит потенциально опасную команду. Вот пример на Perl:

Содержимое /etc/sudoers:
jonh_smith  ALL=/usr/local/bin/safe_rm.pl
Исходный код /usr/local/bin/safe_rm.pl:
#!/usr/bin/perl

use strict;
use warnings;

sub main() {
foreach my $arg ( @ARGV ) {
if ( $arg !~ qr{^/only/below/this/dir/[a-zA-Z0-9_-]+$} ) {
die "Unsafe path: '$arg'\n";
}
}

if ( @ARGV > 0 ) {
return system( "/bin/rm", @ARGV );
} else {
die "Empty path list\n";
}
}

main();

среда, 19 августа 2009 г.

Аналог конструкции "grep -v grep"

Для определения того, запущен ли процесс часто используют команду такого вида:
ps aux | grep foo | grep -v grep
Второй grep при этом убирает из списка процессов саму команду grep foo, которая иногда успевает в него просочиться. Сэкономить один grep можно при помощи такой конструкции:
ps aux | grep [f]oo
Смысл в том, что регулярное выражение [f]oo совпадет со строкой foo в списке процессов, но не совпадет со строкой grep [f]oo, которая может появиться в этом списке. Кроме того, на мой взгляд, вариант без grep -v grep выглядит опрятнее.

Если интересует только PID процесса, то удобнее использовать pgrep(1) или pidof(8). Если вдруг этих программ под рукой не окажется, то подойдет такой вариант:
ps aux | grep [f]oo | awk -F' ' '{ print $2 }'

среда, 12 августа 2009 г.

Создание кросс-платформенных графических интерфейсов на Perl/GTK+

Введение

В этой статье приводится обзор библиотеки GTK+ и её интерфейса к языку Perl - Gtk2-Perl. Поскольку GUI-приложения написанные на Gtk2-Perl довольно большая редкость, собирать информацию приходится по крупицам. Цель статьи - постараться дать объективную оценку связке Perl/GTK+: отметить сильные и слабые стороны, предупредить о возможных сложностях и проблемах.

Библиотека GTK+

Изначально библиотека GTK+ была разработана Питером Матисом (Peter Mattis) и Спенсером Кимбелом (Spencer Kimball) для нужд графического редактора GIMP (GNU Image Manipulation Program), но потом была выделена в отдельный проект. Сама библиотека GTK+ написана на C, но существуют языковые привязки (language bindings) и для многих других языков программирования, в их числе и Perl.

Судя по графику релизов и количеству баг-фиксов проект GTK+ развивается достаточно активными темпами. За время существования проекта вокруг него сформировалось внушительное сообщество, что также является положительным моментом. В настоящее время команда ключевых разработчиков состоит из десяти человек, представляющих такие компании как Red Hat, Novell и Intel Open Source Technology Center.

Следует отметить хорошую поддержку механизмов интернационализации и локализации: обратите внимание на использование кодировки UTF-8 в примере.

Документация по библиотекам, входящим в состав GTK+, поддерживается в актуальном состоянии, однако тут есть один нюанс. Разработчики языковых привязок зачастую считают документацию по своим интерфейсам "производной" от документации по оригинальным библиотекам GTK+ и поэтому не всегда поддерживают её в актуальном состоянии. Именно такая ситуация наблюдается с Gtk2-Perl.

Установка в Linux/BSD

Поскольку GTK+ родом из страны UNIX, проблем с её установкой в UNIX-подобных системах обычно не возникает. Вполне может быть, что все необходимые библиотеки и модули у вас уже установлены. Если нет, то наверняка поставщик вашего дистрибутива подготовил пакет со всем необходимым. К примеру, в Mandriva Linux соответствующий пакет называется perl-Gtk2, а в OpenBSD - p5-Gtk2.

Установка в Windows


В Windows всё несколько сложнее. Поскольку Windows-машина с установленным компилятором языка C и необходимым для сборки окружением скорее исключение чем правило, надеяться приходится только на то, что кто-то заботливо скомпилировал для нас все необходимые библиотеки и языковые привязки к ним. Самое интересное, что на момент написания этих строк в ActivePerl, самом популярном Perl-дистрибутиве для Windows, такого пакета нет! Компиляция этого пакета со всеми зависимостями под Windows - нетривиальная и достаточно хлопотная процедура. На сайте Gtk-perl в разделе Win32 Support даются ссылки на альтернативные PPM-репозитории для ActivePerl, однако это тоже не помогло. Что же делать? Обратите внимание на проект Camelbox. Это Perl-дистрибутив под Windows, в состав которого уже включена поддержка самой последней версии GTK+. Если вы хотите использовать ActivePerl, придется приложить дополнительные усилия.

Минимальное приложение


Продемонстрируем работу Gtk2-Perl на простом примере: окне с кнопкой. Этот пример дает первоначальное представление об API библиотеки и служит своего рода тестом: если программа запустилась, значит все необходимые библиотеки установлены и работают правильно.

Приведенный пример запускается без модификаций как минимум на трёх платформах: Linux, OpenBSD и Windows. Как правило и с более сложными приложениями проблем не возникает. Итак, исходный код:

#!/usr/bin/perl

#
# Александр Симаков, <xdr (тчк) box на Google Mail>
# http://alexander-simakov.blogspot.com/
#
# Простейшая программа использующая Gtk2-Perl
#

use strict;
use warnings;

# Включаем поддержку Unicode
use utf8;
use encoding 'utf8';

# Загрузка и инициализация библиотеки Gkt2. Инициализация
# библиотеки (параметр -init) должна выполняться ровно
# один раз.
use Gtk2 -init;

sub main() {
# Создаем главное окно
my $window = Gtk2::Window->new('toplevel');

# Устанавливаем обработчик сигнала закрытия окна
$window->signal_connect( delete_event => sub { Gtk2->main_quit } );

# Создаем кнопку
my $button = Gtk2::Button->new('Тест');

# Устанавливаем обработчик на кнопку
$button->signal_connect( clicked => sub {
print("Тест Gtk2-Perl\n");
});

# Помещаем кнопку на окно
$window->add($button);

# Делаем окно, а также все дочерние виджеты видимыми
$window->show_all();

# Запускаем цикл обработки событий
Gtk2->main();
}

main();

Вид приложения в Linux:

Вид приложения в OpenBSD:


Вид приложения в Windows:

Выводы

В целом, приложения, написанные с использованием GTK+, выглядят довольно современно и красиво. Проект GTK+ имеет давнюю историю и продолжает развиваться. Также стоит отметить хорошую поддержку интернационализации и локализации.

Несколько расстраивают сложности с установкой библиотек и языковых привязок Gtk2-Perl под Windows. Также нужно учитывать, что в отличии от оригинальной документации по GTK+, документация по Gtk2-perl не всегда актуальна и точна.

Еще один пробел - это отсутствие добротной книги по Gtk2-Perl. Из за отсутствия книги, информацию приходится собирать по крупицам из самых разных источников: оригинальная документация по GTK+, различные tutorial-ы и HOW-TO, сообщения в форумах и т.д.

Ссылки
Статья опубликована на портале CITForum

вторник, 11 августа 2009 г.

Создание шифрованного туннеля с помощью SSH

SSH-туннелирование позволяет прозрачным для клиента образом перенаправить сетевой траффик с одного хоста на другой. Самое приятное в этом процессе то, что все передаваемые через туннель данные шифруются. Чаще всего SSH-туннелирование применяют в следующих ситуациях:
  • Имеется хост, прямого доступа к которому нет. Тем не менее, есть SSH-доступ к "соседней" машине с которой этот недоступный извне хост - доступен. Пример: веб-сервер, находящийся за брандмауэром.
  • Удаленный хост доступен напрямую, но хотелось бы организовать прозрачное для туннелируемых приложений шифрование данных.
С обеими задачами SSH справляется "на отлично". Приятно также и то, что туннель создается всего одной командой:
ssh -f foo@bar.com -L 127.0.0.1:8080:web-server:80 -N
В этом примере подразумевается, что у пользователя foo имеется SSH-аккаунт на сервере bar.com. Далее возможны два варианта: либо веб-сервер, упомянутый в примере, не доступен снаружи (но с bar.com к нему подключиться можно), либо веб-сервер доступен, но требуется шифровать данные на участке между локальной машиной и сервером bar.com. В конечном итоге, SSH будет слушать порт 8080 на интерфейсе 127.0.0.1 и пересылать данные на 80-й порт хоста web-server "от имени" сервера bar.com. В результате, набрав в браузере http://localhost:8080 мы фактически попадем на http://web-server:80

При создании туннеля удобно использовать опции -f и -N. Первая опция переводит ssh-клиент в фоновый режим, а вторая - инструктирует его работать в не-командном режиме (т.е. режиме только для туннелирования данных).

вторник, 4 августа 2009 г.

Создание тестовой инсталляции Debian при помощи debootstrap

Иногда для проведения какого-нибудь эксперимента требуется "чистая" инсталляция системы определённой версии без нагромождения лишних программ и настроек. Справедливо и обратное: в ряде случаев желательно изолировать эксперимент от основной системы чтобы не засорять её лишним ПО. Конечно, для таких задач отлично подойдет одна из технологий виртуализации, но зачастую можно обойтись и более легковесным решением. В Debian такое решение называется debootstrap(8).

Эта программа позволяет установить минимальную рабочую Debian-систему в указанный каталог. После завершения установки можно сделать chroot в эту директорию и работать уже в "чистом" окружении. Вот как выглядит типичная процедура установки:
# cd /
# mkdir lenny-root
# debootstrap lenny /lenny-root/ http://ftp.us.debian.org/debian/

I: Retrieving Release
I: Retrieving Packages
I: Validating Packages
I: Resolving dependencies of required packages...
I: Resolving dependencies of base packages...
I: Checking component main on http://ftp.us.debian.org/debian...
I: Retrieving adduser
I: Validating adduser
...
I: Base system installed successfully.

# echo "proc /lenny-root/proc proc none 0 0" >> /etc/fstab
# mount /lenny-root/proc
# chroot /lenny-root
# cat /etc/debian_version

5.0.2
Вот собственно и всё! Система установлена и готова к использованию.