]> git.proxmox.com Git - pve-manager.git/blobdiff - PVE/APLInfo.pm
update shipped appliance info index
[pve-manager.git] / PVE / APLInfo.pm
index a26c617df8289c76fdf101724d0254e12d42a066..a0bb92908b7d6e54892d664931c9eb5f867f8464 100644 (file)
@@ -1,47 +1,26 @@
 package PVE::APLInfo;
 
 use strict;
+use warnings;
+
 use IO::File;
-use PVE::SafeSyslog;
 use LWP::UserAgent;
 use POSIX qw(strftime);
 
-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 <support@proxmox.com>
-#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 <release@turnkeylinux.com>
-
-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");
-    }
-}
+use PVE::SafeSyslog;
+use PVE::Storage;
+use PVE::Tools qw(run_command);
+use PVE::pvecfg;
+
+my $LOGFILE = "/var/log/pveam.log";
+my $APL_INFO_DIRECTORY = "/var/lib/pve-manager/apl-info";
 
 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) {
@@ -87,25 +66,25 @@ 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.[gx]z)$|$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}";
@@ -122,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;
        }
     }
 }
@@ -139,7 +118,7 @@ sub read_aplinfo {
     close($fh);
 
     die $err if $err;
-    
+
     return $list;
 }
 
@@ -162,12 +141,13 @@ 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 $tmp = "$APL_INFO_DIRECTORY/pveam-${host}.tmp.$$";
     my $tmpgz = "$tmp.gz";
     my $sigfn = "$tmp.asc";
 
@@ -180,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 = <CMD>)) {
-           chomp $line;
-           logmsg($logfd, $line);
 
-           # code borrowed from SA
-           next if $line !~ /^\Q[GNUPG:]\E (?:VALID|GOOD)SIG (\S{8,40})/;
-           my $key = $1;  
+       eval { run_command(["gunzip", "-f", $tmpgz]) };
+       die "update failed: unable to unpack '$tmpgz'\n" if $@;
 
-           # 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, "$APL_INFO_DIRECTORY/$host") or
+           die "update failed: unable to store data: $!\n";
 
-       logmsg($logfd, "update sucessful");
+       logmsg($logfd, "update successful");
     };
 
     my $err = $@;
@@ -243,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");
+    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;
+    mkdir $APL_INFO_DIRECTORY;
 
     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);
 
@@ -301,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("$APL_INFO_DIRECTORY/$host", $list, $info->{url});
        };
        warn $@ if $@;
     }