diff options
-rw-r--r-- | lib/MGA/Advisories.pm | 211 | ||||
-rwxr-xr-x | mkadvisories | 221 |
2 files changed, 219 insertions, 213 deletions
diff --git a/lib/MGA/Advisories.pm b/lib/MGA/Advisories.pm new file mode 100644 index 0000000..b82f181 --- /dev/null +++ b/lib/MGA/Advisories.pm @@ -0,0 +1,211 @@ +package MGA::Advisories; + +use warnings; +use strict; +use YAML qw(LoadFile DumpFile); +use Template; +use DateTime; +use Email::Sender::Simple qw(try_to_sendmail); +use Email::Simple; +use Email::Simple::Creator; +#use Data::Dump qw(dd); + +my $config_file = '/usr/share/mga-advisories/config'; +my $config = LoadFile($ENV{MGAADV_CONF} || $config_file); +my $etc_config_file = '/etc/mga-advisories.conf'; +my $etc_config = LoadFile($etc_config_file); +foreach my $k (keys %$etc_config) { + $config->{$k} = $etc_config->{$k}; +} + +my %basename = ( + CVE => sub { $_[0] }, + ID => sub { $_[0] }, + rel => sub { $_[0] }, + src => sub { 'src_' . $_[0] }, +); + +my %tools = ( + pkgname => sub { $_[0] =~ m/(.+)-[^-]+-[^-]+/; $1; }, +); + +my @report_logs; +sub report_log { + push @report_logs, @_; +} + +sub report_exit { + report_log($_[0]); + send_report_mail({ error => $_[0] }); + exit 1; +} + +sub status_file { + $config->{status_dir} . '/' . $_[0]; +} + +sub save_status { + my ($advdb, $adv) = @_; + my $statusfile = status_file($adv); + DumpFile($statusfile, $advdb->{advisories}{$adv}{status}); +} + +sub get_advisories { + my %advisories; + foreach my $advfile (glob "$config->{advisories_dir}/*.adv") { + my $adv = LoadFile($advfile); + next unless $adv->{ID}; + report_exit("Duplicate advisory $adv->{ID}") if $advisories{$adv->{ID}}; + $advisories{$adv->{ID}} = $adv; + my $statusfile = status_file($adv->{ID}); + $adv->{status} = -f $statusfile ? LoadFile($statusfile) : {}; + } + return \%advisories; +} + +sub publish_advisories { + my ($advdb) = @_; + foreach my $adv (keys %{$advdb->{advisories}}) { + next if $advdb->{advisories}{$adv}{status}{published}; + $advdb->{advisories}{$adv}{status}{published} = + $advdb->{advisories}{$adv}{pubtime} || time(); + save_status($advdb, $adv); + } +} + +sub sort_advisories { + my ($advdb) = @_; + foreach my $adv (keys %{$advdb->{advisories}}) { + push @{$advdb->{by_type}{$advdb->{advisories}{$adv}{type}}}, $adv; + foreach my $cve (@{$advdb->{advisories}{$adv}{CVE}}) { + push @{$advdb->{by_cve}{$cve}}, $adv; + } + foreach my $rel (keys %{$advdb->{advisories}{$adv}{src}}) { + push @{$advdb->{by_rel}{$rel}}, $adv; + foreach my $media (keys %{$advdb->{advisories}{$adv}{src}{$rel}}) { + push @{$advdb->{by_media}{$media}}, $adv; + my %pkgs; + foreach my $srpm (@{$advdb->{advisories}{$adv}{src}{$rel}{$media}}) { + my $pkgname = $tools{pkgname}->($srpm); + push @{$advdb->{by_src}{$pkgname}}, $adv + unless grep { $_ eq $adv } @{$advdb->{by_src}{$pkgname}}; + } + } + } + } +} + +sub process_template { + my ($template, $src, $vars, $dest, $ext) = @_; + foreach my $extension ($ext ? $ext : @{$config->{output_format}}) { + next unless -f "$config->{tmpl_dir}/$src.$extension"; + $template->process("$src.$extension", $vars, ref $dest ? $dest : "$dest.$extension") + || die $template->error, "\n"; + } +} + +sub output_pages { + my ($advdb) = @_; + my $template = Template->new( + INCLUDE_PATH => $config->{tmpl_dir}, + OUTPUT_PATH => $config->{out_dir}, + ); + foreach my $adv (keys %{$advdb->{advisories}}) { + my $vars = { + config => $config, + advisory => $adv, + advdb => $advdb, + basename => \%basename, + tools => \%tools, + }; + process_template($template, 'advisory', $vars, $basename{ID}->($adv)); + } + foreach my $by (['rel', 'by_rel'], ['CVE', 'by_cve'], ['src', 'by_src']) { + foreach my $r (keys %{$advdb->{$by->[1]}}) { + my $vars = { + config => $config, + $by->[0] => $r, + advdb => $advdb, + basename => \%basename, + tools => \%tools, + }; + process_template($template, $by->[1], $vars, $basename{$by->[0]}->($r)); + } + } + my $vars = { + config => $config, + advdb => $advdb, + basename => \%basename, + tools => \%tools, + }; + process_template($template, 'index', $vars, 'index'); + process_template($template, 'advisories', $vars, 'advisories'); + process_template($template, 'CVE', $vars, 'CVE'); +} + +sub send_adv_mail { + my ($advdb) = @_; + return unless $config->{send_adv_mail} eq 'yes'; + my $template = Template->new( + INCLUDE_PATH => $config->{tmpl_dir}, + ); + foreach my $adv (keys %{$advdb->{advisories}}) { + next if $advdb->{advisories}{$adv}{status}{mail_sent}; + my $mailcontent; + my $vars = { + config => $config, + advisory => $adv, + advdb => $advdb, + basename => \%basename, + tools => \%tools, + }; + process_template($template, 'advisory', $vars, \$mailcontent, 'txt'); + my $email = Email::Simple->create( + header => [ + To => $config->{adv_mail_to}, + From => $config->{adv_mail_from}, + Subject => "$adv: " . $advdb->{advisories}{$adv}{subject}, + ], + body => $mailcontent + ); + if (try_to_sendmail($email)) { + report_log("Advisory mail for $adv sent"); + $advdb->{advisories}{$adv}{status}{mail_sent} = time(); + save_status($advdb, $adv); + } else { + report_log("Error sending advisory mail $adv"); + } + } +} + +sub send_report_mail { + my ($advdb) = @_; + return unless $config->{send_report_mail} eq 'yes'; + return unless @report_logs; + my $template = Template->new( + INCLUDE_PATH => $config->{tmpl_dir}, + ); + my $mailcontent; + my $vars = { + config => $config, + advdb => $advdb, + report_logs => \@report_logs, + }; + process_template($template, 'report', $vars, \$mailcontent, 'txt'); + my $email = Email::Simple->create( + header => [ + To => $config->{report_mail_to}, + From => $config->{report_mail_from}, + Subject => $advdb->{error} ? 'Advisories Error' : 'Advisories Update', + ], + body => $mailcontent + ); + try_to_sendmail($email); +} + +sub dumpdb { + my ($advdb) = @_; + DumpFile($config->{out_dir} . '/advisories.yaml', $advdb->{advisories}); +} + +1; diff --git a/mkadvisories b/mkadvisories index 1c957cb..7e3ec41 100755 --- a/mkadvisories +++ b/mkadvisories @@ -1,219 +1,14 @@ #!/usr/bin/perl -w use strict; - -use YAML qw(LoadFile DumpFile); -use Template; -use DateTime; -use Email::Sender::Simple qw(try_to_sendmail); -use Email::Simple; -use Email::Simple::Creator; -#use Data::Dump qw(dd); - -my $config_file = '/usr/share/mga-advisories/config'; -my $config = LoadFile($ENV{MGAADV_CONF} || $config_file); -my $etc_config_file = '/etc/mga-advisories.conf'; -my $etc_config = LoadFile($etc_config_file); -foreach my $k (keys %$etc_config) { - $config->{$k} = $etc_config->{$k}; -} - -my %basename = ( - CVE => sub { $_[0] }, - ID => sub { $_[0] }, - rel => sub { $_[0] }, - src => sub { 'src_' . $_[0] }, -); - -my %tools = ( - pkgname => sub { $_[0] =~ m/(.+)-[^-]+-[^-]+/; $1; }, -); - -my @report_logs; -sub report_log { - push @report_logs, @_; -} - -sub report_exit { - report_log($_[0]); - send_report_mail({ error => $_[0] }); - exit 1; -} - -sub status_file { - $config->{status_dir} . '/' . $_[0]; -} - -sub save_status { - my ($advdb, $adv) = @_; - my $statusfile = status_file($adv); - DumpFile($statusfile, $advdb->{advisories}{$adv}{status}); -} - -sub get_advisories { - my %advisories; - foreach my $advfile (glob "$config->{advisories_dir}/*.adv") { - my $adv = LoadFile($advfile); - next unless $adv->{ID}; - report_exit("Duplicate advisory $adv->{ID}") if $advisories{$adv->{ID}}; - $advisories{$adv->{ID}} = $adv; - my $statusfile = status_file($adv->{ID}); - $adv->{status} = -f $statusfile ? LoadFile($statusfile) : {}; - } - return \%advisories; -} - -sub publish_advisories { - my ($advdb) = @_; - foreach my $adv (keys %{$advdb->{advisories}}) { - next if $advdb->{advisories}{$adv}{status}{published}; - $advdb->{advisories}{$adv}{status}{published} = - $advdb->{advisories}{$adv}{pubtime} || time(); - save_status($advdb, $adv); - } -} - -sub sort_advisories { - my ($advdb) = @_; - foreach my $adv (keys %{$advdb->{advisories}}) { - push @{$advdb->{by_type}{$advdb->{advisories}{$adv}{type}}}, $adv; - foreach my $cve (@{$advdb->{advisories}{$adv}{CVE}}) { - push @{$advdb->{by_cve}{$cve}}, $adv; - } - foreach my $rel (keys %{$advdb->{advisories}{$adv}{src}}) { - push @{$advdb->{by_rel}{$rel}}, $adv; - foreach my $media (keys %{$advdb->{advisories}{$adv}{src}{$rel}}) { - push @{$advdb->{by_media}{$media}}, $adv; - my %pkgs; - foreach my $srpm (@{$advdb->{advisories}{$adv}{src}{$rel}{$media}}) { - my $pkgname = $tools{pkgname}->($srpm); - push @{$advdb->{by_src}{$pkgname}}, $adv - unless grep { $_ eq $adv } @{$advdb->{by_src}{$pkgname}}; - } - } - } - } -} - -sub process_template { - my ($template, $src, $vars, $dest, $ext) = @_; - foreach my $extension ($ext ? $ext : @{$config->{output_format}}) { - next unless -f "$config->{tmpl_dir}/$src.$extension"; - $template->process("$src.$extension", $vars, ref $dest ? $dest : "$dest.$extension") - || die $template->error, "\n"; - } -} - -sub output_pages { - my ($advdb) = @_; - my $template = Template->new( - INCLUDE_PATH => $config->{tmpl_dir}, - OUTPUT_PATH => $config->{out_dir}, - ); - foreach my $adv (keys %{$advdb->{advisories}}) { - my $vars = { - config => $config, - advisory => $adv, - advdb => $advdb, - basename => \%basename, - tools => \%tools, - }; - process_template($template, 'advisory', $vars, $basename{ID}->($adv)); - } - foreach my $by (['rel', 'by_rel'], ['CVE', 'by_cve'], ['src', 'by_src']) { - foreach my $r (keys %{$advdb->{$by->[1]}}) { - my $vars = { - config => $config, - $by->[0] => $r, - advdb => $advdb, - basename => \%basename, - tools => \%tools, - }; - process_template($template, $by->[1], $vars, $basename{$by->[0]}->($r)); - } - } - my $vars = { - config => $config, - advdb => $advdb, - basename => \%basename, - tools => \%tools, - }; - process_template($template, 'index', $vars, 'index'); - process_template($template, 'advisories', $vars, 'advisories'); - process_template($template, 'CVE', $vars, 'CVE'); -} - -sub send_adv_mail { - my ($advdb) = @_; - return unless $config->{send_adv_mail} eq 'yes'; - my $template = Template->new( - INCLUDE_PATH => $config->{tmpl_dir}, - ); - foreach my $adv (keys %{$advdb->{advisories}}) { - next if $advdb->{advisories}{$adv}{status}{mail_sent}; - my $mailcontent; - my $vars = { - config => $config, - advisory => $adv, - advdb => $advdb, - basename => \%basename, - tools => \%tools, - }; - process_template($template, 'advisory', $vars, \$mailcontent, 'txt'); - my $email = Email::Simple->create( - header => [ - To => $config->{adv_mail_to}, - From => $config->{adv_mail_from}, - Subject => "$adv: " . $advdb->{advisories}{$adv}{subject}, - ], - body => $mailcontent - ); - if (try_to_sendmail($email)) { - report_log("Advisory mail for $adv sent"); - $advdb->{advisories}{$adv}{status}{mail_sent} = time(); - save_status($advdb, $adv); - } else { - report_log("Error sending advisory mail $adv"); - } - } -} - -sub send_report_mail { - my ($advdb) = @_; - return unless $config->{send_report_mail} eq 'yes'; - return unless @report_logs; - my $template = Template->new( - INCLUDE_PATH => $config->{tmpl_dir}, - ); - my $mailcontent; - my $vars = { - config => $config, - advdb => $advdb, - report_logs => \@report_logs, - }; - process_template($template, 'report', $vars, \$mailcontent, 'txt'); - my $email = Email::Simple->create( - header => [ - To => $config->{report_mail_to}, - From => $config->{report_mail_from}, - Subject => $advdb->{error} ? 'Advisories Error' : 'Advisories Update', - ], - body => $mailcontent - ); - try_to_sendmail($email); -} - -sub dumpdb { - my ($advdb) = @_; - DumpFile($config->{out_dir} . '/advisories.yaml', $advdb->{advisories}); -} +use MGA::Advisories; my %advdb; -$advdb{advisories} = get_advisories(); -publish_advisories(\%advdb); -sort_advisories(\%advdb); -output_pages(\%advdb); -dumpdb(\%advdb); -send_adv_mail(\%advdb); -send_report_mail(\%advdb); +$advdb{advisories} = MGA::Advisories::get_advisories(); +MGA::Advisories::publish_advisories(\%advdb); +MGA::Advisories::sort_advisories(\%advdb); +MGA::Advisories::output_pages(\%advdb); +MGA::Advisories::dumpdb(\%advdb); +MGA::Advisories::send_adv_mail(\%advdb); +MGA::Advisories::send_report_mail(\%advdb); |