diff --git a/etc/evergreen_yml_components/definitions.yml b/etc/evergreen_yml_components/definitions.yml index 14f75d7b6af..bf087ddb8b3 100644 --- a/etc/evergreen_yml_components/definitions.yml +++ b/etc/evergreen_yml_components/definitions.yml @@ -2949,15 +2949,7 @@ tasks: archive-dist-test task_compile_flags: >- PREFIX=dist-test - - command: subprocess.exec - params: - binary: bash - add_expansions_to_env: true - args: - - "src/evergreen/run_python_script.sh" - - "evergreen/macos_notary.py" - - "mongodb-binaries.${ext|tgz}" - + sign_macos_archive: true - command: s3.put params: optional: true @@ -8081,14 +8073,7 @@ tasks: ${additional_package_targets|} task_compile_flags: >- --legacy-tarball - - command: subprocess.exec - params: - binary: bash - add_expansions_to_env: true - args: - - "src/evergreen/run_python_script.sh" - - "evergreen/macos_notary.py" - - "mongodb-dist.${ext|tgz}" + sign_macos_archive: true - func: "f_expansions_write" - command: subprocess.exec params: diff --git a/etc/macos_dev_entitlements.xml b/etc/macos_dev_entitlements.xml new file mode 100644 index 00000000000..3a9bdfee3c1 --- /dev/null +++ b/etc/macos_dev_entitlements.xml @@ -0,0 +1,10 @@ + + + + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.get-task-allow + + + diff --git a/etc/macos_entitlements.xml b/etc/macos_release_entitlements.xml similarity index 100% rename from etc/macos_entitlements.xml rename to etc/macos_release_entitlements.xml diff --git a/evergreen/macos_notary.py b/evergreen/macos_notary.py index 9439804b279..ad6e4769d4b 100644 --- a/evergreen/macos_notary.py +++ b/evergreen/macos_notary.py @@ -1,3 +1,4 @@ +import argparse import os import platform import shutil @@ -6,15 +7,13 @@ import subprocess import zipfile import stat import sys +import yaml + if platform.system().lower() != 'darwin': print("Not a macos system, skipping macos signing.") sys.exit(0) -if len(sys.argv) < 2: - print("Must provide at least 1 archive to sign.") - sys.exit(1) - supported_archs = { 'arm64': 'arm64', 'x86_64': 'amd64' @@ -25,12 +24,20 @@ if arch not in supported_archs: print(f"Unsupported platform uname arch: {arch}, must be {supported_archs.keys()}") sys.exit(1) -macnotary_name = f'darwin_{supported_archs[arch]}' +expansions_file = "../expansions.yml" +if not os.path.exists(expansions_file): + print("Evergreen expansions file not found. Skipping macos_notary.") + sys.exit(0) -if os.environ['project'] == "mongodb-mongo-master-nightly": - signing_type = 'notarizeAndSign' -else: - signing_type = 'sign' +with open(expansions_file) as file: + expansions = yaml.safe_load(file) + +should_sign = expansions.get("sign_macos_archive", None) +if not should_sign: + print("sign_macos_archive expansion not found not found or false. Skipping macos_notary.") + sys.exit(0) + +macnotary_name = f'darwin_{supported_archs[arch]}' macnotary_url = f'https://macos-notary-1628249594.s3.amazonaws.com/releases/client/latest/{macnotary_name}.zip' print(f'Fetching macnotary tool from: {macnotary_url}') @@ -42,43 +49,51 @@ st = os.stat(f'{macnotary_name}/macnotary') os.chmod(f'{macnotary_name}/macnotary', st.st_mode | stat.S_IEXEC) failed = False -archives = sys.argv[1:] +parser = argparse.ArgumentParser( + prog="MacOS Notary", + description="Sign and/or notarize a tarball containing unsigned binaries.", +) +parser.add_argument("--archive-name", "-a", action="store", required=True) +parser.add_argument("--entitlements-file", "-e", action="store", required=True) +parser.add_argument("--signing-type", "-s", action="store", required=True) +args = parser.parse_args() +archive_name = args.archive_name +entitlements_file = args.entitlements_file +signing_type = args.signing_type -for archive in archives: - archive_base, archive_ext = os.path.splitext(archive) - unsigned_archive = f'{archive_base}_unsigned{archive_ext}' - shutil.move(archive, unsigned_archive) +archive_base, archive_ext = os.path.splitext(archive_name) +unsigned_archive = f'{archive_base}_unsigned{archive_ext}' +shutil.move(archive_name, unsigned_archive) - signing_cmd = [ - f'./{macnotary_name}/macnotary', - '-f', f'{unsigned_archive}', - '-m', f'{signing_type}', - '-u', 'https://dev.macos-notary.build.10gen.cc/api', - '-k', 'server', - '--entitlements', 'etc/macos_entitlements.xml', - '--verify', - '-b', 'server.mongodb.com', - '-i', f'{os.environ["task_id"]}', - '-c', f'{os.environ["project"]}', - '-o', f'{archive}' - ] +signing_cmd = [ + f'./{macnotary_name}/macnotary', + '-f', f'{unsigned_archive}', + '-m', f'{signing_type}', + '-u', 'https://dev.macos-notary.build.10gen.cc/api', + '-k', 'server', + '--entitlements', entitlements_file, + '--verify', + '-b', 'server.mongodb.com', + '-i', f'{expansions["task_id"]}', + '-c', f'{expansions["project"]}', + '-o', f'{archive_name}' +] - signing_env = os.environ.copy() - signing_env['MACOS_NOTARY_SECRET'] = os.environ["macos_notarization_secret"] - print(' '.join(signing_cmd)) - p = subprocess.Popen(signing_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=signing_env) +signing_env = os.environ.copy() +signing_env['MACOS_NOTARY_SECRET'] = expansions.get("macos_notarization_secret", "") +print(' '.join(signing_cmd)) +p = subprocess.Popen(signing_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=signing_env) - print(f"Signing tool completed with exitcode: {p.returncode}") - for line in iter(p.stdout.readline, b''): - print(f'macnotary: {line.decode("utf-8").strip()}') - p.wait() +print(f"Signing tool completed with exitcode: {p.returncode}") +for line in iter(p.stdout.readline, b''): + print(f'macnotary: {line.decode("utf-8").strip()}') +p.wait() - if p.returncode != 0: - failed = True - shutil.move(unsigned_archive, archive) - else: - os.unlink(unsigned_archive) +if p.returncode != 0: + failed = True + shutil.move(unsigned_archive, archive_name) +else: + os.unlink(unsigned_archive) if failed: exit(1) - diff --git a/site_scons/site_tools/auto_archive.py b/site_scons/site_tools/auto_archive.py index 63d76393857..57d0168dbac 100644 --- a/site_scons/site_tools/auto_archive.py +++ b/site_scons/site_tools/auto_archive.py @@ -290,6 +290,25 @@ def archive_builder(source, target, env, for_signature): return cmd +def macos_archive_sign_builder(source, target, env, for_signature): + if env['PLATFORM'] != 'darwin' or env.GetOption("ninja") != 'disabled': + return "" + + if env.GetOption("release") is not None: + print("MacOS release build found, signing with release entitlements.") + entitlements_file = 'etc/macos_release_entitlements.xml' + signing_type = 'notarizeAndSign' + else: + print("MacOS dev build found, signing with insecure development entitlements.") + entitlements_file = 'etc/macos_dev_entitlements.xml' + signing_type = 'sign' + + archive_name = env.File(target[0]) + macos_notory_cmd = f"{sys.executable} evergreen/macos_notary.py --archive-name={archive_name} --entitlements-file={entitlements_file} --signing-type={signing_type}" + + return macos_notory_cmd + + def exists(env): return True @@ -299,11 +318,14 @@ def generate(env): env.Tool("auto_install_binaries") bld = SCons.Builder.Builder( - action=SCons.Action.CommandGeneratorAction( - archive_builder, - {"cmdstr": "Building package ${TARGETS[0]} from ${SOURCES[1:]}"} - if not env.Verbose() else {"cmdstr": ""}, - )) + action=SCons.Action.ListAction([ + SCons.Action.CommandGeneratorAction( + archive_builder, + {"cmdstr": "Building package ${TARGETS[0]} from ${SOURCES[1:]}"} + if not env.Verbose() else {"cmdstr": ""}, + ), + SCons.Action.CommandGeneratorAction(macos_archive_sign_builder, {}) + ])) env.Append(BUILDERS={"AutoArchive": bld}) env["AUTO_ARCHIVE_TARBALL_SUFFIX"] = env.get( "AUTO_ARCHIVE_TARBALL_SUFFIX",