| # Copyright 2020 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| """ |
| The pipeline module orchestrates the entire signing process, which includes: |
| 1. Code signing the application bundle and all of its nested code. |
| 2. Producing a packaged DMG. |
| 3. Signing the DMG. |
| """ |
| |
| import os.path |
| |
| from . import commands, model, notarize, parts, signing |
| |
| |
| def _sign_app(paths, config, dest_dir): |
| """Does signing of an updater app bundle, which is moved into |dest_dir|. |
| |
| Args: |
| paths: A |model.Paths| object. |
| config: A |config.CodeSignConfig|. |
| dest_dir: The directory into which the product will be placed when |
| the operations are completed. |
| """ |
| commands.copy_files(os.path.join(paths.input, config.app_dir), paths.work) |
| commands.copy_files(os.path.join(paths.input, "UpdaterSetup"), paths.work) |
| parts.sign_all(paths, config) |
| commands.make_dir(dest_dir) |
| commands.move_file(os.path.join(paths.work, config.app_dir), |
| os.path.join(dest_dir, config.app_dir)) |
| commands.move_file(os.path.join(paths.work, "UpdaterSetup"), |
| os.path.dirname(dest_dir)) |
| |
| |
| def _package_and_sign_dmg(paths, config): |
| """Packages, signs, and verifies a DMG for a signed build product. |
| |
| Args: |
| paths: A |model.Paths| object. |
| config: The |config.CodeSignConfig| object. |
| |
| Returns: |
| The path to the signed DMG file. |
| """ |
| dmg_path = _package_dmg(paths, config) |
| product = model.CodeSignedProduct(dmg_path, |
| config.packaging_basename, |
| sign_with_identifier=True) |
| signing.sign_part(paths, config, product) |
| signing.verify_part(paths, product) |
| return dmg_path |
| |
| |
| def _package_dmg(paths, config): |
| """Packages an Updater application bundle into a DMG. |
| |
| Args: |
| paths: A |model.Paths| object. |
| config: The |config.CodeSignConfig| object. |
| |
| Returns: |
| A path to the produced DMG file. |
| """ |
| dmg_path = os.path.join(paths.output, |
| '{}.dmg'.format(config.packaging_basename)) |
| app_path = os.path.join(paths.work, config.app_dir) |
| empty_dir = os.path.join(paths.work, 'empty') |
| commands.make_dir(empty_dir) |
| pkg_dmg = [ |
| os.path.join(paths.input, config.packaging_dir, 'signing', 'pkg-dmg'), |
| '--verbosity', |
| '0', |
| '--tempdir', |
| paths.work, |
| '--source', |
| empty_dir, |
| '--target', |
| dmg_path, |
| '--format', |
| 'UDBZ', |
| '--volname', |
| config.app_product, |
| '--copy', |
| '{}:/'.format(app_path), |
| '--copy', |
| '{}/chrome/updater/.install:/.keystone_install'.format(paths.input), |
| ] |
| commands.run_command(pkg_dmg) |
| return dmg_path |
| |
| |
| def _package_zip(paths, config): |
| """Packages an Updater application bundle into a ZIP. |
| |
| Args: |
| paths: A |model.Paths| object. |
| config: The |config.CodeSignConfig| object. |
| |
| Returns: |
| A path to the produced ZIP file. |
| """ |
| zip_path = os.path.join(paths.output, |
| '{}.zip'.format(config.packaging_basename)) |
| prep_dir = os.path.join(paths.work, 'zip_prep') |
| commands.make_dir(prep_dir) |
| commands.copy_files(os.path.join(paths.work, config.app_dir), prep_dir) |
| commands.copy_files('{}/chrome/updater/.install'.format(paths.input), |
| prep_dir) |
| commands.zip(zip_path, prep_dir) |
| return zip_path |
| |
| |
| def sign_all(orig_paths, |
| config, |
| disable_packaging=False, |
| skip_brands=[], |
| channels=[]): |
| """Code signs, packages, and signs the package, placing the result into |
| |orig_paths.output|. |orig_paths.input| must contain the products to |
| customize and sign. |
| |
| Args: |
| orig_paths: A |model.Paths| object. |
| config: The |config.CodeSignConfig| object. |
| disable_packaging: Ignored. |
| skip_brands: Ignored. |
| channels: Ignored. |
| """ |
| with commands.WorkDirectory(orig_paths) as notary_paths: |
| # First, sign and optionally submit the notarization requests. |
| uuid = None |
| with commands.WorkDirectory(orig_paths) as paths: |
| dest_dir = os.path.join(notary_paths.work, |
| config.packaging_basename) |
| _sign_app(paths, config, dest_dir) |
| |
| if config.notarize.should_notarize(): |
| zip_file = os.path.join(notary_paths.work, |
| config.packaging_basename + '.zip') |
| commands.run_command([ |
| 'zip', '--recurse-paths', '--symlinks', '--quiet', |
| zip_file, config.app_dir |
| ], |
| cwd=dest_dir) |
| uuid = notarize.submit(zip_file, config) |
| |
| # Wait for the app notarization result to come back and staple. |
| if config.notarize.should_wait(): |
| for _ in notarize.wait_for_results([uuid], config): |
| pass # We are only waiting for a single notarization. |
| if config.notarize.should_staple(): |
| notarize.staple_bundled_parts( |
| # Only staple to the outermost app. |
| parts.get_parts(config)[-1:], |
| notary_paths.replace_work( |
| os.path.join(notary_paths.work, |
| config.packaging_basename))) |
| |
| # Package. |
| commands.move_file(os.path.join(notary_paths.work, "UpdaterSetup"), |
| orig_paths.output) |
| package_paths = orig_paths.replace_work( |
| os.path.join(notary_paths.work, config.packaging_basename)) |
| _package_zip(package_paths, config) |
| dmg_path = _package_and_sign_dmg(package_paths, config) |
| |
| # Notarize the package, then staple. |
| if config.notarize.should_wait(): |
| for _ in notarize.wait_for_results( |
| [notarize.submit(dmg_path, config)], config): |
| pass # We are only waiting for a single notarization. |
| if config.notarize.should_staple(): |
| notarize.staple(dmg_path) |