Blame SOURCES/0003-reposync-Check-GPG-signatures-of-downloaded-packages-RhBug-1856818.patch

f35d1a
From a4f21266a6dab9e77913d56c04aba1e579f0e0c1 Mon Sep 17 00:00:00 2001
f35d1a
From: Marek Blaha <mblaha@redhat.com>
f35d1a
Date: Fri, 23 Oct 2020 09:06:35 +0200
f35d1a
Subject: [PATCH 1/2] [reposync] Reorder options alphabetically
f35d1a
f35d1a
---
f35d1a
 doc/reposync.rst    | 30 +++++++++++++++---------------
f35d1a
 plugins/reposync.py | 18 +++++++++---------
f35d1a
 2 files changed, 24 insertions(+), 24 deletions(-)
f35d1a
f35d1a
diff --git a/doc/reposync.rst b/doc/reposync.rst
f35d1a
index 71a435dc..3b820f33 100644
f35d1a
--- a/doc/reposync.rst
f35d1a
+++ b/doc/reposync.rst
f35d1a
@@ -39,36 +39,36 @@ Options
f35d1a
 
f35d1a
 All general DNF options are accepted. Namely, the ``--repoid`` option can be used to specify the repositories to synchronize. See `Options` in :manpage:`dnf(8)` for details.
f35d1a
 
f35d1a
-``-p <download-path>, --download-path=<download-path>``
f35d1a
-    Root path under which the downloaded repositories are stored, relative to the current working directory. Defaults to the current working directory. Every downloaded repository has a subdirectory named after its ID under this path.
f35d1a
-    
f35d1a
-``--norepopath``
f35d1a
-    Don't add the reponame to the download path. Can only be used when syncing a single repository (default is to add the reponame).
f35d1a
-
f35d1a
-``--download-metadata``
f35d1a
-    Download all repository metadata. Downloaded copy is instantly usable as a repository, no need to run createrepo_c on it.
f35d1a
-
f35d1a
 ``-a <architecture>, --arch=<architecture>``
f35d1a
     Download only packages of given architectures (default is all architectures). Can be used multiple times.
f35d1a
 
f35d1a
-``--source``
f35d1a
-    Operate on source packages.
f35d1a
+``--delete``
f35d1a
+    Delete local packages no longer present in repository.
f35d1a
+
f35d1a
+``--download-metadata``
f35d1a
+    Download all repository metadata. Downloaded copy is instantly usable as a repository, no need to run createrepo_c on it.
f35d1a
 
f35d1a
 ``-m, --downloadcomps``
f35d1a
     Also download and uncompress comps.xml. Consider using ``--download-metadata`` option which will download all available repository metadata.
f35d1a
 
f35d1a
+``--metadata-path``
f35d1a
+    Root path under which the downloaded metadata are stored. It defaults to ``--download-path`` value if not given.
f35d1a
+
f35d1a
 ``-n, --newest-only``
f35d1a
     Download only newest packages per-repo.
f35d1a
 
f35d1a
-``--delete``
f35d1a
-    Delete local packages no longer present in repository.
f35d1a
+``--norepopath``
f35d1a
+    Don't add the reponame to the download path. Can only be used when syncing a single repository (default is to add the reponame).
f35d1a
 
f35d1a
-``--metadata-path``
f35d1a
-    Root path under which the downloaded metadata are stored. It defaults to ``--download-path`` value if not given.
f35d1a
+``-p <download-path>, --download-path=<download-path>``
f35d1a
+    Root path under which the downloaded repositories are stored, relative to the current working directory. Defaults to the current working directory. Every downloaded repository has a subdirectory named after its ID under this path.
f35d1a
 
f35d1a
 ``--remote-time``
f35d1a
     Try to set the timestamps of the downloaded files to those on the remote side.
f35d1a
 
f35d1a
+``--source``
f35d1a
+    Operate on source packages.
f35d1a
+
f35d1a
 ``-u, --urls``
f35d1a
     Just print urls of what would be downloaded, don't download.
f35d1a
 
f35d1a
diff --git a/plugins/reposync.py b/plugins/reposync.py
f35d1a
index 7556e7eb..6f572cac 100644
f35d1a
--- a/plugins/reposync.py
f35d1a
+++ b/plugins/reposync.py
f35d1a
@@ -63,24 +63,24 @@ def set_argparser(parser):
f35d1a
                             help=_('download only packages for this ARCH'))
f35d1a
         parser.add_argument('--delete', default=False, action='store_true',
f35d1a
                             help=_('delete local packages no longer present in repository'))
f35d1a
-        parser.add_argument('-m', '--downloadcomps', default=False, action='store_true',
f35d1a
-                            help=_('also download and uncompress comps.xml'))
f35d1a
         parser.add_argument('--download-metadata', default=False, action='store_true',
f35d1a
                             help=_('download all the metadata.'))
f35d1a
+        parser.add_argument('-m', '--downloadcomps', default=False, action='store_true',
f35d1a
+                            help=_('also download and uncompress comps.xml'))
f35d1a
+        parser.add_argument('--metadata-path',
f35d1a
+                            help=_('where to store downloaded repository metadata. '
f35d1a
+                                   'Defaults to the value of --download-path.'))
f35d1a
         parser.add_argument('-n', '--newest-only', default=False, action='store_true',
f35d1a
                             help=_('download only newest packages per-repo'))
f35d1a
-        parser.add_argument('-p', '--download-path', default='./',
f35d1a
-                            help=_('where to store downloaded repositories'))
f35d1a
         parser.add_argument('--norepopath', default=False, action='store_true',
f35d1a
                             help=_("Don't add the reponame to the download path."))
f35d1a
-        parser.add_argument('--metadata-path',
f35d1a
-                            help=_('where to store downloaded repository metadata. '
f35d1a
-                                   'Defaults to the value of --download-path.'))
f35d1a
-        parser.add_argument('--source', default=False, action='store_true',
f35d1a
-                            help=_('operate on source packages'))
f35d1a
+        parser.add_argument('-p', '--download-path', default='./',
f35d1a
+                            help=_('where to store downloaded repositories'))
f35d1a
         parser.add_argument('--remote-time', default=False, action='store_true',
f35d1a
                             help=_('try to set local timestamps of local files by '
f35d1a
                                    'the one on the server'))
f35d1a
+        parser.add_argument('--source', default=False, action='store_true',
f35d1a
+                            help=_('operate on source packages'))
f35d1a
         parser.add_argument('-u', '--urls', default=False, action='store_true',
f35d1a
                             help=_("Just list urls of what would be downloaded, "
f35d1a
                                    "don't download"))
f35d1a
f35d1a
From 978b7f2b1c654fed7b1b4cf45cb607143226804c Mon Sep 17 00:00:00 2001
f35d1a
From: Marek Blaha <mblaha@redhat.com>
f35d1a
Date: Fri, 23 Oct 2020 09:14:02 +0200
f35d1a
Subject: [PATCH 2/2] [reposync] Check GPG signatures of downloaded packages
f35d1a
 (RhBug:1856818)
f35d1a
f35d1a
YUMv3 reposync used to have --gpgcheck option to remove packages that fail GPG
f35d1a
signature checking after downloading.
f35d1a
This patch implements the option for DNF.
f35d1a
f35d1a
= changelog =
f35d1a
msg:           Add --gpgcheck option to reposync (RhBug:1856818)
f35d1a
type:          enhancement
f35d1a
resolves:      https://bugzilla.redhat.com/show_bug.cgi?id=1856818
f35d1a
---
f35d1a
 doc/reposync.rst    |  4 ++++
f35d1a
 plugins/reposync.py | 21 +++++++++++++++++++++
f35d1a
 2 files changed, 25 insertions(+)
f35d1a
f35d1a
diff --git a/doc/reposync.rst b/doc/reposync.rst
f35d1a
index 3b820f33..de40957f 100644
f35d1a
--- a/doc/reposync.rst
f35d1a
+++ b/doc/reposync.rst
f35d1a
@@ -48,6 +48,10 @@ All general DNF options are accepted. Namely, the ``--repoid`` option can be use
f35d1a
 ``--download-metadata``
f35d1a
     Download all repository metadata. Downloaded copy is instantly usable as a repository, no need to run createrepo_c on it.
f35d1a
 
f35d1a
+``-g, --gpgcheck``
f35d1a
+    Remove packages that fail GPG signature checking after downloading. Exit code is ``1`` if at least one package was removed.
f35d1a
+    Note that for repositories with ``gpgcheck=0`` set in their configuration the GPG signature is not checked even with this option used.
f35d1a
+
f35d1a
 ``-m, --downloadcomps``
f35d1a
     Also download and uncompress comps.xml. Consider using ``--download-metadata`` option which will download all available repository metadata.
f35d1a
 
f35d1a
diff --git a/plugins/reposync.py b/plugins/reposync.py
f35d1a
index 6f572cac..c891bfa2 100644
f35d1a
--- a/plugins/reposync.py
f35d1a
+++ b/plugins/reposync.py
f35d1a
@@ -24,6 +24,7 @@
f35d1a
 import hawkey
f35d1a
 import os
f35d1a
 import shutil
f35d1a
+import types
f35d1a
 
f35d1a
 from dnfpluginscore import _, logger
f35d1a
 from dnf.cli.option_parser import OptionParser
f35d1a
@@ -65,6 +66,9 @@ def set_argparser(parser):
f35d1a
                             help=_('delete local packages no longer present in repository'))
f35d1a
         parser.add_argument('--download-metadata', default=False, action='store_true',
f35d1a
                             help=_('download all the metadata.'))
f35d1a
+        parser.add_argument('-g', '--gpgcheck', default=False, action='store_true',
f35d1a
+                            help=_('Remove packages that fail GPG signature checking '
f35d1a
+                                   'after downloading'))
f35d1a
         parser.add_argument('-m', '--downloadcomps', default=False, action='store_true',
f35d1a
                             help=_('also download and uncompress comps.xml'))
f35d1a
         parser.add_argument('--metadata-path',
f35d1a
@@ -114,6 +118,7 @@ def configure(self):
f35d1a
 
f35d1a
     def run(self):
f35d1a
         self.base.conf.keepcache = True
f35d1a
+        gpgcheck_ok = True
f35d1a
         for repo in self.base.repos.iter_enabled():
f35d1a
             if self.opts.remote_time:
f35d1a
                 repo._repo.setPreserveRemoteTime(True)
f35d1a
@@ -150,8 +155,24 @@ def run(self):
f35d1a
                 self.print_urls(pkglist)
f35d1a
             else:
f35d1a
                 self.download_packages(pkglist)
f35d1a
+                if self.opts.gpgcheck:
f35d1a
+                    for pkg in pkglist:
f35d1a
+                        local_path = self.pkg_download_path(pkg)
f35d1a
+                        # base.package_signature_check uses pkg.localPkg() to determine
f35d1a
+                        # the location of the package rpm file on the disk.
f35d1a
+                        # Set it to the correct download path.
f35d1a
+                        pkg.localPkg  = types.MethodType(
f35d1a
+                            lambda s, local_path=local_path: local_path, pkg)
f35d1a
+                        result, error = self.base.package_signature_check(pkg)
f35d1a
+                        if result != 0:
f35d1a
+                            logger.warning(_("Removing {}: {}").format(
f35d1a
+                                os.path.basename(local_path), error))
f35d1a
+                            os.unlink(local_path)
f35d1a
+                            gpgcheck_ok = False
f35d1a
             if self.opts.delete:
f35d1a
                 self.delete_old_local_packages(repo, pkglist)
f35d1a
+        if not gpgcheck_ok:
f35d1a
+            raise dnf.exceptions.Error(_("GPG signature check failed."))
f35d1a
 
f35d1a
     def repo_target(self, repo):
f35d1a
         return _pkgdir(self.opts.destdir or self.opts.download_path,