X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=PVE%2FAPLInfo.pm;h=affdde8ecdbe9dce66c8168fc6078f32d7f58252;hb=c6611893f6880c6e610ab926a9fb9d5970ea4b83;hp=ada8cf7be4bdfa6cdec9cd2659ae7ee68eae3c95;hpb=648af5ab223117830a75ce098978236a88d622a3;p=pve-manager.git diff --git a/PVE/APLInfo.pm b/PVE/APLInfo.pm index ada8cf7b..affdde8e 100644 --- a/PVE/APLInfo.pm +++ b/PVE/APLInfo.pm @@ -1,47 +1,26 @@ package PVE::APLInfo; use strict; +use warnings; + use IO::File; -use PVE::SafeSyslog; use LWP::UserAgent; use POSIX qw(strftime); +use PVE::SafeSyslog; +use PVE::Storage; +use PVE::Tools qw(run_command); +use PVE::pvecfg; + my $logfile = "/var/log/pveam.log"; my $aplinfodir = "/var/lib/pve-manager/apl-info"; -# Default list of GPG keys allowed to sign aplinfo -# -#pub 1024D/5CAC72FE 2004-06-24 -# Key fingerprint = 9ABD 7E02 AD24 3AD3 C2FB BCCC B0C1 CC22 5CAC 72FE -#uid Proxmox Support Team -#pub 2048R/A16EB94D 2008-08-15 [expires: 2023-08-12] -# Key fingerprint = 694C FF26 795A 29BA E07B 4EB5 85C2 5E95 A16E B94D -#uid Turnkey Linux Release Key - -my $valid_keys = { - '9ABD7E02AD243AD3C2FBBCCCB0C1CC225CAC72FE' => 1, # fingerprint support@proxmox.com - '25CAC72FE' => 1, # keyid support@proxmox.com - '694CFF26795A29BAE07B4EB585C25E95A16EB94D' => 1, # fingerprint release@turnkeylinux.com - 'A16EB94D' => 1, # keyid release@turnkeylinux.com -}; - -sub import_gpg_keys { - - my @keyfiles = ('support@proxmox.com.pubkey', 'release@turnkeylinux.com.pubkey'); - - foreach my $key (@keyfiles) { - my $fn = "/usr/share/doc/pve-manager/$key"; - system ("/usr/bin/gpg --batch --no-tty --status-fd=1 -q " . - "--logger-fd=1 --import $fn >>$logfile"); - } -} - sub logmsg { my ($logfd, $msg) = @_; chomp $msg; - my $tstr = strftime ("%b %d %H:%M:%S", localtime); + my $tstr = strftime ("%F %H:%M:%S", localtime); foreach my $line (split (/\n/, $msg)) { print $logfd "$tstr $line\n"; @@ -55,7 +34,7 @@ sub read_aplinfo_from_fh { while (my $rec = <$fh>) { chomp $rec; - + my $res = {}; while ($rec) { @@ -69,7 +48,7 @@ sub read_aplinfo_from_fh { $res->{description} = $long; } elsif ($rec =~ s/^Version:\s*(.*\S)\s*\n//i) { my $version = $1; - if ($version =~ m/^(\d[a-zA-Z0-9\.\+\-\:\~]*)-(\d+)$/) { + if ($version =~ m/^(\d[a-zA-Z0-9\.\+\-\:\~]*)(-(\d+))?$/) { $res->{version} = $version; } else { my $msg = "unable to parse appliance record: version = '$version'\n"; @@ -87,29 +66,34 @@ sub read_aplinfo_from_fh { $res->{lc $1} = $2; } else { my $msg = "unable to parse appliance record: $rec\n"; - $update ? die $msg : warn $msg; + $update ? die $msg : warn $msg; $res = {}; last; } } - + if ($res->{'package'} eq 'pve-web-news' && $res->{description}) { - $list->{'all'}->{$res->{'package'}} = $res; + $list->{'all'}->{$res->{'package'}} = $res; next; } $res->{section} = 'unknown' if !$res->{section}; - + if ($res->{'package'} && $res->{type} && $res->{os} && $res->{version} && $res->{infopage}) { my $template; if ($res->{location}) { $template = $res->{location}; - $template =~ s|.*/([^/]+.tar.gz)|$1|; + $template =~ s|.*/([^/]+$PVE::Storage::vztmpl_extension_re)$|$1|; + if ($res->{location} !~ m|^([a-zA-Z]+)\://|) { + # relative localtion (no http:// prefix) + $res->{location} = "$source/$res->{location}"; + } } else { my $arch = $res->{architecture} || 'i386'; $template = "$res->{os}-$res->{package}_$res->{version}_$arch.tar.gz"; $template =~ s/$res->{os}-$res->{os}-/$res->{os}-/; + $res->{location} = "$source/$res->{section}/$template"; } $res->{source} = $source; $res->{template} = $template; @@ -117,7 +101,7 @@ sub read_aplinfo_from_fh { $list->{'all'}->{$template} = $res; } else { my $msg = "found incomplete appliance records\n"; - $update ? die $msg : warn $msg; + $update ? die $msg : warn $msg; } } } @@ -134,7 +118,7 @@ sub read_aplinfo { close($fh); die $err if $err; - + return $list; } @@ -157,10 +141,11 @@ sub url_get { } sub download_aplinfo { - my ($ua, $aplurl, $host, $logfd) = @_; + my ($ua, $aplinfo, $logfd) = @_; - my $aplsrcurl = "$aplurl/aplinfo.dat.gz"; - my $aplsigurl = "$aplurl/aplinfo.dat.asc"; + my $aplsrcurl = "$aplinfo->{url}/$aplinfo->{file}.gz"; + my $aplsigurl = "$aplinfo->{url}/$aplinfo->{file}.asc"; + my $host = $aplinfo->{host}; my $tmp = "$aplinfodir/pveam-${host}.tmp.$$"; my $tmpgz = "$tmp.gz"; @@ -175,57 +160,28 @@ sub download_aplinfo { if (url_get($ua, $aplsrcurl, $tmpgz, $logfd) != 0) { die "update failed - no data file '$aplsrcurl'\n"; } - - if (system("zcat -f $tmpgz >$tmp 2>/dev/null") != 0) { - die "update failed: unable to unpack '$tmpgz'\n"; - } - - # verify signature - - my $cmd = "/usr/bin/gpg --verify --trust-model always --batch --no-tty --status-fd=1 -q " . - "--logger-fd=1 $sigfn $tmp"; - - open(CMD, "$cmd|") || - die "unable to execute '$cmd': $!\n"; - my $line; - my $signer = ''; - while (defined($line = )) { - chomp $line; - logmsg($logfd, $line); + eval { run_command(["gunzip", "-f", $tmpgz]) }; + die "update failed: unable to unpack '$tmpgz'\n" if $@; - # code borrowed from SA - next if $line !~ /^\Q[GNUPG:]\E (?:VALID|GOOD)SIG (\S{8,40})/; - my $key = $1; - - # we want either a keyid (8) or a fingerprint (40) - if (length $key > 8 && length $key < 40) { - substr($key, 8) = ''; - } - # use the longest match we can find - $signer = $key if (length $key > length $signer) && $valid_keys->{$key}; - } - - close(CMD); - - die "unable to verify signature\n" if !$signer; + # verify signature + my $trustedkeyring = "/usr/share/doc/pve-manager/trustedkeys.gpg"; + my $cmd = "/usr/bin/gpgv -q --keyring $trustedkeyring $sigfn $tmp"; - logmsg($logfd, "signature valid: $signer"); + my $logfunc = sub { logmsg($logfd, "signature verification: $_[0]"); }; + eval { + run_command($cmd, outfunc => $logfunc, errfunc => $logfunc); + }; + die "unable to verify signature - $@\n" if $@; # test syntax - eval { - my $fh = IO::File->new("<$tmp") || - die "unable to open file '$tmp' - $!\n"; - read_aplinfo($tmp, {}, $aplurl, 1); - close($fh); - }; + eval { read_aplinfo($tmp, {}, $aplinfo->{url}, 1) }; die "update failed: $@" if $@; - if (system("mv $tmp $aplinfodir/$host 2>/dev/null") != 0) { - die "update failed: unable to store data\n"; - } + rename($tmp, "$aplinfodir/$host") or + die "update failed: unable to store data: $!\n"; - logmsg($logfd, "update sucessful"); + logmsg($logfd, "update successful"); }; my $err = $@; @@ -238,54 +194,56 @@ sub download_aplinfo { } sub get_apl_sources { - - my $urls = []; - push @$urls, "http://download.proxmox.com/images"; - push @$urls, "http://releases.turnkeylinux.org/pve"; - - return $urls; + my $sources = [ + { + host => "download.proxmox.com", + url => "http://download.proxmox.com/images", + file => 'aplinfo-pve-8.dat', + }, + { + host => "releases.turnkeylinux.org", + url => "https://releases.turnkeylinux.org/pve", + file => 'aplinfo.dat', + }, + ]; + + return $sources; } sub update { my ($proxy) = @_; - my $size; - if (($size = (-s $logfile) || 0) > (1024*50)) { - system ("mv $logfile $logfile.0"); + my $logfile_size = -s $logfile || 0; + if ($logfile_size > 1024 * 256) { + rename($logfile, "$logfile.0") or warn "failed to rotate log file $logfile - $!\n"; } my $logfd = IO::File->new (">>$logfile"); logmsg($logfd, "starting update"); - import_gpg_keys(); - - # this code works for ftp and http - # always use passive ftp - local $ENV{FTP_PASSIVE} = 1; my $ua = LWP::UserAgent->new; - $ua->agent("PVE/1.0"); + my $release = PVE::pvecfg::release(); + $ua->agent("PVE/$release"); if ($proxy) { - $ua->proxy(['http'], $proxy); + $ua->proxy(['http', 'https'], $proxy); } else { $ua->env_proxy; } - my $urls = get_apl_sources(); + my $sources = get_apl_sources(); mkdir $aplinfodir; my @dlerr = (); - foreach my $aplurl (@$urls) { - eval { - my $uri = URI->new($aplurl); - my $host = $uri->host(); - download_aplinfo($ua, $aplurl, $host, $logfd); + foreach my $info (@$sources) { + eval { + download_aplinfo($ua, $info, $logfd); }; if (my $err = $@) { logmsg ($logfd, $err); - push @dlerr, $aplurl; + push @dlerr, $info->{url}; } - } + } close($logfd); @@ -296,17 +254,13 @@ sub update { sub load_data { - my $urls = get_apl_sources(); + my $sources = get_apl_sources(); my $list = {}; - - foreach my $aplurl (@$urls) { - - eval { - - my $uri = URI->new($aplurl); - my $host = $uri->host(); - read_aplinfo("$aplinfodir/$host", $list, $aplurl); + foreach my $info (@$sources) { + eval { + my $host = $info->{host}; + read_aplinfo("$aplinfodir/$host", $list, $info->{url}); }; warn $@ if $@; }