Commit 1390f8a0 authored by Robert Sesek's avatar Robert Sesek Committed by Commit Bot

macOS Signing Scripts: Code sign options should be properties of parts, not config.

The options used to code sign parts are integral to their function, and
so they do not belong as options of the config. Instead, they should be
associated with the CodeSignedProduct part that is being signed.

This also removes the `-o library` option to the Helper application,
which was accidentally added during the transition to the new scripts.
The Helper is not yet ready for library validation, since it currently
loads Flash which is signed by a different Team ID.

Bug: 964673, 958163
Change-Id: Iefc8dfb56decc94f6618d4d27fd4c0daae9a059b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1618274Reviewed-by: default avatarMark Mentovai <mark@chromium.org>
Commit-Queue: Robert Sesek <rsesek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#661229}
parent fd3e5657
...@@ -96,25 +96,6 @@ class CodeSignConfig(object): ...@@ -96,25 +96,6 @@ class CodeSignConfig(object):
# build signing. # build signing.
return set(('libwidevinecdm.dylib',)) return set(('libwidevinecdm.dylib',))
@property
def codesign_options_outer_app(self):
"""Returns the codesign -o flags for the outer app bundle."""
return 'restrict'
@property
def codesign_options_helpers(self):
"""Returns the codesign -o flags for helper executables within the
bundle.
"""
return self.codesign_options_outer_app + ',library'
@property
def codesign_options_installer_tools(self):
"""Returns the codesign -o flags for the installer tools, which
are not shipped to end-users.
"""
return self.codesign_options_helpers + ',kill'
@property @property
def codesign_requirements_basic(self): def codesign_requirements_basic(self):
"""Returns the codesign --requirements string that is combined with """Returns the codesign --requirements string that is combined with
......
...@@ -30,8 +30,8 @@ class CodeSignedProduct(object): ...@@ -30,8 +30,8 @@ class CodeSignedProduct(object):
identifier: The unique identifier set when code signing. This is identifier: The unique identifier set when code signing. This is
only explicitly passed with the `--identifier` flag if only explicitly passed with the `--identifier` flag if
|sign_with_identifier| is True. |sign_with_identifier| is True.
options: Comma-separated string of option names passed to the options: Options flags to pass to `codesign --options`, from
`codesign -o` flag. |CodeSignOptions|.
requirements: String for additional `--requirements` to pass to the requirements: String for additional `--requirements` to pass to the
`codesign` command. These are joined with a space to the `codesign` command. These are joined with a space to the
|config.CodeSignConfig.codesign_requirements_basic| string. See |config.CodeSignConfig.codesign_requirements_basic| string. See
...@@ -53,6 +53,8 @@ class CodeSignedProduct(object): ...@@ -53,6 +53,8 @@ class CodeSignedProduct(object):
""" """
self.path = path self.path = path
self.identifier = identifier self.identifier = identifier
if not CodeSignOptions.valid(options):
raise ValueError('Invalid CodeSignOptions: {}'.format(options))
self.options = options self.options = options
self.requirements = requirements self.requirements = requirements
self.identifier_requirement = identifier_requirement self.identifier_requirement = identifier_requirement
...@@ -88,23 +90,23 @@ class CodeSignedProduct(object): ...@@ -88,23 +90,23 @@ class CodeSignedProduct(object):
'options={0.options}, path={0.path})'.format(self) 'options={0.options}, path={0.path})'.format(self)
class VerifyOptions(object): def make_enum(class_name, options):
"""Enum for the options that can be specified when validating the results of """Makes a new class type for an enum.
code signing.
These options are passed to `codesign --verify` after the Args:
|CodeSignedProduct| has been signed. class_name: Name of the new type to make.
""" options: A dictionary of enum options to use. The keys will become
DEEP = ('--deep',) attributes on the class, and the values will be wrapped in a tuple
NO_STRICT = ('--no-strict',) so that the options can be joined together.
IGNORE_RESOURCES = ('--ignore-resources',)
def __init__(self): Returns:
raise TypeError('VerifyOptions cannot be constructed') A new class for the enum.
"""
attrs = {}
@classmethod @classmethod
def valid(cls, options): def valid(cls, opts_to_check):
"""Tests if the specified |options| are valid. """Tests if the specified |opts_to_check| are valid.
Args: Args:
options: Iterable of option strings. options: Iterable of option strings.
...@@ -112,10 +114,41 @@ class VerifyOptions(object): ...@@ -112,10 +114,41 @@ class VerifyOptions(object):
Returns: Returns:
True if all the options are valid, False if otherwise. True if all the options are valid, False if otherwise.
""" """
if options is None: if opts_to_check is None:
return True return True
all_options = cls.DEEP + cls.NO_STRICT + cls.IGNORE_RESOURCES valid_values = options.values()
return all([option in all_options for option in options]) return all([option in valid_values for option in opts_to_check])
attrs['valid'] = valid
for name, value in options.items():
assert type(name) is str
assert type(value) is str
attrs[name] = (value,)
return type(class_name, (object,), attrs)
"""Enum for the options that can be specified when validating the results of
code signing.
These options are passed to `codesign --verify` after the
|CodeSignedProduct| has been signed.
"""
VerifyOptions = make_enum(
'signing.model.VerifyOptions', {
'DEEP': '--deep',
'NO_STRICT': '--no-strict',
'IGNORE_RESOURCES': '--ignore-resources',
})
CodeSignOptions = make_enum(
'signing.model.CodeSignOptions', {
'RESTRICT': 'restrict',
'LIBRARY_VALIDATION': 'library',
'HARDENED_RUNTIME': 'runtime',
'KILL': 'kill',
})
class Distribution(object): class Distribution(object):
......
...@@ -10,7 +10,7 @@ import copy ...@@ -10,7 +10,7 @@ import copy
import os.path import os.path
from . import commands from . import commands
from .model import CodeSignedProduct, VerifyOptions from .model import CodeSignOptions, CodeSignedProduct, VerifyOptions
_PROVISIONPROFILE_EXT = '.provisionprofile' _PROVISIONPROFILE_EXT = '.provisionprofile'
_PROVISIONPROFILE_DEST = 'embedded.provisionprofile' _PROVISIONPROFILE_DEST = 'embedded.provisionprofile'
...@@ -39,7 +39,7 @@ def get_parts(config): ...@@ -39,7 +39,7 @@ def get_parts(config):
CodeSignedProduct( CodeSignedProduct(
'{.app_product}.app'.format(config), '{.app_product}.app'.format(config),
config.base_bundle_id, config.base_bundle_id,
options=config.codesign_options_outer_app, options=CodeSignOptions.RESTRICT,
requirements=config.codesign_requirements_outer_app, requirements=config.codesign_requirements_outer_app,
identifier_requirement=False, identifier_requirement=False,
resource_rules=None if config.use_new_mac_bundle_structure else resource_rules=None if config.use_new_mac_bundle_structure else
...@@ -58,14 +58,16 @@ def get_parts(config): ...@@ -58,14 +58,16 @@ def get_parts(config):
.format(config), .format(config),
'{}.framework.AlertNotificationService'.format( '{}.framework.AlertNotificationService'.format(
config.base_bundle_id), config.base_bundle_id),
options=config.codesign_options_helpers, options=CodeSignOptions.RESTRICT +
CodeSignOptions.LIBRARY_VALIDATION,
verify_options=VerifyOptions.DEEP), verify_options=VerifyOptions.DEEP),
'crashpad': 'crashpad':
CodeSignedProduct( CodeSignedProduct(
'{.framework_dir}/Helpers/chrome_crashpad_handler'.format( '{.framework_dir}/Helpers/chrome_crashpad_handler'.format(
config), config),
'chrome_crashpad_handler', 'chrome_crashpad_handler',
options=config.codesign_options_helpers, options=CodeSignOptions.RESTRICT +
CodeSignOptions.LIBRARY_VALIDATION,
verify_options=VerifyOptions.DEEP), verify_options=VerifyOptions.DEEP),
'helper-app': 'helper-app':
CodeSignedProduct( CodeSignedProduct(
...@@ -74,13 +76,14 @@ def get_parts(config): ...@@ -74,13 +76,14 @@ def get_parts(config):
'{0.app_product}.app/Contents/Versions/{0.version}/{0.product} Helper.app' '{0.app_product}.app/Contents/Versions/{0.version}/{0.product} Helper.app'
).format(config), ).format(config),
'{}.helper'.format(uncustomized_bundle_id), '{}.helper'.format(uncustomized_bundle_id),
options=config.codesign_options_helpers, options=CodeSignOptions.RESTRICT,
verify_options=VerifyOptions.DEEP), verify_options=VerifyOptions.DEEP),
'app-mode-app': 'app-mode-app':
CodeSignedProduct( CodeSignedProduct(
'{.framework_dir}/Helpers/app_mode_loader'.format(config), '{.framework_dir}/Helpers/app_mode_loader'.format(config),
'app_mode_loader', 'app_mode_loader',
options=config.codesign_options_helpers, options=CodeSignOptions.RESTRICT +
CodeSignOptions.LIBRARY_VALIDATION,
verify_options=VerifyOptions.IGNORE_RESOURCES), verify_options=VerifyOptions.IGNORE_RESOURCES),
} }
...@@ -122,12 +125,11 @@ def get_installer_tools(config): ...@@ -122,12 +125,11 @@ def get_installer_tools(config):
'xzdec', 'xzdec',
) )
for binary in binaries: for binary in binaries:
options = config.codesign_options_installer_tools if not binary.endswith( options = CodeSignOptions.RESTRICT + CodeSignOptions.LIBRARY_VALIDATION + CodeSignOptions.KILL
'.dylib') else None
tools[binary] = CodeSignedProduct( tools[binary] = CodeSignedProduct(
'{.packaging_dir}/{binary}'.format(config, binary=binary), '{.packaging_dir}/{binary}'.format(config, binary=binary),
binary.replace('.dylib', ''), binary.replace('.dylib', ''),
options=options, options=options if not binary.endswith('dylib') else None,
verify_options=VerifyOptions.DEEP) verify_options=VerifyOptions.DEEP)
return tools return tools
...@@ -151,7 +153,7 @@ def sign_part(paths, config, part): ...@@ -151,7 +153,7 @@ def sign_part(paths, config, part):
if config.keychain: if config.keychain:
command.extend(['--keychain', config.keychain]) command.extend(['--keychain', config.keychain])
if part.options: if part.options:
command.extend(['--options', part.options]) command.extend(['--options', ','.join(part.options)])
if part.resource_rules: if part.resource_rules:
command.extend([ command.extend([
'--resource-rules', '--resource-rules',
......
...@@ -58,6 +58,27 @@ class TestGetParts(unittest.TestCase): ...@@ -58,6 +58,27 @@ class TestGetParts(unittest.TestCase):
all_parts['helper-app'].identifier) all_parts['helper-app'].identifier)
def test_part_options(self):
parts = signing.get_parts(test_config.TestConfig())
self.assertEqual(
set(model.CodeSignOptions.RESTRICT), set(parts['app'].options))
self.assertEqual(
set(model.CodeSignOptions.RESTRICT),
set(parts['helper-app'].options))
self.assertEqual(
set(model.CodeSignOptions.RESTRICT +
model.CodeSignOptions.LIBRARY_VALIDATION),
set(parts['crashpad'].options))
self.assertEqual(
set(model.CodeSignOptions.RESTRICT +
model.CodeSignOptions.LIBRARY_VALIDATION),
set(parts['notification-xpc'].options))
self.assertEqual(
set(model.CodeSignOptions.RESTRICT +
model.CodeSignOptions.LIBRARY_VALIDATION),
set(parts['app-mode-app'].options))
@mock.patch('signing.commands.run_command') @mock.patch('signing.commands.run_command')
class TestSignPart(unittest.TestCase): class TestSignPart(unittest.TestCase):
...@@ -117,7 +138,10 @@ class TestSignPart(unittest.TestCase): ...@@ -117,7 +138,10 @@ class TestSignPart(unittest.TestCase):
def test_sign_part_with_options(self, run_command): def test_sign_part_with_options(self, run_command):
part = model.CodeSignedProduct( part = model.CodeSignedProduct(
'Test.app', 'test.signing.app', options='restrict,library') 'Test.app',
'test.signing.app',
options=model.CodeSignOptions.RESTRICT +
model.CodeSignOptions.LIBRARY_VALIDATION)
signing.sign_part(self.paths, self.config, part) signing.sign_part(self.paths, self.config, part)
run_command.assert_called_once_with([ run_command.assert_called_once_with([
'codesign', '--sign', '[IDENTITY]', '--requirements', 'codesign', '--sign', '[IDENTITY]', '--requirements',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment