“用户交互是不允许的”试图签署一个 OSX 应用程序使用协同设计

我们的自动生成程序正在 Jenkins 身上运行。构建本身在从服务器上运行,从服务器通过 SSH 执行。

我得到一个错误:

00:03:25.113 [codesign-app] build/App.app: User interaction is not allowed.

到目前为止,我已经尝试了在这里的其他帖子中看到的所有建议:

  • 在签名前立即使用安全解锁钥匙链来解锁钥匙链。
  • 将签名密钥移出到它自己的密钥链中。
  • 将签名密钥移动到登录密钥链中。
  • 将签名密钥移动到系统密钥链中。
  • 手动将 list-keychain 设置为仅包含密钥的 keychain。

在所有情况下,我都会得到相同的错误。

为了诊断这个问题,我尝试在我的本地终端上运行“安全解锁-钥匙链”命令,发现它实际上并没有解锁钥匙链——如果我查看钥匙链访问,锁符号仍然存在。无论是在命令行上传递密码还是让它提示我输入密码,都是这种情况。使用 GUI 解锁相同的密钥链将提示我输入密码,然后解锁。此外,如果我运行“ security lock-keychain”,我 在运行命令后立即看到密钥锁。这让我觉得解锁钥匙链根本没用。我在 Lion (我们正在用它来构建奴隶)和 Mavericks (我正在开发它们)身上体验到了同样的行为

接下来,我尝试在所有安全命令中添加-v:

list-keychains "-d" "system" "-s" "/Users/tester/.secret/App.keychain"
Listing keychains to see if it was added: ((
"/Library/Keychains/System.keychain"
))
unlock-keychain "-p" "**PASSWORD**" "/Users/tester/.secret/App.keychain"
build/App.app: User interaction is not allowed.

由此看来,list-keychain 是不起作用的,也许两者都不起作用。 :/

有一个 类似的问题。解决方案很有趣——在 launchctl 中将“ SessionCreate”设置为 true。但是我不是在主机上构建——我的构建过程是从从构建机器上的 SSH 启动的。也许在运行“ SessionCreate”时,有一种命令行方式可以执行 launchctl 正在执行的操作?

97071 次浏览

我想我今天可以回答我自己的问题了因为经过两天半的努力我尝试的其中一个方法似乎奏效了。我现在要放弃了,希望它能继续工作。

本质上,它看起来像是归结到 -d system实际上不工作。所以这里很多其他问题的答案也许应该更新以反映这一点。

security -v list-keychains -s "$KEYCHAIN" "$HOME/Library/Keychains/login.keychain"
security list-keychains # so we can verify that it was added if it fails again
security -v unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN"
codesign --sign "$SIGNER_IDENTITY" --force --signature-size 9600 \
--resource-rules src/AppResourceRules.plist --timestamp --verbose \
"$APP"

尝试用一行命令调用 security unlock-keychaincodesign。这对我有帮助。比如:

security unlock-keychain -p <password> /Users/<user>/Library/Keychains/login.keychain && codesign --force --verify --verbose --sign "<certificate id>" <app name>

我也一直在抗争这一点。没有任何帮助,直到我尝试了对 http://devnet.jetbrains.com/thread/311971的建议。谢谢阿什格拉瓦!

通过 GUI 登录生成用户并打开 Keychain Access。选择您的签名私钥,右键单击,选择获取信息,更改到访问控制选项卡,并选择“允许所有应用程序访问此项目”。

access control tab

其他的答案对我都不管用。

最终救了我的是 这篇文章

总而言之,这可能是由于默认的5分钟超时造成的,这将在长时间构建后触发此错误。

修复:

security set-keychain-settings -t 3600 -l ~/Library/Keychains/login.keychain

对我来说,似乎没有什么工作需要重新安装 Xcode。 如果将 Xcode 安装移动到 Trash 并重新安装,将节省大量时间。确保至少从命令行运行一次协同设计命令。

即使之后,如果你得到相同的错误尝试设置’解锁钥匙链?属性,并在/Users/${ USER }/Library/Keychain/login.keychain 下给出您的 login.keychain 的路径

我希望之后上帝与你同在。

我的钥匙链是锁着的,如果我想改变这个事实..。

Keychain Access-> Keychain First Aid-> Repair就是这样

在尝试了以上几种解决方案之后。我意识到我有一个因素,那就是我正在使用 ION 控制台开始构建。当我切换回来,从终端应用程序的构建,一切都工作得很好。

把你的钥匙放在系统钥匙链里

在我的例子中,这是由于创建了一个默认超时300秒的密钥链和一个超过300秒的长 xcode 编译引起的。对我来说,解决办法是:

Security set-keychain-sets-t < long timeout in second > < keychain > 安全设置-密钥链-设置-t < 更长的超时时间(秒) >

在创建临时密钥链之后立即执行。

将密钥导入系统密钥链。可以使用以下命令:

sudo security import YourKey.p12 -k /Library/Keychains/System.keychain -P PasswordToYourKey -T /usr/bin/codesign

这就是可以工作的命令。-A是为了防止 Mac 询问密码。导入 System.keychain 不需要 GUI。

sudo security import <cert.p12> -k "/Library/Keychains/System.keychain" -P <passphrase> -A

我浏览了所有这些建议,仍然有问题使用快车的 gym在詹金斯的工作。我已经安装了证书并解锁了钥匙链,当我在命令行上手动运行 codesign 命令时,我可以在从机上进行协同设计。

作为一种变通方法,如果 Jenkins 使用 JNLP 而不是 SSH 连接到从服务器,那么您将能够进行协同设计。

解开钥匙链是不够的。您还必须将私钥访问设置为“允许所有应用程序访问此项目”。要在命令行中实现这一点,需要重新导入密钥。因此,一步一步来:

解锁登录密钥链,如果它是锁定的。它不应该被锁定,但无论如何,这里是你如何做到这一点:

security -v unlock-keychain -p "$KEYCHAIN_PASSWORD" "~/Library/Keychains/login.keychain"

如果由于某种原因您的构建机器锁定了登录密钥链,并且您不想在脚本中公开该密码,那么您应该使用不同的密钥链。您可以现场创建一个,并在前面和下面的命令中使用它。当场创造一个:

security create-keychain -p 'temporaryPassword' MyKeychain.keychain
security list-keychains -d user -s login.keychain MyKeychain.keychain

然后使用 -A 参数将您的证书和关联的私钥导入到登录密钥链中。请注意,您不需要为所有这些 sudo..。

security import <cert.p12> -k "~/Library/Keychains/login.keychain" -P <passphrase> -A

参数-A 将使您的私钥设置为“允许所有应用程序访问此项”

因此,使用所有这些工具,您应该能够编写一个脚本,安装构建发行版 ipa 所需的证书,并在不需要提示的情况下对其进行签名。您可以存储。P12文件,所以任何机器都可以构建您的 ipa 而不需要手动设置。

所以我尝试了这里的每一个答案,但有些东西不太对劲。最后我发现当我重新启动 CI 服务时,它运行在一个不同于我预期的用户之下。更改为实际上可以访问其登录链中的密钥的用户修复了所有问题。这可能不是一个常见的问题,但是我希望能够记录出现这个错误的具体原因,以防其他人也出现这种情况。

对我来说,它发生时,有第二个钥匙链手动添加和它的锁定。由于某种原因,codesign尝试访问锁定的密钥链,即使证书在登录密钥链中(并且是解锁的) ,也会失败。解开第二个解决了这个问题。我觉得没道理。

使用 Security 为/usr/bin/codesign 创建一个 Keychain

导入证书并让它以编程方式与协同设计一起工作并不是使用登录或系统密钥链或向某个协同设计之神祈祷的问题。您只需要设置正确的权限。我建议专门为了协同设计的目的创建一个新的密钥链。

现在,为了使 codesign不产生 errSecInternalComponent,您需要获得正确的分区列表(ACL)。我会走过这些台阶:

创建钥匙链

security create-keychain -p "${KEYCHAIN_PASSWORD}" "${KEYCHAIN_NAME}"

此时钥匙链是解锁的,但不会出现在 Keychain Access中。

将新的 Keychain 添加到搜索列表中

security list-keychains -s "${KEYCHAIN_NAME}" "${OLD_KEYCHAIN_NAMES[@]}"

将新的 Keychain 添加到列表中。如果你不首先从 list-keychains中抓取原始列表,那么你的搜索列表中就不会再有 login.keychain了。

打开钥匙链

security unlock-keychain -p "${KEYCHAIN_PASSWORD}" "${KEYCHAIN_NAME}"

如果你创建了上述的钥匙链,这是多余的,但如果 Keychain 已经存在,这是必要的。

从 Keychain 中删除默认值

security set-keychain-settings "${TESTING_KEYCHAIN}"

通过不指定任何参数,这将把自动锁定超时设置为无限制,并删除睡眠时的自动锁定。

从.p12导入您的签名证书

security import "${DIST_CER}" -P "${CERTIFICATE_PASSWORD}" -k "${KEYCHAIN_NAME}" -T /usr/bin/codesign

导入证书并通过 -T选项赋予 codesign访问权限。

在钥匙链上设置 ACL

security set-key-partition-list -S apple-tool:,apple: -s -k "${KEYCHAIN_PASSWORD}" "${KEYCHAIN_NAME}"

这是很多人都忽略的一个要求。您可以通过使用 dump-keychain 查看 macOS 的功能。在协同设计的情况下,需要 apple:apple-tool:-s指的是签名证书。

我的签字证明呢?

总是一个好主意,以确保您可以找到您的证书

security find-identity -p codesigning -v /path/to/keychain

Gitlab-Runner Jenkins 之类的

对于任何 CI 类型的运行器或构建系统来说,一件非常重要的事情是确保进程从 launchd正确启动。确保你的列表包含 <SessionCreate> </true>

如果不能正确地将密钥链的所有者与构建过程进行匹配,并确保创建了安全会话,将会导致各种各样的问题。从诊断的角度来说,你可以引入 list-keychains,看看输出是否符合你的期望。

这来自 launchd.plist手册:

SessionCreate <boolean>

此密钥指定作业应派生到新的安全性中 审计会话,而不是上下文的默认会话 详情见审核(2)。

UserName <string>

此可选键指定用户以 适用于加载到特权系统中的服务 域名。

GroupName <string>

此可选键指定作业的运行组。此键仅为 适用于加载到特权系统中的服务 如果设置了 UserName 而没有设置 GroupName,则该组将为 设置为用户的主要组。

示例/Library/LaunchDaemons/com.company.gitlab-runner. plist

<?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>Label</key>
<string>com.company.gitlab-runner</string>
<key>SessionCreate</key><true/>
<key>KeepAlive</key><true/>
<key>Disabled</key><false/>
<key>UserName</key>
<string>bob</string>
<key>GroupName</key>
<string>staff</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/opt/gitlab-runner/bin/gitlab-runner</string>
<string>run</string>
<string>--working-directory</string>
<string>/Users/bob/gitlab-runner</string>
<string>--config</string>
<string>/Users/bob/gitlab-runner/config.toml</string>
<string>--service</string>
<string>gitlab-runner</string>
<string>--syslog</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
</dict>
</dict>
</plist>

登记跑步者

gitlab-runner register \
--non-interactive \
--tls-ca-file "\{\{ gitlab_runner_dir }}/certs/git.company.com.crt" \
--config "\{\{ gitlab_runner_dir }}/config.toml" \
--builds-dir "\{\{ gitlab_runner_dir }}/builds" \
--url "\{\{ gitlab_ci }}" \
--registration-token "\{\{ gitlab_token }}" \
--name "\{\{ computername }}" \
--tag-list "\{\{ gitlab_runner_tags }}" \
--output-limit 16384 \
--executor shell \
--shell bash

终于联合设计了

可以使用 find-identity查找签名证书散列

security find-identity -p codesigning -v

在开始签署 Xcode 之前,设置环境变量 CODESIGN_ALLOCATE使用 Xcode 附带的 codesign_allocate,而不是 /usr/bin

export CODESIGN_ALLOCATE="$( xcrun --find codesign_allocate )"

协同设计一个框架、 dylib 等等。

如果您是手动联合设计,从 frameworksdylibs开始,在它们都签署之后,再签署 .app。或者换句话说——你们自下而上的共同设计。

/usr/bin/codesign --verbose=4 -f -s "$SIGNER_HASH" "$SIGNABLE"

协同设计应用程序包

在签署了所有其他可签名之后,签署。应用程序本身。理论上,你可以用 --deep一次完成所有这些,但是,你仍然需要确保你的应用程序有权利和可能的其他标志。

/usr/bin/codesign --verbose=4 -f -s "$SIGNER_HASH" "$SIGNABLE"

所有项目都插上了旗帜:

  • 禁用时间戳

应用程序签名步骤的其他标志:

  • --entitlements /path/to/entitlements.xcent新权利
  • --preserve-metadata=entitlements保留当前应享权利

新的协同设计要求-DER 编码的权利

苹果公司最近开始要求授权不仅要以 plist 形式嵌入,还要以 DER 编码形式嵌入。如果您使用的是较旧的 Mac/Xcode,您可能会遇到错误..。

不再支持代码签名版本

除了解锁密钥链(正如另一个答案中提到的) ,你还需要允许所有应用程序访问密钥链中的 Xcode 认证令牌:

  • 选择“ login”keychain
  • 选择“所有项目”类别
  • 搜索“ xcode”关键字
  • 为所有 Xcode 标记选择“允许所有应用程序访问此项”
  • 不要忘记添加解锁钥匙链步骤(从以前的答案)

Screenshot