summaryrefslogtreecommitdiffstats
path: root/testing/mozharness/mozharness/mozilla/signing.py
diff options
context:
space:
mode:
Diffstat (limited to 'testing/mozharness/mozharness/mozilla/signing.py')
-rwxr-xr-xtesting/mozharness/mozharness/mozilla/signing.py101
1 files changed, 101 insertions, 0 deletions
diff --git a/testing/mozharness/mozharness/mozilla/signing.py b/testing/mozharness/mozharness/mozilla/signing.py
new file mode 100755
index 000000000..3b16ce595
--- /dev/null
+++ b/testing/mozharness/mozharness/mozilla/signing.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+# ***** BEGIN LICENSE BLOCK *****
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+# ***** END LICENSE BLOCK *****
+"""Mozilla-specific signing methods.
+"""
+
+import os
+import re
+import json
+
+from mozharness.base.errors import BaseErrorList
+from mozharness.base.log import ERROR, FATAL
+from mozharness.base.signing import AndroidSigningMixin, BaseSigningMixin
+
+AndroidSignatureVerificationErrorList = BaseErrorList + [{
+ "regex": re.compile(r'''^Invalid$'''),
+ "level": FATAL,
+ "explanation": "Signature is invalid!"
+}, {
+ "substr": "filename not matched",
+ "level": ERROR,
+}, {
+ "substr": "ERROR: Could not unzip",
+ "level": ERROR,
+}, {
+ "regex": re.compile(r'''Are you sure this is a (nightly|release) package'''),
+ "level": FATAL,
+ "explanation": "Not signed!"
+}]
+
+
+# SigningMixin {{{1
+
+class SigningMixin(BaseSigningMixin):
+ """Generic signing helper methods."""
+ def query_moz_sign_cmd(self, formats=['gpg']):
+ if 'MOZ_SIGNING_SERVERS' not in os.environ:
+ self.fatal("MOZ_SIGNING_SERVERS not in env; no MOZ_SIGN_CMD for you!")
+ dirs = self.query_abs_dirs()
+ signing_dir = os.path.join(dirs['abs_work_dir'], 'tools', 'release', 'signing')
+ cache_dir = os.path.join(dirs['abs_work_dir'], 'signing_cache')
+ token = os.path.join(dirs['base_work_dir'], 'token')
+ nonce = os.path.join(dirs['base_work_dir'], 'nonce')
+ host_cert = os.path.join(signing_dir, 'host.cert')
+ python = self.query_exe('python')
+ cmd = [
+ python,
+ os.path.join(signing_dir, 'signtool.py'),
+ '--cachedir', cache_dir,
+ '-t', token,
+ '-n', nonce,
+ '-c', host_cert,
+ ]
+ if formats:
+ for f in formats:
+ cmd += ['-f', f]
+ for h in os.environ['MOZ_SIGNING_SERVERS'].split(","):
+ cmd += ['-H', h]
+ return cmd
+
+ def generate_signing_manifest(self, files):
+ """Generate signing manifest for signingworkers
+
+ Every entry in the manifest requires a dictionary of
+ "file_to_sign" (basename) and "hash" (SHA512) of every file to be
+ signed. Signing format is defined in the signing task.
+ """
+ manifest_content = [
+ {
+ "file_to_sign": os.path.basename(f),
+ "hash": self.query_sha512sum(f)
+ }
+ for f in files
+ ]
+ return json.dumps(manifest_content)
+
+
+# MobileSigningMixin {{{1
+class MobileSigningMixin(AndroidSigningMixin, SigningMixin):
+ def verify_android_signature(self, apk, script=None, key_alias="nightly",
+ tools_dir="tools/", env=None):
+ """Runs mjessome's android signature verification script.
+ This currently doesn't check to see if the apk exists; you may want
+ to do that before calling the method.
+ """
+ c = self.config
+ dirs = self.query_abs_dirs()
+ if script is None:
+ script = c.get('signature_verification_script')
+ if env is None:
+ env = self.query_env()
+ return self.run_command(
+ [script, "--tools-dir=%s" % tools_dir, "--%s" % key_alias,
+ "--apk=%s" % apk],
+ cwd=dirs['abs_work_dir'],
+ env=env,
+ error_list=AndroidSignatureVerificationErrorList
+ )