Browse Source

dist: Add support for automatically signing Android App Bundles

rdb 4 years ago
parent
commit
eb753be249
2 changed files with 33 additions and 3 deletions
  1. 8 0
      direct/src/dist/commands.py
  2. 25 3
      direct/src/dist/installers.py

+ 8 - 0
direct/src/dist/commands.py

@@ -1565,6 +1565,9 @@ class bdist_apps(setuptools.Command):
         self.installers = {}
         self.dist_dir = os.path.join(os.getcwd(), 'dist')
         self.skip_build = False
+        self.signing_certificate = None
+        self.signing_private_key = None
+        self.signing_passphrase = None
         self.installer_functions = {}
         self._current_platform = None
         for opt in self._build_apps_options():
@@ -1578,6 +1581,11 @@ class bdist_apps(setuptools.Command):
             for key, value in _parse_dict(self.installers).items()
         }
 
+        if self.signing_certificate:
+            assert self.signing_private_key, 'Missing signing_private_key'
+            self.signing_certificate = os.path.abspath(self.signing_certificate)
+            self.signing_private_key = os.path.abspath(self.signing_private_key)
+
         tmp = self.DEFAULT_INSTALLER_FUNCS.copy()
         tmp.update(self.installer_functions)
         tmp.update({

+ 25 - 3
direct/src/dist/installers.py

@@ -218,10 +218,12 @@ def create_aab(command, basename, build_dir):
         axml.parse_xml(fh.read())
 
     # We use our own zip implementation, which can create the correct
-    # alignment needed by Android automatically.
+    # alignment and signature needed by Android automatically.
+    bundle_fn.unlink()
+
     bundle = p3d.ZipArchive()
-    if not bundle.open_write(bundle_fn):
-        command.announce.error(
+    if not bundle.open_read_write(bundle_fn):
+        command.announce(
             f'\tUnable to open {bundle_fn} for writing', distutils.log.ERROR)
         return
 
@@ -290,3 +292,23 @@ def create_aab(command, basename, build_dir):
             fn = p3d.Filename.from_os_specific(dirpath) / name
             if fn.is_regular_file():
                 bundle.add_subfile(f'base/{rel_dirpath}/{name}', fn, 9)
+
+    # Finally, generate the manifest file / signature, if a signing certificate
+    # has been specified.
+    if command.signing_certificate:
+        password = command.signing_passphrase or ''
+
+        if not password and 'ENCRYPTED' in open(command.signing_private_key).read():
+            # It appears to be encrypted, and we don't have a passphrase, so we
+            # must request it on the command-line.
+            from getpass import getpass
+            password = getpass(f'Enter pass phrase for private key: ')
+
+        if not bundle.add_jar_signature(
+                p3d.Filename.from_os_specific(command.signing_certificate),
+                p3d.Filename.from_os_specific(command.signing_private_key),
+                password):
+            command.announce(
+                f'\tFailed to sign {bundle_fn}.', distutils.log.ERROR)
+
+    bundle.close()