From 739dcdb8cbb886e15d3ff3d90888c8c6ce05d30d Mon Sep 17 00:00:00 2001 From: Heitor Neiva Date: Thu, 16 Nov 2023 10:19:12 -0800 Subject: [PATCH 1/2] feat: Mac hardened signing on signingscript --- signingscript/Dockerfile | 23 +-- .../docker.d/apple_signing_creds.yml | 24 +++ .../docker.d/build_libdmg_hfsplus.sh | 33 ++++ .../docker.d/build_msix_packaging.sh | 5 + signingscript/docker.d/build_rcodesign.sh | 16 ++ signingscript/docker.d/init_worker.sh | 6 +- signingscript/docker.d/worker.yml | 1 + signingscript/files/README | 3 - signingscript/files/dmg | Bin 157088 -> 0 bytes signingscript/files/hfsplus | Bin 106944 -> 0 bytes signingscript/setup.py | 3 +- signingscript/src/signingscript/apple.py | 42 ++++++ .../data/orgmozillanightly.provisionprofile | Bin 0 -> 12436 bytes signingscript/src/signingscript/rcodesign.py | 141 +++++++++++++++++- signingscript/src/signingscript/script.py | 74 ++++++++- signingscript/src/signingscript/sign.py | 86 +++++++++-- signingscript/src/signingscript/task.py | 2 + signingscript/src/signingscript/utils.py | 58 ++++++- signingscript/tests/conftest.py | 7 +- signingscript/tests/data/test.dmg | Bin 0 -> 17644 bytes .../tests/example_apple_signing_config.json | 7 + signingscript/tests/test_config.py | 1 + signingscript/tests/test_rcodesign.py | 47 +++++- signingscript/tox.ini | 7 +- tox.ini | 10 +- 25 files changed, 545 insertions(+), 51 deletions(-) create mode 100644 signingscript/docker.d/apple_signing_creds.yml create mode 100755 signingscript/docker.d/build_libdmg_hfsplus.sh create mode 100755 signingscript/docker.d/build_rcodesign.sh delete mode 100644 signingscript/files/README delete mode 100755 signingscript/files/dmg delete mode 100755 signingscript/files/hfsplus create mode 100644 signingscript/src/signingscript/apple.py create mode 100644 signingscript/src/signingscript/data/orgmozillanightly.provisionprofile create mode 100644 signingscript/tests/data/test.dmg create mode 100644 signingscript/tests/example_apple_signing_config.json diff --git a/signingscript/Dockerfile b/signingscript/Dockerfile index 58ce579f5..0e8b94175 100644 --- a/signingscript/Dockerfile +++ b/signingscript/Dockerfile @@ -11,6 +11,7 @@ RUN groupadd --gid 10001 app && \ # Copy only required folders COPY ["signingscript", "/app/signingscript/"] +COPY ["scriptworker_client", "/app/scriptworker_client/"] COPY ["configloader", "/app/configloader/"] COPY ["docker.d", "/app/docker.d/"] COPY ["vendored", "/app/vendored/"] @@ -19,19 +20,18 @@ COPY ["vendored", "/app/vendored/"] COPY ["version.jso[n]", "/app/"] # Change owner of /app to app:app +# Build and install libdmg_hfsplus # Install msix # Install rcodesign -RUN chown -R app:app /app && \ - cd /app/signingscript/docker.d && \ - bash build_msix_packaging.sh && \ - cp msix-packaging/.vs/bin/makemsix /usr/bin && \ - cp msix-packaging/.vs/lib/libmsix.so /usr/lib && \ - cd .. && \ - rm -rf msix-packaging && \ - wget -qO- \ - https://github.com/indygreg/apple-platform-rs/releases/download/apple-codesign%2F0.22.0/apple-codesign-0.22.0-x86_64-unknown-linux-musl.tar.gz \ - | tar xvz -C /usr/bin --transform 's/.*\///g' --wildcards --no-anchored 'rcodesign' && \ - chmod +x /usr/bin/rcodesign +RUN chown -R app:app /app \ + && cd /app/scriptworker_client \ + && pip install /app/scriptworker_client \ + && pip install -r requirements/base.txt \ + && pip install . \ + && cd /app/signingscript/docker.d \ + && bash build_libdmg_hfsplus.sh /usr/bin \ + && bash build_rcodesign.sh /usr/bin \ + && bash build_msix_packaging.sh # Set user and workdir USER app @@ -40,6 +40,7 @@ WORKDIR /app # Install signingscript + configloader + widevine RUN python -m venv /app \ && cd signingscript \ + && /app/bin/pip install /app/scriptworker_client \ && /app/bin/pip install -r requirements/base.txt \ && /app/bin/pip install . \ && python -m venv /app/configloader_venv \ diff --git a/signingscript/docker.d/apple_signing_creds.yml b/signingscript/docker.d/apple_signing_creds.yml new file mode 100644 index 000000000..457441a03 --- /dev/null +++ b/signingscript/docker.d/apple_signing_creds.yml @@ -0,0 +1,24 @@ +$let: + scope_prefix: + $match: + 'COT_PRODUCT == "firefox"': 'project:releng:signing:' + 'COT_PRODUCT == "thunderbird"': 'project:comm:thunderbird:releng:signing:' + 'COT_PRODUCT == "mozillavpn"': 'project:mozillavpn:releng:signing:' + 'COT_PRODUCT == "adhoc"': 'project:adhoc:releng:signing:' +in: + $merge: + $match: + 'ENV == "prod" && scope_prefix': + '${scope_prefix[0]}cert:release-signing': + - "app_credentials": {"$eval": "APPLE_APP_SIGNING_CREDENTIALS"} + "installer_credentials": {"$eval": "APPLE_INSTALLER_SIGNING_CREDENTIALS"} + "password": {"$eval": "APPLE_SIGNING_CREDS_PASSWORD"} + '${scope_prefix[0]}cert:nightly-signing': + - "app_credentials": {"$eval": "APPLE_APP_SIGNING_CREDENTIALS"} + "installer_credentials": {"$eval": "APPLE_INSTALLER_SIGNING_CREDENTIALS"} + "password": {"$eval": "APPLE_SIGNING_CREDS_PASSWORD"} + 'ENV != "prod" && scope_prefix': + '${scope_prefix[0]}cert:dep-signing': + - "app_credentials": {"$eval": "APPLE_APP_SIGNING_DEP_CREDENTIALS"} + "installer_credentials": {"$eval": "APPLE_INSTALLER_SIGNING_DEP_CREDENTIALS"} + "password": {"$eval": "APPLE_SIGNING_DEP_CREDS_PASSWORD"} diff --git a/signingscript/docker.d/build_libdmg_hfsplus.sh b/signingscript/docker.d/build_libdmg_hfsplus.sh new file mode 100755 index 000000000..338d94b27 --- /dev/null +++ b/signingscript/docker.d/build_libdmg_hfsplus.sh @@ -0,0 +1,33 @@ +#!/bin/bash +set -x -e -v + +# This script is for building libdmg-hfsplus to get the `dmg` and `hfsplus` +# tools for handling DMG archives on Linux. + +DEST=$1 +if [ -d "$DEST" ]; then + echo "Binaries will be installed to: $DEST" +else + echo "Destination directory doesn't exist!" + exit 1 +fi + +git clone --depth=1 --branch mozilla --single-branch https://github.com/mozilla/libdmg-hfsplus/ libdmg-hfsplus + +pushd libdmg-hfsplus + +# The openssl libraries in the sysroot cannot be linked in a PIE executable so we use -no-pie +cmake \ + -DOPENSSL_USE_STATIC_LIBS=1 \ + -DCMAKE_EXE_LINKER_FLAGS=-no-pie \ + . + +make VERBOSE=1 -j$(nproc) + +# We only need the dmg and hfsplus tools. +strip dmg/dmg hfs/hfsplus +cp dmg/dmg hfs/hfsplus "$DEST" + +popd +rm -rf libdmg-hfsplus +echo "Done." diff --git a/signingscript/docker.d/build_msix_packaging.sh b/signingscript/docker.d/build_msix_packaging.sh index 1aa5cd8cc..3fecbb64f 100755 --- a/signingscript/docker.d/build_msix_packaging.sh +++ b/signingscript/docker.d/build_msix_packaging.sh @@ -8,3 +8,8 @@ cd msix-packaging ./makelinux.sh --pack cd .. + +cp msix-packaging/.vs/bin/makemsix /usr/bin +cp msix-packaging/.vs/lib/libmsix.so /usr/lib + +rm -rf msix-packaging diff --git a/signingscript/docker.d/build_rcodesign.sh b/signingscript/docker.d/build_rcodesign.sh new file mode 100755 index 000000000..f63a78ef9 --- /dev/null +++ b/signingscript/docker.d/build_rcodesign.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -x -e -v + +DEST=$1 +if [ -d "$DEST" ]; then + echo "Binaries will be installed to: $DEST" +else + echo "Destination directory doesn't exist!" + exit 1 +fi + + +wget -qO- https://github.com/indygreg/apple-platform-rs/releases/download/apple-codesign%2F0.26.0/apple-codesign-0.26.0-x86_64-unknown-linux-musl.tar.gz \ + | tar xvz -C "$DEST" --transform 's/.*\///g' --wildcards --no-anchored 'rcodesign' + +chmod +x "${DEST}/rcodesign" diff --git a/signingscript/docker.d/init_worker.sh b/signingscript/docker.d/init_worker.sh index bb1b5940a..0bf63c209 100755 --- a/signingscript/docker.d/init_worker.sh +++ b/signingscript/docker.d/init_worker.sh @@ -21,11 +21,12 @@ test_var_set 'PROJECT_NAME' test_var_set 'PUBLIC_IP' test_var_set 'TEMPLATE_DIR' -export DMG_PATH=$APP_DIR/signingscript/files/dmg -export HFSPLUS_PATH=$APP_DIR/signingscript/files/hfsplus +export DMG_PATH=/usr/bin/dmg +export HFSPLUS_PATH=/usr/bin/hfsplus export PASSWORDS_PATH=$CONFIG_DIR/passwords.json export APPLE_NOTARIZATION_CREDS_PATH=$CONFIG_DIR/apple_notarization_creds.json +export APPLE_SIGNING_CONFIG_PATH=$CONFIG_DIR/apple_signing_config.json export GPG_PUBKEY_PATH=$APP_DIR/signingscript/src/signingscript/data/gpg_pubkey_dep.asc export WIDEVINE_CERT_PATH=$CONFIG_DIR/widevine.crt export AUTHENTICODE_TIMESTAMP_STYLE=old @@ -260,3 +261,4 @@ esac $CONFIG_LOADER $TEMPLATE_DIR/passwords.yml $PASSWORDS_PATH $CONFIG_LOADER $TEMPLATE_DIR/apple_notarization_creds.yml $APPLE_NOTARIZATION_CREDS_PATH +$CONFIG_LOADER $TEMPLATE_DIR/apple_signing_creds.yml $APPLE_SIGNING_CONFIG_PATH diff --git a/signingscript/docker.d/worker.yml b/signingscript/docker.d/worker.yml index 989f734af..80d8ea4d8 100644 --- a/signingscript/docker.d/worker.yml +++ b/signingscript/docker.d/worker.yml @@ -4,6 +4,7 @@ verbose: { "$eval": "VERBOSE == 'true'" } my_ip: { "$eval": "PUBLIC_IP" } autograph_configs: { "$eval": "PASSWORDS_PATH" } apple_notarization_configs: { "$eval": "APPLE_NOTARIZATION_CREDS_PATH" } +apple_signing_configs: { "$eval": "APPLE_SIGNING_CONFIG_PATH" } taskcluster_scope_prefixes: $flatten: $match: diff --git a/signingscript/files/README b/signingscript/files/README deleted file mode 100644 index b02a745df..000000000 --- a/signingscript/files/README +++ /dev/null @@ -1,3 +0,0 @@ -Built from https://github.com/andreas56/libdmg-hfsplus rev 81dd75fd1549b24bf8af9736ac25518b367e6b63. -Source is available in tooltool, digest bdd80489477647559a99bae8ee9b87d7cc5df26e44bc5f9282b3b1d7eb0e6946b4c61b6159d74fe2422196c9a0c5117f4e8ff4decf7e514f86df8777c0c6dc65 /home/worker/workspace/artifacts/libdmg-hfsplus.tar.xz. - diff --git a/signingscript/files/dmg b/signingscript/files/dmg deleted file mode 100755 index cbd0f9e9f75f7ec97fa528219de72943419e5154..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 157088 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

;;*lkDg8^oQ*SH%%KT>SWc;?Enl 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 Lo;VKJ1-$v^GjG0#RHL5fVYx$$~fv1Vbck+nQHp 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 wzl@&@!a753vavLBme*a diff --git a/signingscript/setup.py b/signingscript/setup.py index 61f0b9c33..237a32e00 100644 --- a/signingscript/setup.py +++ b/signingscript/setup.py @@ -5,7 +5,8 @@ with open(os.path.join(os.path.abspath(os.path.dirname(__file__)), "version.txt")) as f: version = f.read().rstrip() -install_requires = ["arrow", "mar", "scriptworker", "taskcluster", "mohawk", "winsign", "macholib"] +with open(os.path.join(os.path.abspath(os.path.dirname(__file__)), "requirements", "base.in")) as f: + install_requires = ["scriptworker_client"] + f.readlines() setup( name="signingscript", diff --git a/signingscript/src/signingscript/apple.py b/signingscript/src/signingscript/apple.py new file mode 100644 index 000000000..4c86f0c61 --- /dev/null +++ b/signingscript/src/signingscript/apple.py @@ -0,0 +1,42 @@ +import logging +import os +from shutil import copy2 + +from signingscript.exceptions import SigningScriptError + +log = logging.getLogger(__name__) + + +PROVISIONING_PROFILE_FILENAMES = { + "firefox": "orgmozillafirefox.provisionprofile", + "devedition": "orgmozillafirefoxdeveloperedition.provisionprofile", + "nightly": "orgmozillanightly.provisionprofile", +} + + +def copy_provisioning_profiles(bundlepath, configs): + """Copy provisioning profiles inside bundle + Args: + bundlepath (str): The absolute path to the app bundle + configs (list): The list of configs with schema [{"profile_name": str, "target_path": str}] + """ + for cfg in configs: + profile_name = cfg.get("profile_name") + target_path = cfg.get("target_path") + if not profile_name or not target_path: + raise SigningScriptError(f"profile_name and target_path are required. Got: {cfg}") + + if profile_name not in PROVISIONING_PROFILE_FILENAMES.values(): + raise SigningScriptError(f"profile_name not allowed: {profile_name}") + + profile_path = os.path.join(os.path.dirname(__file__), "data", profile_name) + if not os.path.exists(profile_path): + raise SigningScriptError(f"Provisioning profile not found: {profile_name}") + + # Resolve absolute destination path + target_abs_path = os.path.join(bundlepath, target_path if target_path[0] != "/" else target_path[1:]) + if os.path.exists(target_abs_path): + log.warning("Provisioning profile at {target_path} already exists, overriding.") + + log.info(f"Copying {profile_name} to {target_abs_path}") + copy2(profile_path, target_abs_path) diff --git a/signingscript/src/signingscript/data/orgmozillanightly.provisionprofile b/signingscript/src/signingscript/data/orgmozillanightly.provisionprofile new file mode 100644 index 0000000000000000000000000000000000000000..32e0606ee493e71ff0c5a0c726e2897d9088f2c7 GIT binary patch literal 12436 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 literal 0 HcmV?d00001 diff --git a/signingscript/src/signingscript/rcodesign.py b/signingscript/src/signingscript/rcodesign.py index 479fb7cd8..60b0d1586 100644 --- a/signingscript/src/signingscript/rcodesign.py +++ b/signingscript/src/signingscript/rcodesign.py @@ -1,8 +1,14 @@ #!/usr/bin/env python """Functions that interface with rcodesign""" import asyncio +from collections import namedtuple import logging +import os import re +from glob import glob + +from scriptworker_client.aio import download_file, raise_future_exceptions, retry_async +from scriptworker_client.exceptions import DownloadError from signingscript.exceptions import SigningScriptError log = logging.getLogger(__name__) @@ -41,13 +47,14 @@ async def _execute_command(command): stderr = (await proc.stderr.readline()).decode("utf-8").rstrip() if stderr: # Unfortunately a lot of outputs from rcodesign come out to stderr - log.warn(stderr) + log.warning(stderr) output_lines.append(stderr) exitcode = await proc.wait() log.info("exitcode {}".format(exitcode)) return exitcode, output_lines + def find_submission_id(logs): """Given notarization logs, find and return the submission id Args: @@ -128,6 +135,7 @@ async def rcodesign_check_result(logs): raise RCodesignError("Notarization failed!") return + async def rcodesign_staple(path): """Staples a given app Args: @@ -146,3 +154,134 @@ async def rcodesign_staple(path): if exitcode > 0: raise RCodesignError(f"Error stapling notarization. Exit code {exitcode}") return + + +def _create_empty_entitlements_file(dest): + contents = """ + + + + + + """.lstrip() + with open(dest, "wt") as fd: + fd.writelines(contents) + + +async def _download_entitlements(hardened_sign_config, workdir): + """Download entitlements listed in the hardened signing config + Args: + hardened_sign_config (list): hardened signing configs + workdir (str): current work directory where entitlements will be saved + + Returns: + Map of url -> local file location + """ + empty_file = os.path.join(workdir, "0-empty.xml") + _create_empty_entitlements_file(empty_file) + # rcodesign requires us to specify an "empty" entitlements file + url_map = {None: empty_file} + + # Unique urls to be downloaded + urls_to_download = set([i["entitlements"] for i in hardened_sign_config if "entitlements" in i]) + # If nothing found, skip + if not urls_to_download: + log.warn("No entitlements urls provided! Skipping download.") + return url_map + + futures = [] + for index, url in enumerate(urls_to_download, start=1): + # Prefix filename with an index in case filenames are the same + filename = "{}-{}".format(index, url.split("/")[-1]) + dest = os.path.join(workdir, filename) + url_map[url] = dest + log.info(f"Downloading resource: {filename} from {url}") + futures.append( + asyncio.ensure_future( + retry_async( + download_file, + retry_exceptions=(DownloadError, TimeoutError), + args=(url, dest), + attempts=5, + ) + ) + ) + await raise_future_exceptions(futures) + return url_map + + +EntitlementEntry = namedtuple( + "EntitlementEntry", + ["file", "entitlement", "runtime"], +) + +def _get_entitlements_args(hardened_sign_config, path, entitlements_map): + """Builds the list of entitlements based on files in path + + Args: + hardened_sign_config (list): hardened signing configuration + path (str): path to app + """ + entries = [] + + for config in hardened_sign_config: + entitlement_path = entitlements_map.get(config.get("entitlements")) + for path_glob in config["globs"]: + separator = "" + if not path_glob.startswith("/"): + separator = "/" + # Join incoming glob with root of app path + full_path_glob = path + separator + path_glob + for binary_path in glob(full_path_glob, recursive=True): + # Get relative path + relative_path = os.path.relpath(binary_path, path) + # Append ":" to list of args + entries.append( + EntitlementEntry( + file=relative_path, + entitlement=entitlement_path, + runtime=config.get("runtime"), + ) + ) + + return entries + + +async def rcodesign_sign(workdir, path, creds_path, creds_pass_path, hardened_sign_config=[]): + """Signs a given app + Args: + workdir (str): Path to work directory + path (str): Path to be signed + creds_path (str): Path to credentials file + creds_pass_path (str): Path to credentials password file + hardened_sign_config (list): Hardened signing configuration + + Returns: + (Tuple) exit code, log lines + """ + # TODO: Validate and sanitize input + command = [ + "rcodesign", + "sign", + "--code-signature-flags=runtime", + f"--p12-file={creds_path}", + f"--p12-password-file={creds_pass_path}", + ] + + entitlements_map = await _download_entitlements(hardened_sign_config, workdir) + file_entitlements = _get_entitlements_args(hardened_sign_config, path, entitlements_map) + + def _scoped_arg(arg, basepath, value): + if basepath == ".": + return f"--{arg}={value}" + return f"--{arg}={basepath}:{value}" + + for entry in file_entitlements: + if entry.runtime: + flags_arg = _scoped_arg("code-signature-flags", entry.file, "runtime") + command.append(flags_arg) + entitlement_arg = _scoped_arg("entitlements-xml-path", entry.file, entry.entitlement) + command.append(entitlement_arg) + + command.append(path) + await _execute_command(command) diff --git a/signingscript/src/signingscript/script.py b/signingscript/src/signingscript/script.py index 99b8f6a6b..8e23c5602 100755 --- a/signingscript/src/signingscript/script.py +++ b/signingscript/src/signingscript/script.py @@ -1,16 +1,17 @@ #!/usr/bin/env python """Signing script.""" +import base64 +import json import logging import os +from dataclasses import asdict import aiohttp -import json import scriptworker.client -from dataclasses import asdict -from signingscript.task import build_filelist_dict, sign, task_signing_formats, task_cert_type -from signingscript.utils import copy_to_dir, load_apple_notarization_configs, load_autograph_configs from signingscript.exceptions import SigningScriptError +from signingscript.task import build_filelist_dict, sign, task_cert_type, task_signing_formats +from signingscript.utils import copy_to_dir, load_apple_notarization_configs, load_apple_signing_configs, load_autograph_configs, unlink log = logging.getLogger(__name__) @@ -40,6 +41,11 @@ async def async_main(context): raise Exception("Apple notarization is enabled but apple_notarization_configs is not defined") setup_apple_notarization_credentials(context) + if "apple_hardened_signing" in all_signing_formats: + if not context.config.get("apple_signing_configs", False): + raise Exception("Apple signing is enabled but apple_signing_configs is not defined") + setup_apple_signing_credentials(context) + context.session = session context.autograph_configs = load_autograph_configs(context.config["autograph_configs"]) @@ -83,6 +89,14 @@ def get_default_config(base_dir=None): return default_config +def _write_text(path, contents): + with open(path, "wb") as fd: + if isinstance(contents, str): + fd.write(contents.encode("ascii")) + else: + fd.write(contents) + + def setup_apple_notarization_credentials(context): """Writes the notarization credential to a file @@ -93,6 +107,7 @@ def setup_apple_notarization_credentials(context): """ cert_type = task_cert_type(context) apple_notarization_configs = load_apple_notarization_configs(context.config["apple_notarization_configs"]) + if cert_type not in apple_notarization_configs: raise SigningScriptError("Credentials not found for scope: %s" % cert_type) scope_credentials = apple_notarization_configs.get(cert_type) @@ -101,15 +116,60 @@ def setup_apple_notarization_credentials(context): context.apple_credentials_path = os.path.join( os.path.dirname(context.config["apple_notarization_configs"]), - 'apple_api_key.json', + "apple_api_key.json", ) if os.path.exists(context.apple_credentials_path): # TODO: If we have different api keys for each product, this needs to overwrite every task: return # Convert dataclass to dict so json module can read it credential = asdict(scope_credentials[0]) - with open(context.apple_credentials_path, 'wb') as credfile: - credfile.write(json.dumps(credential).encode("ascii")) + _write_text(context.apple_credentials_path, json.dumps(credential)) + + +def setup_apple_signing_credentials(context): + """Writes the signing p12 file and password to a file + + Adds properties to context: apple_credentials_path + apple_credentials_pass_path + + Args: + context: Running task Context + """ + cert_type = task_cert_type(context) + + apple_signing_configs = load_apple_signing_configs(context.config["apple_signing_configs"]) + if cert_type not in apple_signing_configs: + raise SigningScriptError("Credentials not found for scope: %s" % cert_type) + scope_credentials = apple_signing_configs.get(cert_type) + if len(scope_credentials) != 1: + raise SigningScriptError("There should only be 1 scope credential, %s found." % len(scope_credentials)) + + context.apple_app_signing_creds_path = os.path.join( + os.path.dirname(context.config["apple_signing_configs"]), + "apple_app_signing_creds.p12", + ) + unlink(context.apple_app_signing_creds_path) + context.apple_installer_signing_creds_path = os.path.join( + os.path.dirname(context.config["apple_signing_configs"]), + "apple_installer_signing_creds.p12", + ) + unlink(context.apple_installer_signing_creds_path) + context.apple_signing_creds_pass_path = os.path.join( + os.path.dirname(context.config["apple_signing_configs"]), + "apple_signing_creds_pass.passwd", + ) + unlink(context.apple_signing_creds_pass_path) + + # Convert dataclass to dict so json module can read it + creds_config = asdict(scope_credentials[0]) + _write_text(context.apple_app_signing_creds_path, base64.b64decode(creds_config["app_credentials"])) + + # Defaults to using the app credentials (ie: on Try) + if creds_config.get("installer_credentials"): + _write_text(context.apple_installer_signing_creds_path, base64.b64decode(creds_config["installer_credentials"])) + else: + context.apple_installer_signing_creds_path = context.apple_app_signing_creds_path + + _write_text(context.apple_signing_creds_pass_path, creds_config["password"]) def main(): diff --git a/signingscript/src/signingscript/sign.py b/signingscript/src/signingscript/sign.py index aadb1a8aa..dfb7dc6c0 100644 --- a/signingscript/src/signingscript/sign.py +++ b/signingscript/src/signingscript/sign.py @@ -30,9 +30,10 @@ from winsign.crypto import load_pem_certs from signingscript import task, utils +from signingscript.apple import copy_provisioning_profiles from signingscript.createprecomplete import generate_precomplete from signingscript.exceptions import SigningScriptError -from signingscript.rcodesign import RCodesignError, rcodesign_notarize, rcodesign_notary_wait, rcodesign_staple +from signingscript.rcodesign import RCodesignError, rcodesign_notarize, rcodesign_notary_wait, rcodesign_sign, rcodesign_staple log = logging.getLogger(__name__) @@ -1510,14 +1511,6 @@ async def sign_debian_pkg(context, path, fmt, *args, **kwargs): return path -def _can_notarize(filename, supported_extensions): - """ - Check if file can be notarized based on extension - """ - _, extension = os.path.splitext(filename) - return extension in supported_extensions - - async def _notarize_single(path, creds_path, staple=True): """Notarizes a single app/pkg retrying if necessary""" ATTEMPTS = 5 @@ -1553,7 +1546,7 @@ async def _notarize_pkg(context, path, workdir): workdir_files = os.listdir(workdir) # Filter supported file extensions - supported_files = [filename for filename in workdir_files if _can_notarize(filename, (".pkg",))] + supported_files = [filename for filename in workdir_files if filename.endswith(".pkg")] if not supported_files: raise SigningScriptError("No supported files found") @@ -1587,7 +1580,7 @@ async def _notarize_all(context, path, workdir): # Filter supported file extensions # We also support .pkg in case it's a tarball with .app + .pkg inside - supported_files = [filename for filename in workdir_files if _can_notarize(filename, (".app", ".pkg"))] + supported_files = [filename for filename in workdir_files if filename.endswith((".app", ".pkg"))] if not supported_files: raise SigningScriptError("No supported files found") @@ -1615,8 +1608,7 @@ async def apple_notarize(context, path, *args, **kwargs): shutil.rmtree(notarization_workdir, ignore_errors=True) utils.mkdir(notarization_workdir) - _, extension = os.path.splitext(path) - if extension == ".pkg": + if path.endswith(".pkg"): return await _notarize_pkg(context, path, notarization_workdir) else: return await _notarize_all(context, path, notarization_workdir) @@ -1633,3 +1625,71 @@ async def apple_notarize_geckodriver(context, path, *args, **kwargs): utils.mkdir(notarization_workdir) return await _notarize_geckodriver(context, path, notarization_workdir) + + +@time_async_function +async def apple_app_hardened_sign(context, path, *args, **kwargs): + """ + Sign an app using rcodesign. + """ + # Setup workdir + signing_dir = os.path.join(context.config["work_dir"], "extracted") + shutil.rmtree(signing_dir, ignore_errors=True) + utils.mkdir(signing_dir) + + if not path.endswith((".dmg", ".tar.gz")): + raise SigningScriptError("File format not supported.") + + extension = os.path.splitext(path)[-1] + # For now, we convert to tar, then continue work as tar + if extension == ".dmg": + await utils.extract_dmg(context, path, signing_dir) + else: + await _extract_tarfile(context, path, extension, signing_dir) + + # Get configs from task payload + payload = context.task.get("payload", {}) + hardened_sign_config = payload.get("hardened-sign-config") + assert hardened_sign_config and isinstance(hardened_sign_config, list) + provisioning_profile_config = payload.get("provisioning-profile-config") + + signed = False + for file in os.scandir(signing_dir): + if file.is_dir() and file.name.endswith(".app"): + # Developer ID Application certificate + creds = context.apple_app_signing_creds_path + elif file.is_file() and file.name.endswith(".pkg"): + # Use installer credentials + creds = context.apple_installer_signing_creds_path + else: + # If not pkg AND not a directory (.app) - then skip file + continue + + bundle_path = os.path.join(signing_dir, file.path) + if provisioning_profile_config: + copy_provisioning_profiles(bundle_path, provisioning_profile_config) + + # TODO: widevine and omnija signing should run from formats? + for f in glob.glob(os.path.join(bundle_path, "**", "omni.ja")): + sign_omnija_with_autograph(context, f) + widevine_files = _get_widevine_signing_files(glob.glob(os.path.join(bundle_path, "**", "*"))) + for f, fmt in widevine_files.items(): # We should make _get_widevine_signing_files return a list + sign_widevine_with_autograph(context, f, "blessed" in fmt) + await rcodesign_sign( + context.config["work_dir"], + bundle_path, + creds, + context.apple_signing_creds_pass_path, + hardened_sign_config, + ) + signed = True + if not signed: + raise SigningScriptError("Could not find an app to sign!") + # get all files from extracted folder (account for background, etc) + all_files = glob.glob(os.path.join(signing_dir, "**", "*"), recursive=True) + glob.glob(os.path.join(signing_dir, ".*")) + # filter for *non folders* so _create_tarfile doesn't include files multiple times + all_files = set([f for f in all_files if not os.path.isdir(f)]) + target = os.path.join(context.config["work_dir"], "public/build", "target.tar.gz") + if not os.path.exists(os.path.dirname(target)): + os.mkdir(os.path.dirname(target)) + return await _create_tarfile(context, target, all_files, "gz", signing_dir) diff --git a/signingscript/src/signingscript/task.py b/signingscript/src/signingscript/task.py index 493e3ebc3..266a8c36b 100644 --- a/signingscript/src/signingscript/task.py +++ b/signingscript/src/signingscript/task.py @@ -15,6 +15,7 @@ from scriptworker.utils import get_single_item_from_sequence from signingscript.sign import ( + apple_app_hardened_sign, apple_notarize, apple_notarize_geckodriver, sign_authenticode, @@ -39,6 +40,7 @@ "gpg": sign_gpg, "autograph_gpg": sign_gpg_with_autograph, "macapp": sign_macapp, + "apple_hardened_signing": apple_app_hardened_sign, "widevine": sign_widevine, "autograph_debsign": sign_debian_pkg, "autograph_widevine": sign_widevine, diff --git a/signingscript/src/signingscript/utils.py b/signingscript/src/signingscript/utils.py index 5ca757f69..46f42e775 100644 --- a/signingscript/src/signingscript/utils.py +++ b/signingscript/src/signingscript/utils.py @@ -28,11 +28,21 @@ class Autograph: @dataclass class AppleNotarization: """Apple notarization configuration object.""" + issuer_id: str key_id: str private_key: str +@dataclass +class AppleSigning: + """Apple signing configuration object.""" + + app_credentials: str + installer_credentials: str + password: str + + def mkdir(path): """Equivalent to `mkdir -p`. @@ -47,6 +57,20 @@ def mkdir(path): pass +def unlink(path): + """Equivalent to rm -f {file} + Ignores FileNotFound errors (as rm -f would) + + Args: + path (str): the path to remove + """ + try: + os.unlink(path) + log.info(f"removed {path}") + except FileNotFoundError: + pass + + def get_hash(path, hash_type="sha512"): """Get the hash of a given path. @@ -97,7 +121,7 @@ def _load_scoped_configs(filename, cls, name): for scope, config in raw_cfg.items(): if cls == Autograph: scope_configs[scope] = [cls(*s) for s in config] - elif cls == AppleNotarization: + elif cls in (AppleNotarization, AppleSigning): scope_configs[scope] = [cls(**s) for s in config] else: raise SigningScriptError("Unknown class for scoped configs: %s" % cls.__name__) @@ -131,6 +155,19 @@ def load_apple_notarization_configs(filename): return _load_scoped_configs(filename, AppleNotarization, "Apple Notarization") +def load_apple_signing_configs(filename): + """Load the apple notarization configuration from `filename`. + + Args: + filename (str): config file + + Returns: + dict of Apple Notarization objects: keyed by signing cert type + + """ + return _load_scoped_configs(filename, AppleSigning, "Apple Signing") + + async def log_output(fh, log_level=logging.INFO): """Log the output from an async generator. @@ -238,3 +275,22 @@ def split_autograph_format(format_): return format_.split(":", 1) else: return format_, None + + +async def extract_dmg(context, source, dest): + """Extracts a source DMG into dest folder + + Args: + context: The running task context object + source (str): the DMG sorce path + dest (str): the destination directory to extract files + """ + dmg = context.config["dmg"] + hfsplus = context.config["hfsplus"] + undmg_cmd = [dmg, "extract", source, "tmp.hfs"] + log.info(undmg_cmd) + await execute_subprocess(undmg_cmd, cwd=context.config["work_dir"], log_level=logging.DEBUG) + + hfsplus_cmd = [hfsplus, "tmp.hfs", "extractall", "/", dest] + log.info(hfsplus_cmd) + await execute_subprocess(hfsplus_cmd, cwd=context.config["work_dir"], log_level=logging.DEBUG) diff --git a/signingscript/tests/conftest.py b/signingscript/tests/conftest.py index df7844961..5e785e29e 100644 --- a/signingscript/tests/conftest.py +++ b/signingscript/tests/conftest.py @@ -19,6 +19,7 @@ def read_file(path): BASE_DIR = os.path.dirname(os.path.dirname(__file__)) SERVER_CONFIG_PATH = os.path.join(os.path.dirname(__file__), "example_server_config.json") APPLE_CONFIG_PATH = os.path.join(os.path.dirname(__file__), "example_apple_notarization_config.json") +APPLE_SIGNING_CONFIG_PATH = os.path.join(os.path.dirname(__file__), "example_apple_signing_config.json") DEFAULT_SCOPE_PREFIX = "project:releng:signing:" TEST_CERT_TYPE = f"{DEFAULT_SCOPE_PREFIX}cert:dep-signing" TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), "data") @@ -55,8 +56,12 @@ def context(tmpdir): context.config["artifact_dir"] = os.path.join(tmpdir, "artifact") context.config["taskcluster_scope_prefixes"] = [DEFAULT_SCOPE_PREFIX] context.config["apple_notarization_configs"] = APPLE_CONFIG_PATH + context.config["apple_signing_configs"] = APPLE_CONFIG_PATH context.autograph_configs = load_autograph_configs(SERVER_CONFIG_PATH) - context.apple_credentials_path = "fakepath" + context.apple_credentials_path = os.path.join(tmpdir, "fakepath") + context.apple_app_signing_creds_path = os.path.join(tmpdir, "apple_app.p12") + context.apple_installer_signing_creds_path = os.path.join(tmpdir, "apple_installer.p12") + context.apple_signing_creds_path = os.path.join(tmpdir, "apple_p12.passwd") mkdir(context.config["work_dir"]) mkdir(context.config["artifact_dir"]) context.task = {"scopes": [TEST_CERT_TYPE]} diff --git a/signingscript/tests/data/test.dmg b/signingscript/tests/data/test.dmg new file mode 100644 index 0000000000000000000000000000000000000000..2970bc111fae346c228251cd06d2992c8e0a9686 GIT binary patch literal 17644 zcmeI2dsq`!7QhogMR^EcRaCY(KrOh60fLGYfrRjgJcS^IZjlfYz=R~7NrWJ^MBNo% zwXLWqK3E^*9;>#ZsEa5FRwFx;*UVr7MA)>hlRqYR?mg$u znR9;UzLIP*CwbzCKyR~`ir!x9{7Lep>ledL`_tpeq=u2^hqK9$^a;ycY&nLVoSd2u zU)&Q~{VYPsGMl3t?da2K*OdP<7#wePNx&1iXc2zd{VXfmB6Y@B-+IuP2dE;h`w5?bi^WjPRh~;bZ3#*n|w;xTPll|UC zmuT_YYSXescgBY2By5ShG9mNJgz}uE*0mLUs*KfLQYsK$t@Ca<(|Kn9+K;X0wie!W ziE7~O`ZcTA76`~Akxk6ZZH7|#%%Y4u?dn(#Y;OaNKQ8_cq({9~C3Sz9y}GV*VIySf zSU$mI_56<76}4xkjtd%l!X}JKnVJdRrTug4%>|DqS!U1ZH0=bQksK_Reo@(5)X*eM z=B#tPb*tU2S0-vM>b~QDZtJBQhO3!*?g5kfEh&pXIM@SnW&0*R=7CL|3qq>4+!0ptDmRvtu4DYE>W7Y!e^~LCVZWVrgu}K&uZ1Z#(i19%A zrSiKM7FJn*;6?a<$fLnq3gJMI5pEg!L__$H@ZnGvDg-|SKLkHS77$rLWC4){Z*~^Q zSHE+>$!Du%VZ`<+$6NR8{PF39br$y{_lmBj4etk_t zMct^lg5DS0b8G(AGfj9w(YU#r{IE!#^I4j-d`kSbW?rnK=wJKtyX<I*J|ha&gMtHF~eJ==Q9{rQfU z=d^49&n|N?-P7XG`pG|@tlxR>r|MBl6^h-Si8WnWU{cq6H#n^uBD2#T=8i9@KkMz= za{oW^ryzUhtP)qNoh2Swyu&km%C2zQ!)4pnNS}M{n6clpw5(xr)x7GB@joU0;3}%B z^q*dxXNBG6)g=D=CaX26wJ7r1<+dXSDYq89+~e@F*Z)5B(XKa}5$szMJNw_iH{@3> z%1pl7B1=S0KL2V(ayKW@B&BfvslS9m|~JM;YdydavVrRDblmIb3s^UVuZgmd#tq>YR0 zj#$~6ZXNNxI9A-Y;($wl=ko2%q!=^EBLDp<#oMy%({28IXIen+kLLk1uds3Xw9aA@ zDg3xi*PHi$jlO?Y5qm`>neCmp%BY4;{Ycf9g%6(0S9eO_CDcg5;O<3rak zr#YCATw-i*`}${R3Viv?T?g~4I~(c#Qk76A7_p#()b0Z!=>iP(oi$;!%_ z$ws7RazvSkAVi4FAQdmawrMro#71i$|x#3v$>rr&uhBuG?e{-jtXId zf-kB=r~;iHmkCl4Qu_Jmig`cc#?A}_L8qf&vv>x9PKPjWZ3yVP22MSkW2hMvNycS7 znhi=aB=Fn_AcHiXbrw5Cz=g+j&tX6v1rja6zE^{&9@BA6n8;v?IMnAam>ZaYY1CDG z!%Xw@{?d!?X_dz=WdD2#s5&Xch1U zb%<1pk|zdMTq5bIP=v5w03+5W^0=1 z3o|uE27`|jHL}WT^%FdleX0btQ(w9e6Ecmts7Wg6$P|^S$elKh%tUnUq*UN3gN5H> zG2&4nnkJZmOirICFp&9(qI#I-s*@#UV@9Y(2L4v|1gDX9U#NeJK^=V74l-Mem%f^$ zRZl;&hMcvLT4XRWMf{2jjedC15U3SYS<dFX5h`Ukq(AuEIdm4}P!AOvfaU&gnxa9>2QQcXT#~FBL2I#+v=Y>|x+qGt9u}JsAILxK`~K=(r}V z7+S`0{nqUluv{CqUkD73K%Hn1*RuxC_3QCuT;4T@Kp4)|RX)I+p@S|(LDx>oh~w4V zszJw$PME0Ria5{{f~m2B0kXrm<1x-weK%N>3_Am2La2*aOLT0E^&WNxMzAsF7_u>* zZ5ZeVfP@n6OVJ+hE0;uK0VL6$yAJ!&KXL@5?HxH{)vm`dE*h|ijpBg9hybB57&j4K z`mMYKul>+bnxJ(sVIaKpf8!D4ob>|i;hBY@#`v_glDk*hRz ePq|{`2V) 1 assert output == ["hello", "err"] + + +@pytest.mark.asyncio +async def test_rcodesign_sign(context, mocker): + + workdir = Path(context.config["work_dir"]) + app_path = workdir / "test.app" + app_path.mkdir() + (app_path / "samplefile").touch() + (app_path / "samplefile2").touch() + context.apple_app_signing_creds_path = workdir / "test_cred.p12" + context.apple_signing_creds_pass_path = workdir / "test_cred.passwd" + entitlement_file = workdir / "test.xml" + entitlement_file.touch() + + hardened_sign_config = [ + { + "entitlements": "https://fakeurl", + "runtime": True, + "globs": [ + "/*" + ] + } + ] + + download = mock.AsyncMock() + download.side_effect = [{"https://fakeurl": str(entitlement_file)}] + mocker.patch.object(rcodesign, "_download_entitlements", download) + execute = mock.AsyncMock() + execute.side_effect = lambda x: x + mocker.patch.object(rcodesign, "_execute_command", execute) + + await rcodesign.rcodesign_sign( + context.config["work_dir"], + str(app_path), + context.apple_app_signing_creds_path, + context.apple_signing_creds_pass_path, + hardened_sign_config, + ) + download.assert_called_once() + execute.assert_called_once() diff --git a/signingscript/tox.ini b/signingscript/tox.ini index 8f458eaae..3daba081d 100644 --- a/signingscript/tox.ini +++ b/signingscript/tox.ini @@ -14,14 +14,19 @@ commands = [testenv] usedevelop = true depends = clean +skip_install = true setenv = PYTHONDONTWRITEBYTECODE=1 - PYTHONPATH = {toxinidir}/tests + PYTHONPATH = {toxinidir}/tests:{toxinidir}/../scriptworker_client/src deps= py38: -r requirements/test.py38.txt + -r {toxinidir}/../scriptworker_client/requirements/test.py38.txt py39: -r requirements/test.txt + -r {toxinidir}/../scriptworker_client/requirements/test.txt commands = + python -I -m pip install {toxinidir}/../scriptworker_client + python -I -m pip install -e {toxinidir} {posargs:py.test --cov-config=tox.ini --cov-append --cov={toxinidir}/src/signingscript --cov-report term-missing tests} [testenv:clean] diff --git a/tox.ini b/tox.ini index 35c177cb6..bfa1bccbb 100644 --- a/tox.ini +++ b/tox.ini @@ -26,7 +26,6 @@ envlist = scriptworker_client-py39 shipitscript-py38 shipitscript-py39 - signingscript-py38 signingscript-py39 treescript-py38 treescript-py39 @@ -193,11 +192,6 @@ changedir = {toxinidir}/shipitscript commands = tox -e py39 -[testenv:signingscript-py38] -changedir = {toxinidir}/signingscript -commands = - tox -e py38 - [testenv:signingscript-py39] changedir = {toxinidir}/signingscript commands = @@ -218,6 +212,6 @@ commands = [testenv:ruff-py39] deps = ruff -commands = +commands = ruff --version - ruff --verbose {toxinidir} \ No newline at end of file + ruff --verbose {toxinidir} From 98cc8ba27f14c88d1f1bf4b4b700fec309f9d901 Mon Sep 17 00:00:00 2001 From: Heitor Neiva Date: Fri, 8 Dec 2023 14:12:49 -0800 Subject: [PATCH 2/2] PR changes --- signingscript/Dockerfile | 8 ++----- .../docker.d/apple_signing_creds.yml | 18 +++++++------- ...uild_rcodesign.sh => install_rcodesign.sh} | 0 .../data/orgmozillafirefox.provisionprofile | Bin 0 -> 13185 bytes ...lafirefoxdeveloperedition.provisionprofile | Bin 0 -> 12503 bytes signingscript/src/signingscript/script.py | 22 +++++++++--------- signingscript/src/signingscript/sign.py | 7 +++--- signingscript/src/signingscript/utils.py | 6 ++--- signingscript/tests/conftest.py | 4 ++-- .../tests/example_apple_signing_config.json | 6 ++--- signingscript/tests/test_rcodesign.py | 8 +++---- 11 files changed, 38 insertions(+), 41 deletions(-) rename signingscript/docker.d/{build_rcodesign.sh => install_rcodesign.sh} (100%) create mode 100644 signingscript/src/signingscript/data/orgmozillafirefox.provisionprofile create mode 100644 signingscript/src/signingscript/data/orgmozillafirefoxdeveloperedition.provisionprofile diff --git a/signingscript/Dockerfile b/signingscript/Dockerfile index 0e8b94175..e53ff7ebf 100644 --- a/signingscript/Dockerfile +++ b/signingscript/Dockerfile @@ -24,13 +24,9 @@ COPY ["version.jso[n]", "/app/"] # Install msix # Install rcodesign RUN chown -R app:app /app \ - && cd /app/scriptworker_client \ - && pip install /app/scriptworker_client \ - && pip install -r requirements/base.txt \ - && pip install . \ && cd /app/signingscript/docker.d \ && bash build_libdmg_hfsplus.sh /usr/bin \ - && bash build_rcodesign.sh /usr/bin \ + && bash install_rcodesign.sh /usr/bin \ && bash build_msix_packaging.sh # Set user and workdir @@ -39,8 +35,8 @@ WORKDIR /app # Install signingscript + configloader + widevine RUN python -m venv /app \ - && cd signingscript \ && /app/bin/pip install /app/scriptworker_client \ + && cd signingscript \ && /app/bin/pip install -r requirements/base.txt \ && /app/bin/pip install . \ && python -m venv /app/configloader_venv \ diff --git a/signingscript/docker.d/apple_signing_creds.yml b/signingscript/docker.d/apple_signing_creds.yml index 457441a03..64432a5df 100644 --- a/signingscript/docker.d/apple_signing_creds.yml +++ b/signingscript/docker.d/apple_signing_creds.yml @@ -10,15 +10,15 @@ in: $match: 'ENV == "prod" && scope_prefix': '${scope_prefix[0]}cert:release-signing': - - "app_credentials": {"$eval": "APPLE_APP_SIGNING_CREDENTIALS"} - "installer_credentials": {"$eval": "APPLE_INSTALLER_SIGNING_CREDENTIALS"} - "password": {"$eval": "APPLE_SIGNING_CREDS_PASSWORD"} + - "app_pkcs12_bundle": {"$eval": "APPLE_APP_SIGNING_PKCS12"} + "installer_pkcs12_bundle": {"$eval": "APPLE_INSTALLER_SIGNING_PKCS12"} + "pkcs12_password": {"$eval": "APPLE_SIGNING_PKCS12_PASSWORD"} '${scope_prefix[0]}cert:nightly-signing': - - "app_credentials": {"$eval": "APPLE_APP_SIGNING_CREDENTIALS"} - "installer_credentials": {"$eval": "APPLE_INSTALLER_SIGNING_CREDENTIALS"} - "password": {"$eval": "APPLE_SIGNING_CREDS_PASSWORD"} + - "app_pkcs12_bundle": {"$eval": "APPLE_APP_SIGNING_PKCS12"} + "installer_pkcs12_bundle": {"$eval": "APPLE_INSTALLER_SIGNING_PKCS12"} + "pkcs12_password": {"$eval": "APPLE_SIGNING_PKCS12_PASSWORD"} 'ENV != "prod" && scope_prefix': '${scope_prefix[0]}cert:dep-signing': - - "app_credentials": {"$eval": "APPLE_APP_SIGNING_DEP_CREDENTIALS"} - "installer_credentials": {"$eval": "APPLE_INSTALLER_SIGNING_DEP_CREDENTIALS"} - "password": {"$eval": "APPLE_SIGNING_DEP_CREDS_PASSWORD"} + - "app_pkcs12_bundle": {"$eval": "APPLE_APP_SIGNING_DEP_PKCS12"} + "installer_pkcs12_bundle": {"$eval": "APPLE_INSTALLER_SIGNING_DEP_PKCS12"} + "pkcs12_password": {"$eval": "APPLE_SIGNING_DEP_PKCS12_PASSWORD"} diff --git a/signingscript/docker.d/build_rcodesign.sh b/signingscript/docker.d/install_rcodesign.sh similarity index 100% rename from signingscript/docker.d/build_rcodesign.sh rename to signingscript/docker.d/install_rcodesign.sh diff --git a/signingscript/src/signingscript/data/orgmozillafirefox.provisionprofile b/signingscript/src/signingscript/data/orgmozillafirefox.provisionprofile new file mode 100644 index 0000000000000000000000000000000000000000..e1c4920fc0669df0da99835665194062c524bf60 GIT binary patch literal 13185 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 literal 0 HcmV?d00001 diff --git a/signingscript/src/signingscript/data/orgmozillafirefoxdeveloperedition.provisionprofile b/signingscript/src/signingscript/data/orgmozillafirefoxdeveloperedition.provisionprofile new file mode 100644 index 0000000000000000000000000000000000000000..26da37f7782a8d857a7118fa35d5738aa86905d1 GIT binary patch literal 12503 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 Y?l>^RGGeIv?gzhLzBKs3c;D9l0(#_vvj6}9 literal 0 HcmV?d00001 diff --git a/signingscript/src/signingscript/script.py b/signingscript/src/signingscript/script.py index 8e23c5602..a60a3991d 100755 --- a/signingscript/src/signingscript/script.py +++ b/signingscript/src/signingscript/script.py @@ -143,33 +143,33 @@ def setup_apple_signing_credentials(context): if len(scope_credentials) != 1: raise SigningScriptError("There should only be 1 scope credential, %s found." % len(scope_credentials)) - context.apple_app_signing_creds_path = os.path.join( + context.apple_app_signing_pkcs12_path = os.path.join( os.path.dirname(context.config["apple_signing_configs"]), "apple_app_signing_creds.p12", ) - unlink(context.apple_app_signing_creds_path) - context.apple_installer_signing_creds_path = os.path.join( + unlink(context.apple_app_signing_pkcs12_path) + context.apple_installer_signing_pkcs12_path = os.path.join( os.path.dirname(context.config["apple_signing_configs"]), "apple_installer_signing_creds.p12", ) - unlink(context.apple_installer_signing_creds_path) - context.apple_signing_creds_pass_path = os.path.join( + unlink(context.apple_installer_signing_pkcs12_path) + context.apple_signing_pkcs12_pass_path = os.path.join( os.path.dirname(context.config["apple_signing_configs"]), "apple_signing_creds_pass.passwd", ) - unlink(context.apple_signing_creds_pass_path) + unlink(context.apple_signing_pkcs12_pass_path) # Convert dataclass to dict so json module can read it creds_config = asdict(scope_credentials[0]) - _write_text(context.apple_app_signing_creds_path, base64.b64decode(creds_config["app_credentials"])) + _write_text(context.apple_app_signing_pkcs12_path, base64.b64decode(creds_config["app_pkcs12_bundle"])) # Defaults to using the app credentials (ie: on Try) - if creds_config.get("installer_credentials"): - _write_text(context.apple_installer_signing_creds_path, base64.b64decode(creds_config["installer_credentials"])) + if creds_config.get("installer_pkcs12_bundle"): + _write_text(context.apple_installer_signing_pkcs12_path, base64.b64decode(creds_config["installer_pkcs12_bundle"])) else: - context.apple_installer_signing_creds_path = context.apple_app_signing_creds_path + context.apple_installer_signing_pkcs12_path = context.apple_app_signing_pkcs12_path - _write_text(context.apple_signing_creds_pass_path, creds_config["password"]) + _write_text(context.apple_signing_pkcs12_pass_path, creds_config["pkcs12_password"]) def main(): diff --git a/signingscript/src/signingscript/sign.py b/signingscript/src/signingscript/sign.py index dfb7dc6c0..f16ce5f42 100644 --- a/signingscript/src/signingscript/sign.py +++ b/signingscript/src/signingscript/sign.py @@ -1657,12 +1657,13 @@ async def apple_app_hardened_sign(context, path, *args, **kwargs): for file in os.scandir(signing_dir): if file.is_dir() and file.name.endswith(".app"): # Developer ID Application certificate - creds = context.apple_app_signing_creds_path + creds = context.apple_app_signing_pkcs12_path elif file.is_file() and file.name.endswith(".pkg"): # Use installer credentials - creds = context.apple_installer_signing_creds_path + creds = context.apple_installer_signing_pkcs12_path else: # If not pkg AND not a directory (.app) - then skip file + log.info(f"Skipping unsupported file at root: {file.path}") continue bundle_path = os.path.join(signing_dir, file.path) @@ -1679,7 +1680,7 @@ async def apple_app_hardened_sign(context, path, *args, **kwargs): context.config["work_dir"], bundle_path, creds, - context.apple_signing_creds_pass_path, + context.apple_signing_pkcs12_pass_path, hardened_sign_config, ) signed = True diff --git a/signingscript/src/signingscript/utils.py b/signingscript/src/signingscript/utils.py index 46f42e775..26e51d3bf 100644 --- a/signingscript/src/signingscript/utils.py +++ b/signingscript/src/signingscript/utils.py @@ -38,9 +38,9 @@ class AppleNotarization: class AppleSigning: """Apple signing configuration object.""" - app_credentials: str - installer_credentials: str - password: str + app_pkcs12_bundle: str + installer_pkcs12_bundle: str + pkcs12_password: str def mkdir(path): diff --git a/signingscript/tests/conftest.py b/signingscript/tests/conftest.py index 5e785e29e..79cd744dd 100644 --- a/signingscript/tests/conftest.py +++ b/signingscript/tests/conftest.py @@ -59,8 +59,8 @@ def context(tmpdir): context.config["apple_signing_configs"] = APPLE_CONFIG_PATH context.autograph_configs = load_autograph_configs(SERVER_CONFIG_PATH) context.apple_credentials_path = os.path.join(tmpdir, "fakepath") - context.apple_app_signing_creds_path = os.path.join(tmpdir, "apple_app.p12") - context.apple_installer_signing_creds_path = os.path.join(tmpdir, "apple_installer.p12") + context.apple_app_signing_pkcs12_path = os.path.join(tmpdir, "apple_app.p12") + context.apple_installer_signing_pkcs12_path = os.path.join(tmpdir, "apple_installer.p12") context.apple_signing_creds_path = os.path.join(tmpdir, "apple_p12.passwd") mkdir(context.config["work_dir"]) mkdir(context.config["artifact_dir"]) diff --git a/signingscript/tests/example_apple_signing_config.json b/signingscript/tests/example_apple_signing_config.json index 1ce2d7fa7..cedc23862 100644 --- a/signingscript/tests/example_apple_signing_config.json +++ b/signingscript/tests/example_apple_signing_config.json @@ -1,7 +1,7 @@ { "project:releng:signing:cert:dep-signing": [{ - "app_credentials": "abcdef", - "installer_credentials": "abcdef", - "password": "verysecret" + "app_pkcs12_bundle": "abcdef", + "installer_pkcs12_bundle": "abcdef", + "pkcs12_password": "verysecret" }] } diff --git a/signingscript/tests/test_rcodesign.py b/signingscript/tests/test_rcodesign.py index b42e642bf..1ed0f80b5 100644 --- a/signingscript/tests/test_rcodesign.py +++ b/signingscript/tests/test_rcodesign.py @@ -179,8 +179,8 @@ async def test_rcodesign_sign(context, mocker): app_path.mkdir() (app_path / "samplefile").touch() (app_path / "samplefile2").touch() - context.apple_app_signing_creds_path = workdir / "test_cred.p12" - context.apple_signing_creds_pass_path = workdir / "test_cred.passwd" + context.apple_app_signing_pkcs12_path = workdir / "test_cred.p12" + context.apple_signing_pkcs12_pass_path = workdir / "test_cred.passwd" entitlement_file = workdir / "test.xml" entitlement_file.touch() @@ -204,8 +204,8 @@ async def test_rcodesign_sign(context, mocker): await rcodesign.rcodesign_sign( context.config["work_dir"], str(app_path), - context.apple_app_signing_creds_path, - context.apple_signing_creds_pass_path, + context.apple_app_signing_pkcs12_path, + context.apple_signing_pkcs12_pass_path, hardened_sign_config, ) download.assert_called_once()