Описание системы оповещения о проблемах безопасности Gentoo серверов с glsa

Материал из DvoWiki
Перейти к: навигация, поиск

Описание проблемы

На данный момент в академгородке существует несколько серверов, работающих на Gentoo Linux. Периодически обнаруживаются пакеты с уязвимостями. Присутствие таких пакетов системе отслеживает команда glsa-check. На данный момент в сети работает автоматический сбор информации, предоставляемой glsa, которая агрегируется в RT (request-tracker). Здесь я опишу процесс настройки RT связанный с сбором glsa, а также процесс добавления нового сервера в систему слежения.

Настройки RT связанные с агрегацией писем

Сама по себе настройка RT, это то ещё занятие, но на данный момент допустим, что основная система уже работает. Будим считать, что для обработки событий связанных с нарушениями безопасности glsa у нас есть очередь accity-net. Для того чтобы RT принимал письма, нужно чтобы sendmail перенаправлял их скрипту rt-mailgate. Для этого необходимо прописать alias в файле /etc/mail/aliases следующие строки.

rt-accity-net: "|/var/www/rt/rt-4.0.1/bin/rt-mailgate --queue accity-net --action correspond --url https://rt.dvo.ru/"
rt-accity-net-comment: "|/var/www/rt/rt-4.0.1/bin/rt-mailgate --queue accity-net --action comment --url https://rt.dvo.ru/"

После этого всякое письмо поступающее на адрес rt-accity-net@dvo.ru будет отправлятся в RT и для него будет заводится ticket в очереди accity-net. Письма поступающие на rt-accity-net-comment будут проходить в качестве комментариев. Подробнее об rt-mailgate можно прочесть здесь.

Для того чтобы sendmail смог запустить rt-mailgate нужно добавить ссылку на этот скрипт в папку /usr/adm/sm.bin/

ln -s /var/www/rt/rt-4.0.1/bin/rt-mailgate /usr/adm/sm.bin/rt-mailgate
ls /usr/adm/sm.bin/rt-mailgate
/usr/adm/sm.bin/rt-mailgate -> /var/www/rt/rt-4.0.1/bin/rt-mailgate

Хочу обратить внимание на ещё одну возможность, она описана в коментарии к статье которую уже приводил выше, но наверное стоит привести здесь текст целиком.

Иногда делать через alias неудобно. Например, почтовый сервер и WWW сервер с RT разнесены в разные контейнеры/виртуальные машины/реальные серверы, и устанавливать RT (или даже ее часть) не хочется. Тогда можно воспользоваться fetchmail. Для RT надо создать настоящий почтовый ящик с логином и паролем, после чего для fetchmail можно использовать такой конфиг:

set daemon 15
set syslog
poll MAIL-SERVER-ADDRESS proto IMAP
 user "RT-MAILBOX-LOGIN"
   password "RT-PASSWORD"
   fetchsizelimit 0
   mda '/usr/local/bin/rt-mailgate --queue QUEUE --action correspond --url RT-URL'
set daemon 15 - будем опрашивать ящик один раз в 15 секунд

Где

set syslog - журнал в syslog
poll - секция, описывающая ящик, который надо опросить. Может быть несколько.
MAIL-SERVER-ADDRESS - адрес почтового сервера (в данном случае протокол IMAP)
RT-MAILBOX-LOGIN - login для получения почты
RT-PASSWORD - пароль
QUEUE - очередь
RT-URL - URL, по которому доступна RT

Добавление нового сервера

Для того, чтобы добавить новый сервер к уже работающему RT необходимо произвести следующие действия

  1. Записать скрипт, который будет отвечать за отсылку glsa на добавляемую машину. Поместить его можно в папку /root/Projects
  2. Добавить выполнение скрипта в cron.

Приведу здесь исходник скрипта:

#!/bin/perl

use Getopt::Long;
use Mail::GPG;
use Email::Send;

Getopt::Long::Configure qw(bundling no_getopt_compat);

GetOptions( "body=s" => \$body_text,
            "from=s" => \$from,
            "to=s" => \$to,
            "key_id=s" => \$key_id,
            "subject=s" => \$subject,
            "password=s" => \$password,
            "help" => \$h,
            "glsa" => \$glsa,
            "sign" => \$sign
          );

if(defined $h){
   print "--from <from\@mail>\n";
   print "--to <to\@mail>\n";
   print "--key_id \"key id for sign\"\n";
   print "--password \"password for private key\"\n";
   print "--subject \"Subject of message\"\n";
   print "--body \"Body of message\"\n";
   print "--glsa GLSA send glsa information with (or instead of) body\n";
   print "--sign Sign the message by GPG";
   print "--help This message\n";
   exit(0);
}

my $mg = Mail::GPG->new;

if((not (defined $body_text)) and (not(defined $glsa))){
    die "Body text is not set\n";
}elsif(defined $glsa){
    open(GLSA_OUT, "glsa-check -nl affected |");
    my $new_glsa;
    my $line;
    my $glsa_count=0;
    while(<GLSA_OUT>){
     if($_=~  m/^.*\d+-\d+/g){
          $body_text = $body_text ."\n". $_;
          $glsa_count++;
     }
   }
   close(GLSA_OUT);
   if($glsa_count eq 0){
       die "No glsa affected\n";
   }
}

if(not (defined $from)){
   die "Ftom filed is not set\n ";
}

if(not (defined $to)){
  die "To filed is not set\n ";
}

if(defined $sign){
    if(not (defined $key_id)){
        $key_id =   get_key_id_for_mail($mg ,$from);
        if(not (defined $key_id)){
            die "Key filed is not set\n ";
        }
    } 

   if(not (defined $password)){
       die "Password filed is not set\n ";
   }
}

if(not (defined $subject)){
    die "Subject filed is not set, use standart subject \n"; 
}
 

my @mail_data = [$body_text, "\n"];
my $entity = MIME::Entity->build (
       From     => $from,
       Subject  => $subject,
       Data     => @mail_data, 
       Encoding => "quoted-printable",
       Charset  => "iso-8859-1",
       To => $to,
       );

my $mail_text;
if(defined $sign){
    my $encrypted_entity = $mg->mime_sign( #mime_sign_encrypt (
                                           entity     => $entity,
                                           key_id     => $key_id,
                                           passphrase => $password,
                                           recipients => [$to ],
        );
    $mail_text = $encrypted_entity->as_string;
}else{
    $mail_text = $entity->as_string;
}


print "Mail text:" . $mail_text;

my $sender = Email::Send->new({mailer => 'SMTP'});
  $sender->mailer_args([Host => 'mail.dvo.ru']);
    $sender->send($mail_text);

#===============End main context=====================================

#get key ID for mail address
sub get_key_id_for_mail{
   my ($mg, $from)=@_;
   my $key_id = $mg->query_keyring (
       search => $from,
       );
   return $key_id;
}

В своих инсталляциях я называл этот скрипт PGP_Mail.pl, поэтому буду придерживаться этого названия и дальше. После того как файл /root/Projects/PGP_Mail.pl создан, нужно проверить, установленны ли в системе необходимые модули. Если что, то

g-cpan -i Mail::GPG
g-cpan -i Email::Send;

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

perl /root/Projects/PGP_Mail.pl --to=rt-accity-net@rt.dvo.ru --from=glsa-checker@dvo.ru --subject="glsa Имя новой машины" --glsa

Поясню эту команду.

--to указывает на какой адрес посылать информацию о найденных проблемах. В настоящий момент это rt-accity-net@rt.dvo.ru, специальный алиас который 
перенаправляет всю почту в RT
--from от какого пользователя письмо. Пользователь glsa-checker@dvo.ru специально заведён в LDAP
--subject Заголовок письма
--glsa Указывает на то что нужно проверять glsa и отсылать письмо при обнаружении

После того как вы удостоверились, что скрипт будет работать без ошибок. Можно добавить его в cron

crontab -e
0 4 * * * perl /root/Projects/PGP_Mail.pl --to=rt-accity-net@rt.dvo.ru --from=glsa-checker@dvo.ru --subject="glsa New born machine name" --glsa