blob: 3e8acfec54e1405c25ac229f1f40e8df8a8ef685 [file] [log] [blame]
# Copyright 2019 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os.path
from .model import Distribution, NotarizationTool
class ConfigError(Exception):
def __init__(self, attr_name):
super(Exception, self).__init__(
'Missing CodeSignConfig attribute "{}"'.format(attr_name))
class CodeSignConfig(object):
"""Code sign base configuration object.
A CodeSignConfig contains properties that provide path component information
to locate products for code signing and options that control the code
signing process.
There is a class hierarchy of CodeSignConfig objects, with the
build_props_config.BuildPropsConfig containing injected variables from the
build process. Configs for Chromium and Google Chrome subclass that to
control signing options further. And then derived configurations are
created for internal signing artifacts and when using |model.Distribution|
objects.
"""
def __init__(self,
identity=None,
installer_identity=None,
notary_user=None,
notary_password=None,
notary_asc_provider=None,
notary_team_id=None,
codesign_requirements_basic='',
notarization_tool=None):
"""Creates a CodeSignConfig that will sign the product using the static
properties on the class, using the code signing identity passed to the
constructor.
Args:
identity: The name of the code signing identity to use for non-PKG
files. This can be any value that `codesign -s <identity>`
accepts, like the hex-encoded SHA1 hash of the certificate. Must
not be None.
installer_identity: The name of the code signing identity to use for
PKG files. This will be passed as the parameter for the call to
`productbuild --sign <identity>`. Note that a hex-encoded SHA1
hash is not a valid option, as it is for |identity| above. The
common name of the cert will work. If there is any distribution
that is packaged in a PKG this must not be None.
notary_user: Optional string username that will be used to
authenticate to Apple's notary service if notarizing.
notary_password: Optional string password or password reference
(e.g. @keychain, see `xcrun altool -h`) that will be used to
authenticate to Apple's notary service if notarizing.
notary_asc_provider: Optional string that will be used as the
`--asc-provider` argument to `xcrun altool`, to be used when
notary_user is associated with multiple Apple developer teams.
codesign_requirements_basic: Optional string to specify the default
basic `codesign --requirements`.
notary_team_id: String for the Apple Team ID to use when notarizing.
Mandatory when using the notarytool `notarization_tool`, ignored
otherwise.
notarization_tool: The tool to use to communicate with the Apple
notary service. If None, the config will choose a default.
"""
assert identity is not None
assert type(identity) is str
self._identity = identity
self._installer_identity = installer_identity
self._notary_user = notary_user
self._notary_password = notary_password
self._notary_asc_provider = notary_asc_provider
self._codesign_requirements_basic = codesign_requirements_basic
self._notary_team_id = notary_team_id
self._notarization_tool = notarization_tool
@staticmethod
def is_chrome_branded():
"""Returns True if the build is an official Google Chrome build and
should use Chrome-specific resources.
This is a @staticmethod and not a @property so that it can be tested
during the process of creating a CodeSignConfig object.
"""
raise ConfigError('is_chrome_branded')
@property
def enable_updater(self):
"""Returns True if the build should use updater-related resources.
"""
raise ConfigError('enable_updater')
@property
def identity(self):
"""Returns the code signing identity that will be used to sign the
products, everything but PKG files.
"""
return self._identity
@property
def installer_identity(self):
"""Returns the code signing identity that will be used to sign the
PKG file products.
"""
return self._installer_identity
@property
def notary_user(self):
"""Returns the username for authenticating to Apple's notary service."""
return self._notary_user
@property
def notary_password(self):
"""Returns the password or password reference for authenticating to
Apple's notary service.
"""
return self._notary_password
@property
def notary_asc_provider(self):
"""Returns the ASC provider for authenticating to Apple's notary service
when notary_user is associatetd with multiple Apple developer teams.
"""
return self._notary_asc_provider
@property
def notary_team_id(self):
"""Returns the Apple Developer Team ID for authenticating to Apple's
notary service. Mandatory when notarization_tool is `NOTARYTOOL`.
"""
return self._notary_team_id
@property
def notarization_tool(self):
"""Returns the name of the tool to use for communicating with Apple's
notary service. The values are from the signing.model.NotarizationTool
enum.
"""
return self._notarization_tool or NotarizationTool.ALTOOL
@property
def notarization_tool_path(self):
"""Returns the path to the notarization tool binary, or None if this
Config does not override the default. The default is to invoke the tool
via xcrun(1). If a Config does override this value, it must be
appropriate for the active Config.notarization_tool.
"""
return None
@property
def app_product(self):
"""Returns the product name that is used for the outer .app bundle.
This is displayed to the user in Finder.
"""
raise ConfigError('app_product')
@property
def product(self):
"""Returns the branding product name. This can match |app_product|
for some release channels. Other release channels may customize
app_product, but components internal to the app bundle will still
refer to |product|. This is used to locate the build products from
the build system, while |app_product| is used when customizing for
|model.Distribution| objects.
"""
raise ConfigError('product')
@property
def version(self):
"""Returns the version of the application."""
raise ConfigError('version')
@property
def base_bundle_id(self):
"""Returns the base CFBundleIdentifier that is used for the outer app
bundle, and to which sub-component identifiers are appended.
"""
raise ConfigError('base_bundle_id')
@property
def codesign_requirements_basic(self):
"""Returns the codesign --requirements string that is combined with
a designated identifier requirement string of a
|model.CodeSignedProduct|. This requirement is applied to all
CodeSignedProducts.
"""
return self._codesign_requirements_basic
@property
def codesign_requirements_outer_app(self):
"""Returns the codesign --requirements string for the outer app bundle.
This is used in conjunction with |codesign_requirements_basic|."""
return ''
@property
def provisioning_profile_basename(self):
"""Returns the basename of the provisioning profile used to sign the
outer app bundle. This file with a .provisionprofile extension is
located in the |packaging_dir|.
"""
raise ConfigError('provisioning_profile_basename')
@property
def packaging_basename(self):
"""Returns the file basename of the packaged output files."""
return '{}-{}'.format(self.app_product.replace(' ', ''), self.version)
@property
def distributions(self):
"""Returns a list of |model.Distribution| objects that customize the
results of signing. This must contain at least one Distribution, which
can be a default Distribution.
"""
return [Distribution()]
@property
def run_spctl_assess(self):
"""Returns whether the final code signed binary should be assessed by
Gatekeeper after signing.
"""
return True
@property
def inject_get_task_allow_entitlement(self):
"""Returns whether the com.apple.security.get-task-allow entitlement
should be added to all entitlement files. This will permit attaching a
debugger to a signed process, if the binary was signed with the
hardened runtime.
"""
return False
# Computed Properties ######################################################
@property
def app_dir(self):
"""Returns the path to the outer app bundle directory."""
return '{.app_product}.app'.format(self)
@property
def resources_dir(self):
"""Returns the path to the outer app's Resources directory."""
return os.path.join(self.app_dir, 'Contents', 'Resources')
@property
def framework_dir(self):
"""Returns the path to the app's framework directory."""
return '{0.app_dir}/Contents/Frameworks/{0.product} Framework.framework'.format(
self)
@property
def packaging_dir(self):
"""Returns the path to the packaging and installer tools."""
return '{.product} Packaging'.format(self)