Mac OS Gatekeeper 阻止签名命令行工具

Posted

技术标签:

【中文标题】Mac OS Gatekeeper 阻止签名命令行工具【英文标题】:Mac OS Gatekeeper blocking signed command line tool 【发布时间】:2016-10-01 21:51:05 【问题描述】:

我在 Xcode 中有一个被 Gatekeeper 阻止的“命令行工具”目标(不是 App 包)。多年来,我一直使用这个工具作为我的 PostCheck 地址簿插件的简单安装程序。

在 2012 年,我使用我的 Apple Developer ID 签署了该工具,这样它就不会被 Gatekeeper 阻止,并且有一段时间一切都很好。我现在注意到 macOS Sierra (10.12) 现在被阻止了,在测试期间我还发现它也被 10.11.6 阻止了。 (当我说被阻止时,我的意思是用户必须右键单击它并选择“打开”而不是在警告对话框中获得选项。)它仍然适用于 10.11.2! – 如果我记得,Mac OS X 10.11.4 有一个错误,即使已签名也阻止非应用程序包,但我认为该问题已在 10.11.5 中修复。也许是相关的?

我尝试在 Sierra 下使用 Xcode 8 重新编译和重新签名可执行文件。我尝试在二进制文件中嵌入一个 Info.plist(我以前没有做过)。我已经尝试归档,而不仅仅是“构建”,以防它是调试与发布配置的问题。我花了两天时间搜索验证我的可执行文件是否正确签名的方法,似乎结果相互矛盾……

有这个:

codesign --verify --verbose <executable> 
<executable>: valid on disk
<executable>: satisfies its Designated Requirement

还有这个:

spctl --assess --verbose <executable> 
<executable>: rejected (the code is valid but does not seem to be an app)
source=matched cdhash

还有这个:

spctl -a -v --raw <executable> 
<executable>: accepted
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>assessment:authority</key>
    <dict>
        <key>assessment:authority:flags</key>
        <integer>0</integer>
        <key>assessment:authority:source</key>
        <string>allowed cdhash</string>
        <key>assessment:authority:weak</key>
        <true/>
    </dict>
    <key>assessment:cserror</key>
    <integer>-67002</integer>
    <key>assessment:remote</key>
    <true/>
    <key>assessment:verdict</key>
    <true/>
</dict>
</plist>

我想我的部分问题是我不知道命令行可执行文件在使用有效的 Apple 开发人员 ID 签名后应该是什么样子。而且我也不知道这是否是我无能为力的 macOS 问题。对于命令行工具和代码签名问题,Google 也很难找到与命令行 Unix 可执行文件的代码签名相关的内容。

感谢您对这里可能发生的事情的任何见解。谢谢!

【问题讨论】:

尝试使用--strict 选项和codesign。另外,请尝试将-t open 选项与spctl 一起使用,因为双击可执行文件并不会真正直接执行它,它会将其作为文档传递给终端,而终端将路径作为命令执行。这可能会解决“似乎不是应用程序”的问题。您还可以多次指定-v 以增加详细程度。使用--ignore-cache 只是为了确保您正在评估文件是新鲜的。 FWIW,错误 cserror -67002 是 errSecCSNotAppLike(这可能不是一个大惊喜)。我通过创建一个包含命令行工具的应用程序包并签署该包来“修复”这个问题。然后我可以运行命令行工具,只需将其引用为 foo.app/Contents/MacOS/foo。不是很好的用户体验,但可以满足我的需求。 【参考方案1】:

我讨厌回答我的问题,但万一有人遇到同样的问题:

解决方案是将命令行工具分发到签名的磁盘映像而不是 zip 文件中。

我最终测试回 10.11.4 并确认那是问题开始的时候。 (当时我一定是在不正确地测试它。)无论我如何签名,OS X 都会阻止双击 Unix 命令行工具。这可能是最好的,因为大多数命令行工具都将在 Terminal.app 中运行。

对于 Sierra,事实证明我无论如何都需要签名的 DMG 来绕过 Gatekeeper 的新路径随机化功能。

【讨论】:

似乎从 Catalina 开始,“公证”可能会像僵尸一样从坟墓中复活这个问题,在这种情况下,似乎(在我的情况下,无论如何)制作可执行文件签名和公证的 DMG 文件的一部分可能无法解决问题。 为后代自我回答;就我而言,问题可能是可执行文件加载了另一个库,因此即使两者都经过公证,运行加载库的可执行文件也是不行的。 我也发现 Catalina 会阻止一个命令行工具,该工具链接到具有相对加载器路径的 .dylib(即 otool -L /path/to/libFoo.dylib 在某处输出 @executable_path,因为该库是使用 DYLIB_INSTALL_NAME_BASE=@executable_path 构建的)。可能的解决方法包括:1) 删除相对加载器路径(指定 /usr/local/bin 而不是 @executable_path)2) 从签名的 .pkg 打包并安装它们,以避免在用户下载您的分发时设置隔离标志,3) 分发包中的可执行文件和库,然后从那里运行 CLI 工具。【参考方案2】:

在 macOS Catalina 10.15.3 及更早版本(在 10.15.4 中修复)中存在一个已知错误,其中一个经过公证的命令行应用程序链接到其捆绑包之外的 .dylib(并且命令行应用程序通常不在捆绑包中) 仍然会在命令行可执行文件上设置隔离**标志时触发 Gatekeeper 检查失败。

为解决此问题,Apple DTS 建议:

最简单的解决方法是使用强化的运行时和库验证标志对您的工具进行签名。

也就是说,更改您对 codesign 的调用:

% codesign -s …stuff… -o runtime …stuff… helloworld

到这里:

% codesign -s …stuff… -o runtime,library …stuff… helloworld

显式设置库标志会禁用此 Gatekeeper 检查并允许您的工具在 macOS 10.15 上运行。0,1,2,3。请在 10.15.4 发布并广泛采用后删除此标志。

**根据https://eclecticlight.co/2019/10/24/airdrop-and-quarantine-flags/,每当您通过 Internet 下载或 AirDrop(但不是通过网络文件共享或 iCloud Drive)接收文件时,就会设置隔离标志

【讨论】:

【参考方案3】:

当我与 go-astilectron-bundler 捆绑并在我的情况下添加时遇到了同样的问题

<key>CFBundlePackageType</key>
<string>APPL</string>

Info.plist 文件解决了问题。

【讨论】:

以上是关于Mac OS Gatekeeper 阻止签名命令行工具的主要内容,如果未能解决你的问题,请参考以下文章

第三方证书和Gatekeeper

MAC os x 10.8+ 代码签名证书详细信息

为啥 electron-osx-sign 无法生成 Gatekeeper 识别的签名应用程序?

mac命令行对复杂ipa包重新签名

苹果mac os怎么用命令行终端打开app应用程序

苹果mac os怎么用命令行终端打开app应用程序