【问题标题】:Missing certificates and keys in the keychain while using Jenkins/Hudson as Continuous Integration for iOS and Mac development使用 Jenkins/Hudson 作为 iOS 和 Mac 开发的持续集成时,钥匙串中缺少证书和密钥
【发布时间】:2011-10-13 06:16:05
【问题描述】:

我正在尝试改进适用于 iOS 的 Hudson CI,并在系统启动后立即启动 Hudson。为此,我使用以下启动脚本:

<?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>Hudson CI</string>
    <key>ProgramArguments</key>
    <array>
    <string>/usr/bin/java</string>
    <string>-jar</string>
    <string>/Users/user/Hudson/hudson.war</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>UserName</key>
    <string>user</string>
</dict>
</plist>

这可以正常工作,但是当由 Hudson 启动的 xcodebuild 尝试签署应用程序时,它会失败,因为它无法在钥匙串中找到正确的密钥/证书。但是,如果我从命令行启动 Hudson,密钥/证书对就在那里,因为它工作正常。

你知道为什么会这样吗?

【问题讨论】:

    标签: ios hudson jenkins keychain launchd


    【解决方案1】:

    我们在 Mac OSX Lion 上作为启动守护程序启动的 hudson slave 遇到了同样的问题。当我们使用 webstart 启动 slave 时,它​​起作用了。我们发现的唯一区别是环境变量不同。

    com.apple.java.jvmTask=WebStart
    

    有效,如果我们在没有 webstart 的情况下启动从站,则变量为

    com.apple.java.jvmTask=CommandLine.java
    

    我们发现无法预先影响价值。我建议你在 Hudson 中创建一个新节点,在同一台机器上运行并由 webstart 启动。为了启动从站,我们使用以下启动守护程序配置:

    <?xml version"1.0" encoding="UTF-8"?>
    <plist version="1.0">
    <dict>
        <key>Label</key>
        <string>jenkins</string>
        <key>UserName</key>
        <string>apple</string>
        <key>Program</key>
        <string>/usr/bin/javaws</string>
        <key>ProgramArguments</key>
        <array>
            <string>-verbose</string>
            <string>-wait</string>
            <string>http://<hudson-hostname>:8080/computer/<node-name>/slave-agent.jnlp</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>KeepAlive</key>
        <true/>
        <key>WorkingDirectory</key>
        <string>/Users/apple</string>
    </dict>
    </plist>
    

    【讨论】:

    • 谢谢。我一有时间就试试。
    • 我在这里遇到了完全相同的问题,您找到解决方案了吗?很想来这里。
    • @DASKAjA 上面的 LaunchDaemon 配置是我们解决问题的方法。通过 webstart 启动从站,它可以访问钥匙串。作为另一种方法,可以将密钥和证书从登录钥匙串移动到系统钥匙串。但我只听说这行得通,但我自己从未尝试过。
    【解决方案2】:

    在这个问题上花费了数小时和数天后,我找到了一个相当简单的解决方案。如上所述,您的启动配置中是否有不同的用户名并不重要:

    <key>UserName</key>
    <string>user</string>
    

    缺少的证书和密钥必须在系统钥匙串 (/Library/Keychains/System.keychain) 上。我在设置执行多个 security shell 调用的 jenkins 作业后发现了这一点。有趣的是security list-keychains

    + security list-keychains
        "/Library/Keychains/System.keychain"
        "/Library/Keychains/applepushserviced.keychain"
        "/Library/Keychains/System.keychain"
    

    这是 jenkins 将搜索证书和密钥的钥匙串,因此它们应该在那里。在我将证书移到那里后,它就可以工作了。确保您还将»Apple Worldwide Developer Relations Certification Authority« 证书复制到系统钥匙串,否则您将看到来自codesignCSSMERR_TP_NOT_TRUSTED 错误。

    还可以使用security list-keychains -s [path to additional keychains] 注册更多钥匙串。我还没有尝试过,但是像 security list-keychains -s $HOME/Library/Keychains/login.keychain 这样的东西作为 jenkins 中的预构建 shell 执行可能会起作用。

    编辑:我尝试使用-s 将用户钥匙串添加到搜索路径,但我无法让它工作。所以现在,我们必须将我们的证书和密钥复制到系统钥匙串中。

    EDIT^2:阅读并使用 joensson' solution 而不是我的,他管理它来访问用户钥匙串,而不仅仅是系统钥匙串。

    【讨论】:

    • 但是在无人登录的情况下如何解锁系统钥匙串呢? sudo 命令?
    • @Zsub 我认为您不需要 System.keychain 的密码。但如果我在这里搞砸了,你可以用密码拨打security unlock -p password /path/to/System.keychain
    • 我创建了一个执行“security list-keychains”的简单作业,发现 Jenkins 使用了 $JENKINS_HOME/Library/Keychains/login.keychain,无论守护程序以哪个用户身份运行,或者我添加了哪些选项命令。所以,我放弃并将我想要的钥匙串复制到 $JENKINS_HOME/Library/Keychains/login.keychain 并且它起作用了。
    • 摆弄 System.keychain 会对所有已安装的应用程序产生副作用。 joensson 下面有一个更好的解决方案。
    【解决方案3】:

    我们在 Lion 和 SnowLeopard 上遇到了完全相同的问题。我们必须启动一个带有 xcodebuild 作业的 Tomcat/Hudson 作为服务。从命令行启动时,xcodebuild 可以访问 login.keychain 以使用包含的证书。但重启机器后,xcodebuild 看不到 login.keychain,因此签名失败。

    由于我们需要通过钥匙串提供我们的公司证书,因此系统钥匙串不是一个选项。相反,我们通过一个简单的解决方法解决了这个问题。我们删除了用户名,以便启动守护程序在 root 下启动进程。

    <plist version="1.0">
     <dict>
       <key>Label</key>
       <string>${LAUNCH_LABEL}</string>
       <key>Disabled</key>
       <false/>
       <key>RunAtLoad</key>
       <true/>
       <key>ProgramArguments</key>
       <array>
         <string>${INSTALL_DIR}/start.sh</string>
       </array>
       <key>StandardOutPath</key>
       <string>${INSTALL_DIR}/tomcat-stdout.log</string>
       <key>StandardErrorPath</key>
       <string>${INSTALL_DIR}/tomcat-stderr.log</string>
     </dict>
    </plist>
    

    启动守护进程调用一个简单的脚本(start.sh),模拟完全登录并运行想要的程序

    su -l username -c program
    

    现在,即使在启动之后,xcodebuild 也可以访问 login.keychain。这也适用于 Snow Leopard,但是,如果您在并行会话中关闭用户特定的 login.keychain(如 vnc 登录/注销),则钥匙串会丢失。狮子的行为不同。似乎 Lion 将钥匙串与用户分离并将其分配给登录会话。

    【讨论】:

      【解决方案4】:

      为了为 Jenkins/Hudson 保留一个分隔的钥匙串,我将 launchctl 项从

      /Library/LaunchDaemons/org.jenkins-ci.plist
      

      /Users/Shared/Jenkins/Home/Library/LaunchAgents/org.jenkins-ci.plist
      

      这让我可以访问为 Jenkins 创建的私钥链。

      【讨论】:

      • 我相信您的回答只会在 Jenkins 用户登录后立即启动?
      • 没错。如果不登录用户,我找不到方法。
      • 因为我们的解决方案并没有太大的不同:“我的”Jenkins 在启动时启动,但我仍然需要登录用户:P
      • 经过一段时间的处理,LaunchAgents 和 LaunchDaemons 具有不同的功能,不仅仅是它们何时以及如何启动,这些会影响构建过程的行为(尤其是在构建 mac 应用程序时)。跨度>
      【解决方案5】:

      我找到了一个解决方案,让我可以访问我的 Jenkins 用户的常规钥匙串。

      除了按照公认的答案在 plist 中指定 UserName 元素之外,为您在 UserName 中指定的用户获取普通钥匙串的访问权限的技巧是还向 plist 文件添加一个值为 true 的 SessionCreate 元素 - /Library/LaunchDaemons/org.jenkins-ci.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>EnvironmentVariables</key>
              <dict>
                      <key>JENKINS_HOME</key>
                      <string>/Users/Shared/Jenkins/Home</string>
              </dict>
              <key>GroupName</key>
              <string>wheel</string>
              <key>KeepAlive</key>
              <true/>
              <key>Label</key>
              <string>org.jenkins-ci</string>
              <key>ProgramArguments</key>
              <array>
                      <string>/bin/bash</string>
                      <string>/Library/Application Support/Jenkins/jenkins-runner.sh</string>
              </array>
              <key>RunAtLoad</key>
              <true/>
              <key>UserName</key>
              <string>jenkins</string>
              <key>SessionCreate</key>
              <true />
      </dict>
      

      然后重新启动守护程序并尝试在 Jenkins 中运行调用安全列表钥匙串的作业 - 您不应再将 System.keychain 作为唯一条目,而是常规登录和您可能已添加到列表中的任何自定义钥匙链“jenkins”用户的钥匙串。

      我现在在我的 Jenkins 构建服务器上使用自定义钥匙串中的代码签名证书 - 我没有在我的系统钥匙串中安装任何证书或密钥。

      【讨论】:

      • 很好的解决方案!用这个,而不是我的!
      • 谢谢!这正是我所需要的。太糟糕了,它没有记录在案。我为它创建了一个错误报告rdar://11708751
      • 当我执行命令 security list-keychains 时,我的 login.keychain 在列表中。问题是Jenkins仍然输出:security: SecKeychainUnlock /Users/Shared/Jenkins/Library/Keychains/login.keychain: The specified keychain could not be found.
      • 仅供参考,Jenkins 1.477 的更改日志,“更改了 Mac 安装程序的默认设置,使 iOS 代码设计更容易。”,似乎默认解决了这个问题。
      • 这是充满陷阱的旅程中最后丢失的部分。非常感谢!
      【解决方案6】:

      您可以尝试我的 Jenkins.app,https://github.com/stisti/jenkins-app,这是运行 Jenkins 的另一种方式。它在用户会话中运行 Jenkins,因此 Keychain 访问不是问题。

      【讨论】:

        【解决方案7】:

        我遇到了同样的问题,并尝试按照其他帖子中的说明更改 /Library/LaunchDaemons/org.jenkins-ci.plist 中的用户名。但是,它仍然没有工作,一些不起眼的 NullPointerException 并没有帮助我识别问题。因此,我只想分享我的解决方案:我还必须更改 JENKINS_HOME 目录的所有者(也在 org.jenkins-ci.plist 中定义):

        chown -R myBuildUser /Users/Shared/Jenkins
        

        myBuildUser 是安装了证书的用户,这是我在 plist 文件中指定的用户。

        当我终于意识到时,这个解决方案非常明显 - 但我花了几个小时才知道这一点,所以希望这篇文章可以为其他人节省时间:-)

        【讨论】:

          【解决方案8】:

          添加 会话创建 并在钥匙串管理器中设置大量证书以“始终信任” 使用从 plist 开始的 buildbot 为我工作......但在某些时候,代码设计开始失败 与 CSSMERR_TP_NOT_TRUSTED。我通过在钥匙串管理器中将 iPhone 分发证书设置为“使用系统默认值”来恢复。即使在重新启动后,没有登录, 然后 buildbot 从站就可以签署代码了,哇哦。

          【讨论】:

            【解决方案9】:

            添加这个是因为我遇到了同样的问题,但这些解决方案都不适合我。

            我的问题是我的签名证书已过期。更新后,手动运行 xcode 和运行 xcodebuild 工作正常,但 Jenkins 无法签署应用程序。

            这是我修复它的方法:

            1. 查看钥匙串并搜索钥匙。出于某种我不明白的原因,我有多个结果。

            2. 确保私钥处于系统级别(如果不是,则将其拖放到左侧的系统图标中。

            【讨论】:

              【解决方案10】:

              对于手动签名将您的证书从登录名移至钥匙串中的系统。在存档和生成 iPA 期间无法访问登录。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2022-11-11
                • 2012-10-20
                • 2018-10-29
                • 2013-09-09
                • 1970-01-01
                • 2017-05-01
                • 2023-04-04
                • 2011-12-28
                相关资源
                最近更新 更多