mirror of
https://github.com/openai/codex.git
synced 2026-09-20 12:47:38 +00:00
Preserve the provisioned macOS CLI's code-signing identity (#46495)
## Why Existing login-keychain access rules identify the CLI as `codex`. Packaging it in an app bundle must preserve that code-signing identifier independently of the bundle identifier and provisioned App ID. ## What changed - Sign the provisioned CLI with the identifier `codex`, retaining `com.openai.codex.cli` as its bundle identifier. - Require the expected signing identifier and team during signature verification, and reject unexpected bundle identifiers, executable names, or package types. - Document the identity distinction and keychain compatibility limits. ## Testing Extend signing-driver tests to check the signing identifier, verification requirement, bundle metadata, and provisioned entitlements, and to reject altered bundle identity fields. These tests use generated credentials and stubbed native tools; they do not verify runtime keychain access or credential recovery. GitOrigin-RevId: ab00072e48189551adb0e70008210fee6d36241d
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
"""Exercise package signing and native verification with generated credentials."""
|
||||
"""Exercise signing orchestration with generated credentials and stubbed native tools."""
|
||||
|
||||
import itertools
|
||||
import json
|
||||
import os
|
||||
import plistlib
|
||||
import shutil
|
||||
import ssl
|
||||
import subprocess
|
||||
@@ -172,6 +173,9 @@ class MacosSigningTests(ProvisioningTestCase):
|
||||
)
|
||||
],
|
||||
)
|
||||
self.assertEqual(
|
||||
signing[0][signing[0].index("--identifier") + 1], "codex"
|
||||
)
|
||||
self.assertEqual(
|
||||
signing[0][signing[0].index("--entitlements") + 1],
|
||||
str(
|
||||
@@ -208,7 +212,49 @@ class MacosSigningTests(ProvisioningTestCase):
|
||||
],
|
||||
)
|
||||
if provisioned:
|
||||
verification = [
|
||||
call
|
||||
for call in calls
|
||||
if call[0] == "codesign" and "--test-requirement" in call
|
||||
]
|
||||
cli_verification = verification[0]
|
||||
self.assertEqual(cli_verification[-1], str(package / bundle.APP))
|
||||
requirement = cli_verification[
|
||||
cli_verification.index("--test-requirement") + 1
|
||||
]
|
||||
self.assertIn(' and identifier "codex"', requirement)
|
||||
self.assertIn(
|
||||
' and certificate leaf[subject.OU] = "TESTTEAM01"', requirement
|
||||
)
|
||||
with zipfile.ZipFile(root / "provisioned-cli.zip") as archive:
|
||||
info = plistlib.loads(
|
||||
archive.read("CodexCLI.app/Contents/Info.plist")
|
||||
)
|
||||
self.assertEqual(
|
||||
info["CFBundleIdentifier"], "com.openai.codex.cli"
|
||||
)
|
||||
self.assertEqual(info["CFBundleExecutable"], "codex")
|
||||
self.assertEqual(
|
||||
plistlib.loads(
|
||||
(
|
||||
root
|
||||
/ "signing-verification/codex-provisioned-entitlements.plist"
|
||||
).read_bytes()
|
||||
),
|
||||
{
|
||||
**plistlib.loads(
|
||||
(
|
||||
Path(env["MOCK_SIGNING_SCRIPTS"])
|
||||
/ "codex.entitlements.plist"
|
||||
).read_bytes()
|
||||
),
|
||||
"com.apple.application-identifier": "TESTTEAM01.com.openai.codex.cli",
|
||||
"com.apple.developer.team-identifier": "TESTTEAM01",
|
||||
"keychain-access-groups": [
|
||||
"TESTTEAM01.com.openai.codex.cli"
|
||||
],
|
||||
},
|
||||
)
|
||||
self.assertEqual(
|
||||
archive.read(
|
||||
"CodexCLI.app/Contents/embedded.provisionprofile"
|
||||
@@ -225,6 +271,28 @@ class MacosSigningTests(ProvisioningTestCase):
|
||||
)
|
||||
)
|
||||
|
||||
def test_provisioned_verification_rejects_changed_bundle_identity(self):
|
||||
for field, value in (
|
||||
("CFBundleIdentifier", "codex"),
|
||||
("CFBundleExecutable", "another-codex"),
|
||||
("CFBundlePackageType", "BNDL"),
|
||||
):
|
||||
with self.subTest(field=field), tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory).resolve()
|
||||
package, driver, env = self.fixture(root, True)
|
||||
signed = self.run_driver(driver, "sign", package, env)
|
||||
self.assertEqual(signed.returncode, 0, signed.stderr)
|
||||
info_path = package / bundle.APP / "Contents/Info.plist"
|
||||
info = plistlib.loads(info_path.read_bytes())
|
||||
info[field] = value
|
||||
info_path.write_bytes(plistlib.dumps(info))
|
||||
result = self.run_driver(driver, "verify", package, env)
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertIn(
|
||||
"Unexpected provisioned CLI bundle identity or executable",
|
||||
result.stderr,
|
||||
)
|
||||
|
||||
def test_signing_and_notarization_failures_stop_the_driver(self):
|
||||
for tool in ("sign_macos_code.sh", "notarize_with_akv.py"):
|
||||
with self.subTest(tool=tool), tempfile.TemporaryDirectory() as directory:
|
||||
|
||||
Reference in New Issue
Block a user