1#!/usr/bin/env python 2# Copyright 2019 The Chromium Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6import argparse 7import os 8import sys 9 10sys.path.append(os.path.dirname(__file__)) 11 12from signing import config_factory, commands, logger, model, pipeline 13 14 15def _link_stdout_and_stderr(): 16 """This script's output is entirely log messages and debugging information, 17 so there is not a useful distinction between stdout and stderr. Because some 18 subcommands this script runs output to one stream or the other, link the 19 two streams so that any buffering done by Python, or the invoker of this 20 script, does not get incorrectly interleaved. 21 """ 22 stdout_fileno = sys.stdout.fileno() 23 sys.stdout.close() 24 sys.stdout = sys.stderr 25 os.dup2(sys.stderr.fileno(), stdout_fileno) 26 27 28def create_config(config_args, development): 29 """Creates the |model.CodeSignConfig| for the signing operations. 30 31 If |development| is True, the config will be modified to not require 32 restricted internal assets, nor will the products be required to match 33 specific certificate hashes. 34 35 Args: 36 config_args: List of args to expand to the config class's constructor. 37 development: Boolean indicating whether or not to modify the chosen 38 config for development testing. 39 40 Returns: 41 An instance of |model.CodeSignConfig|. 42 """ 43 config_class = config_factory.get_class() 44 45 if development: 46 47 class DevelopmentCodeSignConfig(config_class): 48 49 @property 50 def codesign_requirements_basic(self): 51 return '' 52 53 @property 54 def provisioning_profile_basename(self): 55 return None 56 57 @property 58 def run_spctl_assess(self): 59 # Self-signed or ad-hoc signed signing identities won't pass 60 # spctl assessment so don't do it. 61 return False 62 63 config_class = DevelopmentCodeSignConfig 64 65 return config_class(*config_args) 66 67 68def _show_tool_versions(): 69 logger.info('Showing macOS and tool versions.') 70 commands.run_command(['sw_vers']) 71 commands.run_command(['xcodebuild', '-version']) 72 commands.run_command(['xcrun', '-show-sdk-path']) 73 74 75def main(): 76 parser = argparse.ArgumentParser( 77 description='Code sign and package Chrome for channel distribution.') 78 parser.add_argument( 79 '--identity', 80 required=True, 81 help='The identity to sign everything but PKGs with.') 82 parser.add_argument( 83 '--installer-identity', help='The identity to sign PKGs with.') 84 parser.add_argument( 85 '--notary-user', 86 help='The username used to authenticate to the Apple notary service.') 87 parser.add_argument( 88 '--notary-password', 89 help='The password or password reference (e.g. @keychain, see ' 90 '`xcrun altool -h`) used to authenticate to the Apple notary service.') 91 parser.add_argument( 92 '--notary-asc-provider', 93 help='The ASC provider string to be used as the `--asc-provider` ' 94 'argument to `xcrun altool`, to be used when --notary-user is ' 95 'associated with multiple Apple developer teams. See `xcrun altool -h. ' 96 'Run `iTMSTransporter -m provider -account_type itunes_connect -v off ' 97 '-u USERNAME -p PASSWORD` to list valid providers.') 98 parser.add_argument( 99 '--development', 100 action='store_true', 101 help='The specified identity is for development. Certain codesign ' 102 'requirements will be omitted.') 103 parser.add_argument( 104 '--input', 105 required=True, 106 help='Path to the input directory. The input directory should ' 107 'contain the products to sign, as well as the Packaging directory.') 108 parser.add_argument( 109 '--output', 110 required=True, 111 help='Path to the output directory. The signed (possibly packaged) ' 112 'products and installer tools will be placed here.') 113 parser.add_argument( 114 '--disable-packaging', 115 action='store_true', 116 help='Disable creating any packaging (.dmg/.pkg) specified by the ' 117 'configuration.') 118 parser.add_argument( 119 '--skip-brand', 120 dest='skip_brands', 121 action='append', 122 default=[], 123 help='Causes any distribution whose brand code matches to be skipped.') 124 125 group = parser.add_mutually_exclusive_group(required=False) 126 group.add_argument( 127 '--notarize', 128 dest='notarize', 129 action='store_true', 130 help='Defaults to False. Submit the signed application and DMG to ' 131 'Apple for notarization.') 132 group.add_argument('--no-notarize', dest='notarize', action='store_false') 133 134 _link_stdout_and_stderr() 135 136 parser.set_defaults(notarize=False) 137 args = parser.parse_args() 138 139 if args.notarize: 140 if not args.notary_user or not args.notary_password: 141 parser.error('The --notary-user and --notary-password arguments ' 142 'are required with --notarize.') 143 144 config = create_config( 145 (args.identity, args.installer_identity, args.notary_user, 146 args.notary_password, args.notary_asc_provider), args.development) 147 paths = model.Paths(args.input, args.output, None) 148 149 if not os.path.exists(paths.output): 150 os.mkdir(paths.output) 151 152 _show_tool_versions() 153 154 pipeline.sign_all( 155 paths, 156 config, 157 disable_packaging=args.disable_packaging, 158 do_notarization=args.notarize, 159 skip_brands=args.skip_brands) 160 161 162if __name__ == '__main__': 163 main() 164