← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~cjwatson/launchpad/fix-release-file-signing into lp:launchpad

 

Colin Watson has proposed merging lp:~cjwatson/launchpad/fix-release-file-signing into lp:launchpad.

Commit message:
Fix signing of Release files when distsroot is overridden.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #1759422 in Launchpad itself: "r18584 broke Release file signing with overridden distsroot"
  https://bugs.launchpad.net/launchpad/+bug/1759422

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/fix-release-file-signing/+merge/342252
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/fix-release-file-signing into lp:launchpad.
=== modified file 'lib/lp/archivepublisher/archivesigningkey.py'
--- lib/lp/archivepublisher/archivesigningkey.py	2018-01-19 17:38:51 +0000
+++ lib/lp/archivepublisher/archivesigningkey.py	2018-03-27 23:03:09 +0000
@@ -62,6 +62,7 @@
 
     def __init__(self, archive):
         self.archive = archive
+        self.pubconf = getPubConfig(self.archive)
 
     @property
     def can_sign(self):
@@ -119,9 +120,11 @@
                     "No signing key available for %s" %
                     self.archive.displayname)
 
-    def signRepository(self, suite, suffix='', log=None):
+    def signRepository(self, suite, pubconf=None, suffix='', log=None):
         """See `ISignableArchive`."""
-        suite_path = os.path.join(self._archive_root_path, 'dists', suite)
+        if pubconf is None:
+            pubconf = self.pubconf
+        suite_path = os.path.join(pubconf.distsroot, suite)
         release_file_path = os.path.join(suite_path, 'Release' + suffix)
         if not os.path.exists(release_file_path):
             raise AssertionError(
@@ -140,12 +143,12 @@
     def signFile(self, suite, path, log=None):
         """See `ISignableArchive`."""
         # Allow the passed path to be relative to the archive root.
-        path = os.path.realpath(os.path.join(self._archive_root_path, path))
+        path = os.path.realpath(os.path.join(self.pubconf.archiveroot, path))
 
         # Ensure the resulting path is within the archive root after
         # normalisation.
         # NOTE: uses os.sep to prevent /var/tmp/../tmpFOO attacks.
-        archive_root = self._archive_root_path + os.sep
+        archive_root = self.pubconf.archiveroot + os.sep
         if not path.startswith(archive_root):
             raise AssertionError(
                 "Attempting to sign file (%s) outside archive_root for %s" % (
@@ -159,10 +162,6 @@
 class ArchiveSigningKey(SignableArchive):
     """`IArchive` adapter for manipulating its GPG key."""
 
-    @property
-    def _archive_root_path(self):
-        return getPubConfig(self.archive).archiveroot
-
     def getPathForSecretKey(self, key):
         """See `IArchiveSigningKey`."""
         return os.path.join(

=== modified file 'lib/lp/archivepublisher/interfaces/archivesigningkey.py'
--- lib/lp/archivepublisher/interfaces/archivesigningkey.py	2018-01-19 15:38:21 +0000
+++ lib/lp/archivepublisher/interfaces/archivesigningkey.py	2018-03-27 23:03:09 +0000
@@ -36,10 +36,15 @@
 
     can_sign = Attribute("True if this archive is set up for signing.")
 
-    def signRepository(suite, log=None):
+    def signRepository(suite, pubconf=None, suffix='', log=None):
         """Sign the corresponding repository.
 
         :param suite: suite name to be signed.
+        :param pubconf: an optional publisher configuration instance
+            indicating where files should be written (if not passed, uses
+            the archive's defaults).
+        :param suffix: an optional suffix for repository index files (e.g.
+            ".new" to help with publishing files atomically).
         :param log: an optional logger.
         :raises CannotSignArchive: if the context archive is not set up for
             signing.

=== modified file 'lib/lp/archivepublisher/publishing.py'
--- lib/lp/archivepublisher/publishing.py	2018-01-19 17:38:51 +0000
+++ lib/lp/archivepublisher/publishing.py	2018-03-27 23:03:09 +0000
@@ -1247,7 +1247,8 @@
         if signable_archive.can_sign:
             # Sign the repository.
             self.log.debug("Signing Release file for %s" % suite)
-            signable_archive.signRepository(suite, suffix=".new", log=self.log)
+            signable_archive.signRepository(
+                suite, pubconf=self._config, suffix=".new", log=self.log)
             core_files.add("Release.gpg")
             core_files.add("InRelease")
         else:

=== modified file 'lib/lp/archivepublisher/tests/test_archivesigningkey.py'
--- lib/lp/archivepublisher/tests/test_archivesigningkey.py	2018-03-21 11:52:42 +0000
+++ lib/lp/archivepublisher/tests/test_archivesigningkey.py	2018-03-27 23:03:09 +0000
@@ -62,8 +62,7 @@
         self.assertTrue(signer.can_sign)
         signer.signFile(self.suite, filename)
 
-        signature = filename + '.gpg'
-        self.assertTrue(os.path.exists(signature))
+        self.assertTrue(os.path.exists(filename + ".gpg"))
 
     def test_signFile_absolute_outside_archive(self):
         filename = os.path.join(self.temp_dir, "signme")
@@ -72,7 +71,7 @@
         signer = ISignableArchive(self.archive)
         self.assertTrue(signer.can_sign)
         self.assertRaises(
-            AssertionError, lambda: signer.signFile(self.suite, filename))
+            AssertionError, signer.signFile, self.suite, filename)
 
     def test_signFile_relative_within_archive(self):
         filename_relative = "signme"
@@ -83,8 +82,7 @@
         self.assertTrue(signer.can_sign)
         signer.signFile(self.suite, filename_relative)
 
-        signature = filename + '.gpg'
-        self.assertTrue(os.path.exists(signature))
+        self.assertTrue(os.path.exists(filename + ".gpg"))
 
     def test_signFile_relative_outside_archive(self):
         filename_relative = "../signme"
@@ -94,8 +92,7 @@
         signer = ISignableArchive(self.archive)
         self.assertTrue(signer.can_sign)
         self.assertRaises(
-            AssertionError,
-            lambda: signer.signFile(self.suite, filename_relative))
+            AssertionError, signer.signFile, self.suite, filename_relative)
 
 
 class TestSignableArchiveWithRunParts(RunPartsMixin, TestCaseWithFactory):
@@ -144,6 +141,29 @@
                 "clear signature of %s (%s/%s)\n" %
                 (release_path, self.distro.name, self.suite)))
 
+    def test_signRepository_honours_pubconf(self):
+        pubconf = getPubConfig(self.archive)
+        pubconf.distsroot = self.makeTemporaryDirectory()
+        suite_dir = os.path.join(pubconf.distsroot, self.suite)
+        release_path = os.path.join(suite_dir, "Release")
+        write_file(release_path, "Release contents")
+
+        signer = ISignableArchive(self.archive)
+        self.assertTrue(signer.can_sign)
+        self.assertRaises(AssertionError, signer.signRepository, self.suite)
+        signer.signRepository(self.suite, pubconf=pubconf)
+
+        self.assertThat(
+            os.path.join(suite_dir, "Release.gpg"),
+            FileContains(
+                "detached signature of %s (%s/%s)\n" %
+                (release_path, self.distro.name, self.suite)))
+        self.assertThat(
+            os.path.join(suite_dir, "InRelease"),
+            FileContains(
+                "clear signature of %s (%s/%s)\n" %
+                (release_path, self.distro.name, self.suite)))
+
     def test_signFile_runs_parts(self):
         filename = os.path.join(self.archive_root, "signme")
         write_file(filename, "sign this")

=== modified file 'lib/lp/archivepublisher/tests/test_publisher.py'
--- lib/lp/archivepublisher/tests/test_publisher.py	2018-03-26 06:51:44 +0000
+++ lib/lp/archivepublisher/tests/test_publisher.py	2018-03-27 23:03:09 +0000
@@ -34,6 +34,10 @@
 except ImportError:
     from backports import lzma
 import pytz
+from testscenarios import (
+    load_tests_apply_scenarios,
+    WithScenarios,
+    )
 from testtools.matchers import (
     ContainsAll,
     DirContains,
@@ -2928,9 +2932,15 @@
             os.rename(temporary_dists, original_dists)
 
 
-class TestPublisherRepositorySignatures(RunPartsMixin, TestPublisherBase):
+class TestPublisherRepositorySignatures(
+        WithScenarios, RunPartsMixin, TestPublisherBase):
     """Testing `Publisher` signature behaviour."""
 
+    scenarios = [
+        ('default distsroot', {'override_distsroot': False}),
+        ('overridden distsroot', {'override_distsroot': True}),
+        ]
+
     run_tests_with = AsynchronousDeferredRunTest.make_factory(timeout=10)
 
     archive_publisher = None
@@ -2947,6 +2957,9 @@
             allowed_suites = []
             self.archive_publisher = getPublisher(
                 archive, allowed_suites, self.logger)
+            if self.override_distsroot:
+                self.archive_publisher._config.distsroot = (
+                    self.makeTemporaryDirectory())
 
     def _publishArchive(self, archive):
         """Publish a test source in the given archive.
@@ -3335,3 +3348,6 @@
             ),
         }
         self.assertThat(self.fetchSums(rootdir), MatchesDict(expected))
+
+
+load_tests = load_tests_apply_scenarios


Follow ups