codex / .github /scripts /macos-signing /sign_macos_cli_package.py
SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
2ee40b0 verified
Raw History Blame Contribute Delete
6.89 kB
"""Sign and verify macOS CLI packages using the shared AKV and native tools."""
import argparse
import os
import subprocess
import sys
from pathlib import Path
import provisioned_macos_cli_package as bundle
def main(configuration: bundle.ProfileConfiguration | None = None):
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("operation", choices=("sign", "verify"))
parser.add_argument("package", type=Path)
args, configuration = bundle.parse_profile_args(parser, configuration)
package = args.package.resolve(strict=True)
if not package.is_dir():
parser.error("package must be an extracted CLI package directory")
repo_root = os.environ.get("CODEX_REPO_ROOT")
if not repo_root:
parser.error("CODEX_REPO_ROOT must be set")
reports = Path(repo_root) / "signing-verification"
reports.mkdir(parents=True, exist_ok=True)
provisioned = os.environ.get("PROVISIONED_MACOS", "false") == "true"
if provisioned:
if args.operation == "sign":
configuration.validate_signing_certificate(
Path(os.environ["OAI_AKV_SIGNING_CERTIFICATE_PEM"])
)
bundle.prepare(package, reports, configuration)
else:
bundle.verify(package, reports, os.environ["TARGET"], configuration)
for relative in ("bin/codex", *bundle.HELPERS):
binary = package / relative
name = binary.name
target = binary
identifier = name
entitlements = bundle.SIGNING / f"{name}.entitlements.plist"
if provisioned and relative == "bin/codex":
binary = package / bundle.EXECUTABLE
target = package / bundle.APP
identifier = bundle.BUNDLE_ID
entitlements = reports / "codex-provisioned-entitlements.plist"
if args.operation == "sign":
command = [
"bash",
str(bundle.SIGNING / "sign_macos_code.sh"),
"--target",
str(target),
"--identity",
"unused",
"--deep",
"false",
"--options",
"runtime",
"--timestamp",
"true",
]
if relative.startswith("bin/"):
command.extend(
["--identifier", identifier, "--entitlements", str(entitlements)]
)
else:
command.extend(["--identifier", f"com.openai.codex.{name}"])
subprocess.run(command, check=True)
with (reports / f"{name}-signature.yaml").open("wb") as output:
subprocess.run(
["rcodesign", "print-signature-info", str(binary)],
stdout=output,
check=True,
)
if not provisioned:
subprocess.run(
[
"bash",
str(bundle.SIGNING / "notarize_macos_binary_with_akv.sh"),
"--binary",
str(binary),
"--report-dir",
str(reports / name),
],
check=True,
)
else:
target_triple = os.environ["TARGET"]
architectures = {
"aarch64-apple-darwin": "arm64",
"x86_64-apple-darwin": "x86_64",
}
if target_triple not in architectures:
raise ValueError(f"Unexpected macOS target: {target_triple}")
subprocess.run(
["lipo", str(binary), "-verify_arch", architectures[target_triple]],
check=True,
)
subprocess.run(
[
"codesign",
"--verify",
"--strict",
"--verbose=2",
"--test-requirement",
# Require Apple's Developer ID Application certificate chain.
(
"=anchor apple generic"
" and certificate 1[field.1.2.840.113635.100.6.2.6] exists"
" and certificate leaf[field.1.2.840.113635.100.6.1.13] exists"
),
str(target),
],
check=True,
)
signature = reports / f"{name}-signature.txt"
with signature.open("wb") as output:
subprocess.run(
["codesign", "-d", "--verbose=4", str(target)],
stderr=output,
check=True,
)
actual = reports / f"{name}-entitlements.plist"
with actual.open("wb") as output:
subprocess.run(
["codesign", "-d", "--entitlements", ":-", str(target)],
stdout=output,
check=True,
)
if relative.startswith("bin/"):
expected = reports / f"{name}-expected.plist"
subprocess.run(
[
"plutil",
"-convert",
"xml1",
"-o",
str(expected),
str(entitlements),
],
check=True,
)
subprocess.run(["plutil", "-convert", "xml1", str(actual)], check=True)
subprocess.run(["diff", "-u", str(expected), str(actual)], check=True)
elif actual.stat().st_size:
raise ValueError(
f"Bundled helper {name} must not have signing entitlements"
)
if provisioned and args.operation == "sign":
archive = Path(os.environ["RUNNER_TEMP"]) / "provisioned-cli.zip"
subprocess.run(["zip", "-q", "-r", str(archive), "."], cwd=package, check=True)
command = [
sys.executable,
str(bundle.SIGNING / "notarize_with_akv.py"),
"--file",
str(archive),
"--report-log",
str(reports / "notarization-developer-log.json"),
"--max-wait-seconds",
"1200",
]
with (
(reports / "notarization.log").open("w") as output,
subprocess.Popen(
command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True
) as process,
):
assert process.stdout is not None
for line in process.stdout:
print(line, end="", flush=True)
output.write(line)
if returncode := process.wait():
raise subprocess.CalledProcessError(returncode, command)
if __name__ == "__main__":
main()