← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:signing-cv2-kernel into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:signing-cv2-kernel into launchpad:master.

Commit message:
Add support for Ambarella CV2 kernel keys

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/396930

Unlike the existing key types which were all added before we wrote lp-signing, this key type works exclusively via the signing service.  This should be the pattern for any future key types we add.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:signing-cv2-kernel into launchpad:master.
diff --git a/lib/lp/archivepublisher/signing.py b/lib/lp/archivepublisher/signing.py
index ffa1464..588a66f 100644
--- a/lib/lp/archivepublisher/signing.py
+++ b/lib/lp/archivepublisher/signing.py
@@ -1,4 +1,4 @@
-# Copyright 2012-2020 Canonical Ltd.  This software is licensed under the
+# Copyright 2012-2021 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """The processing of Signing tarballs.
@@ -297,6 +297,8 @@ class SigningUpload(CustomUpload):
                     key_type = SigningKeyType.SIPL
                 elif filename.endswith(".fit"):
                     key_type = SigningKeyType.FIT
+                elif filename.endswith(".cv2-kernel"):
+                    key_type = SigningKeyType.CV2_KERNEL
                 else:
                     continue
 
@@ -305,9 +307,12 @@ class SigningUpload(CustomUpload):
                         key_type, self.archive, self.distro_series)
                     handler = partial(
                         self.signUsingSigningService, key_type, key)
-                    fallback_handler = partial(
-                        self.signUsingLocalKey, key_type,
-                        fallback_handlers.get(key_type))
+                    if key_type in fallback_handlers:
+                        fallback_handler = partial(
+                            self.signUsingLocalKey, key_type,
+                            fallback_handlers.get(key_type))
+                    else:
+                        fallback_handler = None
                     yield file_path, handler, fallback_handler
                 else:
                     yield file_path, fallback_handlers.get(key_type), None
@@ -344,7 +349,7 @@ class SigningUpload(CustomUpload):
             SigningKeyType.FIT: [self.fit_cert, self.fit_key],
             }
         # If we are missing local key files, do not proceed.
-        key_files = [i for i in fallback_keys[key_type] if i]
+        key_files = [i for i in fallback_keys.get(key_type, []) if i]
         return all(os.path.exists(key_file) for key_file in key_files)
 
     def signUsingSigningService(self, key_type, signing_key, filename):
@@ -398,10 +403,14 @@ class SigningUpload(CustomUpload):
             public_key_suffix = ".crt"
         else:
             file_suffix = ".sig"
-            public_key_suffix = ".x509"
+            if key_type == SigningKeyType.CV2_KERNEL:
+                public_key_suffix = ".pub"
+            else:
+                public_key_suffix = ".x509"
 
         signed_filename = filename + file_suffix
-        public_key_filename = key_type.name.lower() + public_key_suffix
+        public_key_filename = (
+            key_type.name.lower().replace("_", "-") + public_key_suffix)
 
         with open(signed_filename, 'wb') as fd:
             fd.write(signed_content)
diff --git a/lib/lp/archivepublisher/tests/test_copy_signingkeys.py b/lib/lp/archivepublisher/tests/test_copy_signingkeys.py
index 049bf95..56862a7 100644
--- a/lib/lp/archivepublisher/tests/test_copy_signingkeys.py
+++ b/lib/lp/archivepublisher/tests/test_copy_signingkeys.py
@@ -139,6 +139,8 @@ class TestCopySigningKeysScript(TestCaseWithFactory):
             "INFO No FIT signing key for %s / None" % archives[0].reference,
             "INFO No OpenPGP signing key for %s / None" %
                 archives[0].reference,
+            "INFO No CV2 Kernel signing key for %s / None" %
+                archives[0].reference,
             ]
         self.assertEqual(
             expected_log, script.logger.content.as_text().splitlines())
@@ -245,6 +247,8 @@ class TestCopySigningKeysScript(TestCaseWithFactory):
                 archives[0].reference, distro_serieses[0].name),
             "INFO No OpenPGP signing key for %s / %s" % (
                 archives[0].reference, distro_serieses[0].name),
+            "INFO No CV2 Kernel signing key for %s / %s" % (
+                archives[0].reference, distro_serieses[0].name),
             ]
         self.assertEqual(
             expected_log, script.logger.content.as_text().splitlines())
diff --git a/lib/lp/archivepublisher/tests/test_signing.py b/lib/lp/archivepublisher/tests/test_signing.py
index 9ca1be5..d431457 100644
--- a/lib/lp/archivepublisher/tests/test_signing.py
+++ b/lib/lp/archivepublisher/tests/test_signing.py
@@ -1,4 +1,4 @@
-# Copyright 2012-2020 Canonical Ltd.  This software is licensed under the
+# Copyright 2012-2021 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Test UEFI custom uploads."""
@@ -1632,6 +1632,7 @@ class TestSigningUploadWithSigningService(TestSigningHelpers):
         self.tarfile.add_file("1.0/empty.opal", b"c")
         self.tarfile.add_file("1.0/empty.sipl", b"d")
         self.tarfile.add_file("1.0/empty.fit", b"e")
+        self.tarfile.add_file("1.0/empty.cv2-kernel", b"f")
 
         self.process_emulate()
 
@@ -1653,6 +1654,8 @@ class TestSigningUploadWithSigningService(TestSigningHelpers):
                 '1.0/control/sipl.x509',
                 '1.0/empty.fit', '1.0/empty.fit.signed',
                 '1.0/control/fit.crt',
+                '1.0/empty.cv2-kernel', '1.0/empty.cv2-kernel.sig',
+                '1.0/control/cv2-kernel.pub',
                 ], tarball.getnames())
         self.assertEqual(0, self.signing_service_client.generate.call_count)
         keys = self.signing_keys
@@ -1671,7 +1674,11 @@ class TestSigningUploadWithSigningService(TestSigningHelpers):
                 'empty.sipl', b'd', SigningMode.DETACHED),
             call(
                 SigningKeyType.FIT, keys[SigningKeyType.FIT].fingerprint,
-                'empty.fit', b'e', SigningMode.ATTACHED)],
+                'empty.fit', b'e', SigningMode.ATTACHED),
+            call(
+                SigningKeyType.CV2_KERNEL,
+                keys[SigningKeyType.CV2_KERNEL].fingerprint,
+                'empty.cv2-kernel', b'f', SigningMode.DETACHED)],
             self.signing_service_client.sign.call_args_list)
 
     def test_options_signed_only(self):
@@ -1685,6 +1692,7 @@ class TestSigningUploadWithSigningService(TestSigningHelpers):
         self.tarfile.add_file("1.0/empty.opal", b"c")
         self.tarfile.add_file("1.0/empty.sipl", b"d")
         self.tarfile.add_file("1.0/empty.fit", b"e")
+        self.tarfile.add_file("1.0/empty.cv2-kernel", b"f")
 
         self.process_emulate()
 
@@ -1695,6 +1703,7 @@ class TestSigningUploadWithSigningService(TestSigningHelpers):
             "1.0/empty.opal.sig", "1.0/control/opal.x509",
             "1.0/empty.sipl.sig", "1.0/control/sipl.x509",
             "1.0/empty.fit.signed", "1.0/control/fit.crt",
+            "1.0/empty.cv2-kernel.sig", "1.0/control/cv2-kernel.pub",
         ]))
         self.assertEqual(0, self.signing_service_client.generate.call_count)
         keys = self.signing_keys
@@ -1713,7 +1722,11 @@ class TestSigningUploadWithSigningService(TestSigningHelpers):
                 'empty.sipl', b'd', SigningMode.DETACHED),
             call(
                 SigningKeyType.FIT, keys[SigningKeyType.FIT].fingerprint,
-                'empty.fit', b'e', SigningMode.ATTACHED)],
+                'empty.fit', b'e', SigningMode.ATTACHED),
+            call(
+                SigningKeyType.CV2_KERNEL,
+                keys[SigningKeyType.CV2_KERNEL].fingerprint,
+                'empty.cv2-kernel', b'f', SigningMode.DETACHED)],
             self.signing_service_client.sign.call_args_list)
 
     def test_options_tarball_signed_only(self):
@@ -1728,6 +1741,7 @@ class TestSigningUploadWithSigningService(TestSigningHelpers):
         self.tarfile.add_file("1.0/empty.opal", b"c")
         self.tarfile.add_file("1.0/empty.sipl", b"d")
         self.tarfile.add_file("1.0/empty.fit", b"e")
+        self.tarfile.add_file("1.0/empty.cv2-kernel", b"f")
         self.process_emulate()
         self.assertThat(self.getSignedPath("test", "amd64"), SignedMatches([
             "1.0/SHA256SUMS",
@@ -1743,6 +1757,7 @@ class TestSigningUploadWithSigningService(TestSigningHelpers):
                 '1.0/empty.opal.sig', '1.0/control/opal.x509',
                 '1.0/empty.sipl.sig', '1.0/control/sipl.x509',
                 '1.0/empty.fit.signed', '1.0/control/fit.crt',
+                '1.0/empty.cv2-kernel.sig', '1.0/control/cv2-kernel.pub',
             ], tarball.getnames())
         self.assertEqual(0, self.signing_service_client.generate.call_count)
         keys = self.signing_keys
@@ -1761,7 +1776,11 @@ class TestSigningUploadWithSigningService(TestSigningHelpers):
                 'empty.sipl', b'd', SigningMode.DETACHED),
             call(
                 SigningKeyType.FIT, keys[SigningKeyType.FIT].fingerprint,
-                'empty.fit', b'e', SigningMode.ATTACHED)],
+                'empty.fit', b'e', SigningMode.ATTACHED),
+            call(
+                SigningKeyType.CV2_KERNEL,
+                keys[SigningKeyType.CV2_KERNEL].fingerprint,
+                'empty.cv2-kernel', b'f', SigningMode.DETACHED)],
             self.signing_service_client.sign.call_args_list)
 
     def test_archive_copy(self):
@@ -1780,6 +1799,7 @@ class TestSigningUploadWithSigningService(TestSigningHelpers):
         self.tarfile.add_file("1.0/empty.opal", b"c")
         self.tarfile.add_file("1.0/empty.sipl", b"d")
         self.tarfile.add_file("1.0/empty.fit", b"e")
+        self.tarfile.add_file("1.0/empty.cv2-kernel", b"f")
         self.tarfile.close()
         self.buffer.close()
 
@@ -1790,7 +1810,8 @@ class TestSigningUploadWithSigningService(TestSigningHelpers):
         signed_path = self.getSignedPath("test", "amd64")
         self.assertThat(signed_path, SignedMatches(
             ["1.0/SHA256SUMS", "1.0/empty.efi", "1.0/empty.ko",
-             "1.0/empty.opal", "1.0/empty.sipl", "1.0/empty.fit", ]))
+             "1.0/empty.opal", "1.0/empty.sipl", "1.0/empty.fit",
+             "1.0/empty.cv2-kernel"]))
 
         self.assertEqual(0, self.signing_service_client.generate.call_count)
         self.assertEqual(0, self.signing_service_client.sign.call_count)
@@ -1809,7 +1830,7 @@ class TestSigningUploadWithSigningService(TestSigningHelpers):
 
         filenames = [
             "1.0/empty.efi", "1.0/empty.ko", "1.0/empty.opal",
-            "1.0/empty.sipl", "1.0/empty.fit"]
+            "1.0/empty.sipl", "1.0/empty.fit", "1.0/empty.cv2-kernel"]
 
         # Write data on the archive
         self.openArchive("test", "1.0", "amd64")
@@ -1860,7 +1881,7 @@ class TestSigningUploadWithSigningService(TestSigningHelpers):
 
         filenames = [
             "1.0/empty.efi", "1.0/empty.ko", "1.0/empty.opal",
-            "1.0/empty.sipl", "1.0/empty.fit"]
+            "1.0/empty.sipl", "1.0/empty.fit", "1.0/empty.cv2-kernel"]
 
         self.openArchive("test", "1.0", "amd64")
         for filename in filenames:
@@ -1879,20 +1900,20 @@ class TestSigningUploadWithSigningService(TestSigningHelpers):
         expected_signed_filenames = [
             "1.0/empty.efi.signed", "1.0/empty.ko.sig",
             "1.0/empty.opal.sig", "1.0/empty.sipl.sig",
-            "1.0/empty.fit.signed"]
+            "1.0/empty.fit.signed", "1.0/empty.cv2-kernel.sig"]
 
         expected_public_keys_filenames = [
             "1.0/control/uefi.crt", "1.0/control/kmod.x509",
             "1.0/control/opal.x509", "1.0/control/sipl.x509",
-            "1.0/control/fit.crt"]
+            "1.0/control/fit.crt", "1.0/control/cv2-kernel.pub"]
 
         signed_path = self.getSignedPath("test", "amd64")
         self.assertThat(signed_path, SignedMatches(
             ["1.0/SHA256SUMS"] + filenames + expected_public_keys_filenames +
             expected_signed_filenames))
 
-        self.assertEqual(5, self.signing_service_client.generate.call_count)
-        self.assertEqual(5, self.signing_service_client.sign.call_count)
+        self.assertEqual(6, self.signing_service_client.generate.call_count)
+        self.assertEqual(6, self.signing_service_client.sign.call_count)
 
         fingerprints = {
             key_type: data['fingerprint'] for key_type, data in
@@ -1912,7 +1933,12 @@ class TestSigningUploadWithSigningService(TestSigningHelpers):
                 'empty.sipl', b'data - 1.0/empty.sipl', SigningMode.DETACHED),
             call(
                 SigningKeyType.FIT, fingerprints[SigningKeyType.FIT],
-                'empty.fit', b'data - 1.0/empty.fit', SigningMode.ATTACHED)],
+                'empty.fit', b'data - 1.0/empty.fit', SigningMode.ATTACHED),
+            call(
+                SigningKeyType.CV2_KERNEL,
+                fingerprints[SigningKeyType.CV2_KERNEL],
+                'empty.cv2-kernel', b'data - 1.0/empty.cv2-kernel',
+                SigningMode.DETACHED)],
             self.signing_service_client.sign.call_args_list)
 
         # Checks that all files got signed
@@ -1920,13 +1946,14 @@ class TestSigningUploadWithSigningService(TestSigningHelpers):
             signed_path, expected_signed_filenames)
         key_types = (
             SigningKeyType.UEFI, SigningKeyType.KMOD, SigningKeyType.OPAL,
-            SigningKeyType.SIPL, SigningKeyType.FIT)
+            SigningKeyType.SIPL, SigningKeyType.FIT, SigningKeyType.CV2_KERNEL)
         modes = {
             SigningKeyType.UEFI: SigningMode.ATTACHED,
             SigningKeyType.KMOD: SigningMode.DETACHED,
             SigningKeyType.OPAL: SigningMode.DETACHED,
             SigningKeyType.SIPL: SigningMode.DETACHED,
             SigningKeyType.FIT: SigningMode.ATTACHED,
+            SigningKeyType.CV2_KERNEL: SigningMode.DETACHED,
             }
         expected_signed_contents = [
             ("signed with key_type=%s mode=%s" % (
diff --git a/lib/lp/services/signing/enums.py b/lib/lp/services/signing/enums.py
index ef3b612..bba843f 100644
--- a/lib/lp/services/signing/enums.py
+++ b/lib/lp/services/signing/enums.py
@@ -1,4 +1,4 @@
-# Copyright 2009-2020 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2021 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Enums for signing keys management."""
@@ -62,6 +62,12 @@ class SigningKeyType(DBEnumeratedType):
         An OpenPGP signing key.
         """)
 
+    CV2_KERNEL = DBItem(7, """
+        CV2 Kernel
+
+        An Ambarella CV2 kernel signing key.
+        """)
+
 
 class OpenPGPKeyAlgorithm(EnumeratedType):