def run_signing_pipeline(self): """ Run the full signing pipeline starting from the point when buildbot worker have requested signing. """ # Make sure storage directory exists. self.signed_storage_dir.mkdir(parents=True, exist_ok=True) with TemporaryDirectory(prefix='blender-codesign-') as temp_dir_str: temp_dir = Path(temp_dir_str) logger_server.info('Extracting unsigned files from archive...') extract_files( archive_filepath=self.unsigned_archive_info.archive_filepath, extraction_dir=temp_dir) logger_server.info('Collecting all files which needs signing...') files = AbsoluteAndRelativeFileName.recursively_from_directory( temp_dir) logger_server.info('Signing all requested files...') self.sign_all_files(files) logger_server.info('Packing signed files...') pack_files( files=files, archive_filepath=self.signed_archive_info.archive_filepath) self.signed_archive_info.tag_ready() logger_server.info('Removing signing request...') self.unsigned_archive_info.clean() logger_server.info('Signing is complete.')
def codesign_bundles( self, files: List[AbsoluteAndRelativeFileName]) -> None: """ Codesign all .app bundles in the given list of files. Bundle is deducted from paths of the files, and every bundle is only signed once. """ signed_bundles = set() extra_files = [] for file in files: if not is_file_from_bundle(file): continue bundle = get_bundle_from_file(file) bundle_name = bundle.relative_filepath if bundle_name in signed_bundles: continue logger_server.info('Running codesign routines on bundle %s', bundle_name) # It is not possible to remove signature from DMG. if bundle.relative_filepath.name.endswith('.app'): self.codesign_remove_signature(bundle) self.codesign_file(bundle) signed_bundles.add(bundle_name) # Codesign on a bundle adds an extra folder with information. # It needs to be compied to the source. code_signature_directory = \ bundle.absolute_filepath / 'Contents' / '_CodeSignature' code_signature_files = \ AbsoluteAndRelativeFileName.recursively_from_directory( code_signature_directory) for code_signature_file in code_signature_files: bundle_relative_file = AbsoluteAndRelativeFileName( bundle.base_dir, code_signature_directory / code_signature_file.relative_filepath) extra_files.append(bundle_relative_file) files.extend(extra_files) return True
def collect_files_to_sign(self, path: Path) \ -> List[AbsoluteAndRelativeFileName]: # Include all files when signing app or dmg bundle: all the files are # needed to do valid signature of bundle. if path.name.endswith('.app'): return AbsoluteAndRelativeFileName.recursively_from_directory(path) if path.is_dir(): files = [] for child in path.iterdir(): if child.name.endswith('.app'): current_files = AbsoluteAndRelativeFileName.recursively_from_directory( child) else: current_files = super().collect_files_to_sign(child) for current_file in current_files: files.append(AbsoluteAndRelativeFileName( path, current_file.absolute_filepath)) return files return super().collect_files_to_sign(path)
def get_bundle_from_file( file: AbsoluteAndRelativeFileName) -> AbsoluteAndRelativeFileName: """ Get AbsoluteAndRelativeFileName descriptor of bundle """ assert(is_file_from_bundle(file)) parts = file.relative_filepath.parts bundle_name = parts[0] base_dir = file.base_dir bundle_filepath = file.base_dir / bundle_name return AbsoluteAndRelativeFileName(base_dir, bundle_filepath)
def collect_files_to_sign(self, path: Path) \ -> List[AbsoluteAndRelativeFileName]: """ Get all files which need to be signed from the given path. NOTE: The path might either be a file or directory. This function is run from the buildbot worker side. """ # If there is a single file provided trust the buildbot worker that it # is eligible for signing. if path.is_file(): file = AbsoluteAndRelativeFileName.from_path(path) if not self.check_file_is_to_be_signed(file): return [] return [file] all_files = AbsoluteAndRelativeFileName.recursively_from_directory( path) files_to_be_signed = [file for file in all_files if self.check_file_is_to_be_signed(file)] return files_to_be_signed