From afb5f81ca052fcc49906dac36675d966d1a581d4 Mon Sep 17 00:00:00 2001 From: Matt Hardcastle Date: Thu, 20 Jun 2019 15:35:47 -0700 Subject: [PATCH 1/3] Add signing to macOS Interface and HQ Launcher This change adds signing to the macOS version of Interface and HQ Launcher. By default, signing is not enabled; to enable signing you must add the `XCODE_DEVELOPMENT_TEAM` environment variable and rerun CMake. Jira: https://highfidelity.atlassian.net/browse/DEVOPS-52 --- interface/CMakeLists.txt | 16 +++++ interface/interface.entitlements | 16 +++++ launchers/darwin/CMakeLists.txt | 23 +++++- launchers/darwin/HQ Launcher.entitlements | 14 ++++ tools/ci-scripts/postbuild.py | 88 +++++++++++++++++++++-- 5 files changed, 148 insertions(+), 9 deletions(-) create mode 100644 interface/interface.entitlements create mode 100644 launchers/darwin/HQ Launcher.entitlements diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 9553b571c5..ac23264aeb 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -142,6 +142,22 @@ endif() if (APPLE) add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM}) + set_from_env(XCODE_DEVELOPMENT_TEAM XCODE_DEVELOPMENT_TEAM "") + if ("${XCODE_DEVELOPMENT_TEAM}" STREQUAL "") + message(WARNING "XCODE_DEVELOPMENT_TEAM environment variable is not set. Not signing build.") + else() + set_target_properties(${TARGET_NAME} PROPERTIES + XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/interface.entitlements" + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Developer ID Application" + XCODE_ATTRIBUTE_CODE_SIGN_INJECT_BASE_ENTITLEMENTS NO + XCODE_ATTRIBUTE_CODE_SIGN_STYLE "Manual" + XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "${XCODE_DEVELOPMENT_TEAM}" + XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME YES + XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS "--timestamp --deep" + XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER "" + ) + endif() + # make sure the output name for the .app bundle is correct # Fix up the rpath so macdeployqt works set_target_properties(${TARGET_NAME} PROPERTIES INSTALL_RPATH "@executable_path/../Frameworks") diff --git a/interface/interface.entitlements b/interface/interface.entitlements new file mode 100644 index 0000000000..22747cbc32 --- /dev/null +++ b/interface/interface.entitlements @@ -0,0 +1,16 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + com.apple.security.network.server + + com.apple.security.application-groups + + high-fidelity.hifi + + + diff --git a/launchers/darwin/CMakeLists.txt b/launchers/darwin/CMakeLists.txt index 0a7ef70461..88ac666a93 100644 --- a/launchers/darwin/CMakeLists.txt +++ b/launchers/darwin/CMakeLists.txt @@ -69,8 +69,27 @@ function(set_from_env _RESULT_NAME _ENV_VAR_NAME _DEFAULT_VALUE) endfunction() add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${src_files}) -set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${APP_NAME} - MACOSX_BUNDLE_BUNDLE_NAME ${APP_NAME}) + +set_from_env(XCODE_DEVELOPMENT_TEAM XCODE_DEVELOPMENT_TEAM "") +if ("${XCODE_DEVELOPMENT_TEAM}" STREQUAL "") + message(WARNING "XCODE_DEVELOPMENT_TEAM environmental variable is not set. Not signing build.") + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${APP_NAME} + MACOSX_BUNDLE_BUNDLE_NAME ${APP_NAME} + ) +else() + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${APP_NAME} + MACOSX_BUNDLE_BUNDLE_NAME ${APP_NAME} + XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "HQ Launcher.entitlements" + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Developer ID Application" + XCODE_ATTRIBUTE_CODE_SIGN_INJECT_BASE_ENTITLEMENTS NO + XCODE_ATTRIBUTE_CODE_SIGN_STYLE "Manual" + XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "${XCODE_DEVELOPMENT_TEAM}" + XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME YES + XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS "--timestamp" + XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER "" + ) +endif() + set_from_env(LAUNCHER_HMAC_SECRET LAUNCHER_HMAC_SECRET "") if ("${LAUNCHER_HMAC_SECRET}" STREQUAL "") message(FATAL_ERROR "LAUNCHER_HMAC_SECRET is not set") diff --git a/launchers/darwin/HQ Launcher.entitlements b/launchers/darwin/HQ Launcher.entitlements new file mode 100644 index 0000000000..0f41736b78 --- /dev/null +++ b/launchers/darwin/HQ Launcher.entitlements @@ -0,0 +1,14 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + com.apple.security.application-groups + + high-fideilty.hifi + + + diff --git a/tools/ci-scripts/postbuild.py b/tools/ci-scripts/postbuild.py index 00b3007104..949c40b0f2 100644 --- a/tools/ci-scripts/postbuild.py +++ b/tools/ci-scripts/postbuild.py @@ -2,6 +2,9 @@ import os import sys import shutil +import subprocess +import tempfile +import uuid import zipfile import base64 @@ -11,6 +14,33 @@ sys.path.append(SOURCE_PATH) import hifi_utils + +class ZipAttrs: + """ A readable wrapper for ZipInfo's external attributes bit field """ + + S_IFREG = 0x8 + S_IFLNK = 0xa + S_IFDIR = 0x4 + MODE_MASK = 0xfff0000 + + def __init__(self, zip_info): + # File stats are the 4 high bits of external_attr, a 32 bit field. + self._stat = zip_info.external_attr >> 28 + self.mode = (zip_info.external_attr & self.MODE_MASK) >> 16 + + @property + def is_symlink(self): + return self._stat == self.S_IFLNK + + @property + def is_dir(self): + return self._stat == self.S_IFDIR + + @property + def is_regular(self): + return self._stat == self.S_IFREG + + BUILD_PATH = os.path.join(SOURCE_PATH, 'build') INTERFACE_BUILD_PATH = os.path.join(BUILD_PATH, 'interface', 'Release') WIPE_PATHS = [] @@ -65,8 +95,12 @@ def fixupMacZip(filename): fullPath = os.path.join(BUILD_PATH, "{}.zip".format(filename)) outFullPath = "{}.zip".format(fullPath) print("Fixup mac ZIP file {}".format(fullPath)) - with zipfile.ZipFile(fullPath) as inzip: - with zipfile.ZipFile(outFullPath, 'w') as outzip: + tmpDir = os.path.join(tempfile.gettempdir(), + 'com.highfidelity.launcher.postbuild', + str(uuid.uuid4())) + + try: + with zipfile.ZipFile(fullPath) as inzip: rootPath = inzip.infolist()[0].filename for entry in inzip.infolist(): if entry.filename == rootPath: @@ -86,11 +120,51 @@ def fixupMacZip(filename): continue # if we made it here, include the file in the output buffer = inzip.read(entry.filename) - entry.filename = newFilename - outzip.writestr(entry, buffer) - outzip.close() - print("Replacing {} with fixed {}".format(fullPath, outFullPath)) - shutil.move(outFullPath, fullPath) + newFilename = os.path.join(tmpDir, newFilename) + + attrs = ZipAttrs(entry) + if attrs.is_dir: + os.makedirs(newFilename) + elif attrs.is_regular: + with open(newFilename, mode='wb') as _file: + _file.write(buffer) + os.chmod(newFilename, mode=attrs.mode) + elif attrs.is_symlink: + os.symlink(buffer, newFilename) + else: + raise IOError('Invalid file stat') + + if 'XCODE_DEVELOPMENT_TEAM' in os.environ: + print('XCODE_DEVELOPMENT_TEAM environment variable is not set. ' + 'Not signing build.', file=sys.stderr) + else: + # The interface.app bundle must be signed again after being + # stripped. + print('Signing interface.app bundle') + entitlementsPath = os.path.join( + os.path.dirname(__file__), + '../../interface/interface.entitlements') + subprocess.run([ + 'codesign', '-s', 'Developer ID Application', '--deep', + '--timestamp', '--force', '--entitlements', entitlementsPath, + os.path.join(tmpDir, 'interface.app') + ], check=True) + + # Repackage the zip including the signed version of interface.app + print('Replacing {} with fixed {}'.format(fullPath, outFullPath)) + if os.path.exists(outFullPath): + print('fixed zip already exists, deleting it', file=sys.stderr) + os.unlink(outFullPath) + previous_cwd = os.getcwd() + os.chdir(tmpDir) + try: + subprocess.run(['zip', '--symlink', '-r', outFullPath, './.'], + stdout=subprocess.DEVNULL, check=True) + finally: + os.chdir(previous_cwd) + + finally: + shutil.rmtree(tmpDir) def fixupWinZip(filename): fullPath = os.path.join(BUILD_PATH, "{}.zip".format(filename)) From 99991c3259665910322eefbbb42f5496dbb6a61b Mon Sep 17 00:00:00 2001 From: dante ruiz Date: Mon, 15 Jul 2019 15:48:24 -0700 Subject: [PATCH 2/3] fix signing crash --- interface/interface.entitlements | 14 ++++++++++---- launchers/darwin/HQ Launcher.entitlements | 8 ++++---- launchers/darwin/src/Launcher.m | 8 +++++++- launchers/darwin/src/main.mm | 2 +- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/interface/interface.entitlements b/interface/interface.entitlements index 22747cbc32..800200933c 100644 --- a/interface/interface.entitlements +++ b/interface/interface.entitlements @@ -4,13 +4,19 @@ com.apple.security.app-sandbox + com.apple.security.application-groups + + high-fidelity.hifi + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.device.audio-input + com.apple.security.network.client com.apple.security.network.server - com.apple.security.application-groups - - high-fidelity.hifi - diff --git a/launchers/darwin/HQ Launcher.entitlements b/launchers/darwin/HQ Launcher.entitlements index 0f41736b78..5c5393f915 100644 --- a/launchers/darwin/HQ Launcher.entitlements +++ b/launchers/darwin/HQ Launcher.entitlements @@ -4,11 +4,11 @@ com.apple.security.app-sandbox + com.apple.security.application-groups + + high-fidelity.hifi + com.apple.security.network.client - com.apple.security.application-groups - - high-fideilty.hifi - diff --git a/launchers/darwin/src/Launcher.m b/launchers/darwin/src/Launcher.m index 1a84e9143d..8e9f5a982e 100644 --- a/launchers/darwin/src/Launcher.m +++ b/launchers/darwin/src/Launcher.m @@ -226,9 +226,15 @@ static BOOL const DELETE_ZIP_FILES = TRUE; NSWorkspace* workspace = [NSWorkspace sharedWorkspace]; NSArray* apps = [workspace runningApplications]; for (NSRunningApplication* app in apps) { + NSLog(@"app: %@", [app bundleIdentifier]); if ([[app bundleIdentifier] isEqualToString:@"com.highfidelity.interface"] || [[app bundleIdentifier] isEqualToString:@"com.highfidelity.interface-pr"]) { - [app terminate]; + pid_t pid = [app processIdentifier]; + int status = kill(pid, SIGTERM); + + NSLog(@"exit status %d", status); + /*BOOL success = [app forceTerminate]; + NSLog(success ? @"SUCCESSSFUL" : @"NOT SUCCESSFUL");*/ self.waitingForInterfaceToTerminate = true; } } diff --git a/launchers/darwin/src/main.mm b/launchers/darwin/src/main.mm index b6555aad87..4d66d15549 100644 --- a/launchers/darwin/src/main.mm +++ b/launchers/darwin/src/main.mm @@ -17,7 +17,7 @@ void redirectLogToDocuments() int main(int argc, const char* argv[]) { //NSApp.appearance = [NSAppearance appearanceNamed: NSAppearanceNameAqua]; - redirectLogToDocuments(); + //redirectLogToDocuments(); NSArray* apps = [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.highfidelity.launcher"]; if ([apps count] > 1) { NSLog(@"launcher is already running"); From f3a09e015625f9ffa1788ddcd418d51405a3ead4 Mon Sep 17 00:00:00 2001 From: dante ruiz Date: Wed, 17 Jul 2019 19:31:05 -0700 Subject: [PATCH 3/3] remove debug stuff --- launchers/darwin/src/Launcher.m | 8 +------- launchers/darwin/src/main.mm | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/launchers/darwin/src/Launcher.m b/launchers/darwin/src/Launcher.m index 8e9f5a982e..1a84e9143d 100644 --- a/launchers/darwin/src/Launcher.m +++ b/launchers/darwin/src/Launcher.m @@ -226,15 +226,9 @@ static BOOL const DELETE_ZIP_FILES = TRUE; NSWorkspace* workspace = [NSWorkspace sharedWorkspace]; NSArray* apps = [workspace runningApplications]; for (NSRunningApplication* app in apps) { - NSLog(@"app: %@", [app bundleIdentifier]); if ([[app bundleIdentifier] isEqualToString:@"com.highfidelity.interface"] || [[app bundleIdentifier] isEqualToString:@"com.highfidelity.interface-pr"]) { - pid_t pid = [app processIdentifier]; - int status = kill(pid, SIGTERM); - - NSLog(@"exit status %d", status); - /*BOOL success = [app forceTerminate]; - NSLog(success ? @"SUCCESSSFUL" : @"NOT SUCCESSFUL");*/ + [app terminate]; self.waitingForInterfaceToTerminate = true; } } diff --git a/launchers/darwin/src/main.mm b/launchers/darwin/src/main.mm index 4d66d15549..b6555aad87 100644 --- a/launchers/darwin/src/main.mm +++ b/launchers/darwin/src/main.mm @@ -17,7 +17,7 @@ void redirectLogToDocuments() int main(int argc, const char* argv[]) { //NSApp.appearance = [NSAppearance appearanceNamed: NSAppearanceNameAqua]; - //redirectLogToDocuments(); + redirectLogToDocuments(); NSArray* apps = [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.highfidelity.launcher"]; if ([apps count] > 1) { NSLog(@"launcher is already running");