操作系统X上的Jenkins:xcodebuild会出现代码签名错误

ede*_*y05 107 macos jenkins

摘要:

使用最新的安装程序(截至2012年3月9日),在OS X上设置Jenkins变得非常容易,但是管理代码签名的过程仍然非常困难,没有简单的答案.

动机:

运行无头CI服务器,该服务器遵循在OS X上运行服务的常见最佳实践(其中一些以简单语言解释).

背景:

处理:

通过OS X 安装程序包安装Jenkins CI .对于"安装类型"步骤,单击"自定义"按钮,然后选择"以启动时启动为'jenkins.'"

讨论:

在这一点上天真的期望是使用构建脚本的自由风格项目xcodebuild -target MyTarget -sdk iphoneos应该工作.正如这篇文章的标题所示,它没有,也没有失败:

Code Sign error: The identity 'iPhone Developer' doesn't match any valid certificate/private key pair in the default keychain

很明显需要发生什么 - 您需要将有效的代码签名证书和私钥添加到默认的钥匙串中.在研究如何实现这一目标时,我还没有找到一种解决方案,它不能将系统打开到某种程度的漏洞.

问题1:没有jenkins守护程序的默认钥匙串

sudo -u jenkins security default-keychain ...产生"无法找到默认钥匙串"

正如Ivo Dancet在下面指出的那样,默认情况下,对于jenkins守护进程,UserShell设置为/ usr/bin/false(我认为这是一个功能,而不是一个bug); 按照他的回答将UserShell更改为bash.然后,您可以使用sudo su jenkins以jenkins用户身份登录并获取bash提示符.

  1. sudo su jenkins
  2. cd ~/Library
  3. mkdir Keychains
  4. cd Keychains
  5. security create-keychain <keychain-name>.keychain
  6. security default-keychain -s <keychain-name>.keychain

好,太棒了.我们现在有一个默认的钥匙串; 让我们继续吧?但是,首先为什么我们甚至打扰制作默认钥匙串?

我在整个研究过程中阅读的几乎所有答案,建议或对话都表明,应该将他们的代码签名证书和密钥放入系统密钥链中.如果你security list-keychains在Jenkins中作为一个自由风格的项目运行,你会看到唯一可用的钥匙串是系统钥匙串; 我认为这是大多数人提出将证书和密钥放在那里的想法.但是,这似乎是一个非常糟糕的主意 - 特别是考虑到您需要使用密码创建一个纯文本脚本来打开钥匙串.

问题2:添加代码签名证书和私钥

这是我真正开始变得娇气的地方.我有一种直觉,我应该创建一个与Jenkins一起使用的新的公钥/私钥.我的思维过程是如果jenkins守护程序被泄露,那么我可以轻松地撤销Apple的Provisioning Portal中的证书并生成另一个公钥/私钥.如果我为我的用户帐户和Jenkins使用相同的密钥和证书,那么如果jenkins服务受到攻击,则意味着更麻烦(损坏?).

指向Simon Urbanek的答案,您将使用纯文本密码从脚本中解锁钥匙串.在jenkins守护程序的钥匙串中保留除"一次性"证书和钥匙之外的任何东西似乎是不负责任的.

我对任何相反的讨论都很感兴趣.我是否过于谨慎?

要在终端I中创建一个新的CSR作为jenkins守护进程,请执行以下操作...

  1. sudo su jenkins
  2. certtool r CertificateSigningRequest.certSigningRequest 系统会提示您输入以下内容(其中大部分是我在正确的答案中做出了有根据的猜测;您有更好的见解吗?请分享.)...
    • 输入密钥和证书标签:
    • 选择算法:( r对于RSA)
    • 以位为单位输入密钥大小: 2048
    • 选择签名算法:( 5对于MD5)
    • 输入挑战字符串:
    • 然后是RDN的一堆问题
  3. 使用新的Apple ID将生成的CSR文件(CertificateSigningRequest.certSigningRequest)提交到Apple的Provisioning Portal
  4. 批准请求并下载.cer文件
  5. security unlock-keychain
  6. security add-certificate ios_development.cer

这让我们更近了一步......

问题3:供应配置文件和钥匙串解锁

我在Provisioning Portal中创建了一个特殊的配置文件,只是为了与CI一起使用,希望如果发生了不好的事情,我的影响会小一点.最佳做法还是过于谨慎?

  1. sudo su jenkins
  2. mkdir ~/Library/MobileDevice
  3. mkdir ~/Library/MobileDevice/Provisioning\ Profiles
  4. 将您在Provisioning Portal中设置的配置文件移动到此新文件夹中.我们现在距离能够以命令行的形式运行xcodebuild只有两步之遥,因为这意味着我们也能够让Jenkins CI运行构建.
  5. security unlock-keychain -p <keychain password>
  6. xcodebuild -target MyTarget -sdk iphoneos

现在,当我们以jenkins守护进程登录时,我们从命令行获得了成功的构建,因此如果我们创建一个自由风格的项目并添加最后两个步骤(上面的#5和#6),我们将能够自动构建我们的iOS项目!

它可能没有必要,但在我成功完成所有这些设置后,我觉得将jenkins UserShell设置回/ usr/bin/false会更好.我是偏执狂吗?

问题4:默认钥匙串仍然无法使用!

(编辑:我发布了对我的问题的编辑,重新启动以确保我的解决方案是100%,当然,我已经省略了一步)

即使执行了上述所有步骤,您仍需要在/Library/LaunchDaemons/org.jenkins-ci.plist中修改Launch Daemon plist,如本答案中所述.请注意,这也是一个openrdar错误.

它应该如下所示:

<?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>daemon</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>
        <!-- **NEW STUFF** -->
        <key>SessionCreate</key>
        <true />
</dict>
</plist>
Run Code Online (Sandbox Code Playgroud)

有了这个设置,我还推荐JenkinsXcode插件,这使得设置xcodebuild脚本更容易一些.在这一点上,我还建议阅读xcodebuild的手册页 - 你到底在终端做到了,对吧?

这种设置并不完美,非常感谢任何建议或见解.

我很难选择一个"正确"的答案,因为我用它来解决我的问题只是每个人的输入集合.我试图给每个人至少一个投票,但是给了西蒙的答案,因为他主要回答了原来的问题.此外,Sami Tikka因为让Jenkins通过AppleScript作为普通的OS X应用程序而努力,值得称赞.如果您只想让Jenkins在您的用户会话中快速上手(即不是无头服务器),那么他的解决方案就像Mac一样.

我希望我的努力引发进一步的讨论,并帮助下一个可怜的灵魂,他们认为他们可以在一个周末为他们的iOS项目安装Jenkins CI,因为他们听到了所有关于它的精彩内容.


更新:2013年8月9日

有这么多的赞成票和最爱,我想我会在18个月后再回过头来学习一些简短的经验教训.

第1课:不要将Jenkins暴露在公共互联网上

在2012 WWDC上,我将这个问题提交给Xcode和OS X Server工程师.我收到了一声"不要那样做!"的杂音.来自我问过的任何人.他们都同意自动构建过程很棒,但服务器只能在本地网络上访问.OS X Server工程师建议允许通过VPN进行远程访问.

第2课:现在有新的安装选项

我最近给了一个CocoaHeads谈论我的Jenkins体验,令我惊讶的是我发现了一些新的安装方法 - Homebrew甚至是Bitnami Mac App Store版本.这些绝对值得一试.乔纳森赖特有一个详细的要求让Homebrew Jenkins工作.

第3课:不,严重的是,不要将构建盒暴露在互联网上

从原始帖子中可以清楚地看出,我既不是系统管理员,也不是安全专家.关于私人东西(钥匙串,凭证,证书等)的常识让我对将詹金斯盒子放在互联网上感到非常不安.在这篇文章中,Neglected Potential的Nick Arnott能够很容易地确认我的heebie-jeebies .

TL; DR

在过去一年半的时间里,我向其他寻求自动化构建过程的人的建议发生了变化.确保您的Jenkins机器位于防火墙后面.使用安装程序,Bitnami Mac App Store版本,Sami Tikka的AppleScript等安装和设置Jenkins作为专用的Jenkins用户; 这解决了我上面详述的大部分问题.如果您需要远程访问,在OS X Server中设置VPN服务需要十分钟的时间.我已经使用这个设置超过一年,我很高兴.祝好运!

Sim*_*nek 30

钥匙串需要先解锁才能使用.你可以security unlock-keychain用来解锁.您可以以交互方式(更安全)或通过在命令行上指定密码(不安全)来执行此操作,例如:

security unlock-keychain -p mySecretPassword...
Run Code Online (Sandbox Code Playgroud)

显然,将其放入脚本会危及该钥匙串的安全性,因此通常人们只使用签名凭证设置单独的钥匙串,以最大限度地减少此类损害.

通常,Terminal钥匙串已经被您的会话解锁,因为默认钥匙串在登录时解锁,因此您不需要这样做.但是,任何未在您的会话中运行的进程都不会有解锁的钥匙串,即使它是您作为用户(最常见的是影响ssh,但也包括任何其他进程).


Zsu*_*sub 12

假设您还想通过Jenkins进行临时分发,这就要求除了配置文件外,Jenkins还可以访问分发证书和团队管理员身份.

使用.cer文件中的导出标识,您可以通过编程方式导入它,-A开关允许所有程序访问此条目.或者,您可以使用多个-T /path/to/program开关来允许codesignxcodebuild访问:

$ security import devcertificate.cer -k jenkins.keychain -A
Run Code Online (Sandbox Code Playgroud)

当然,我们也应该拥有Apple WWDCRA证书,以几乎相同的方式导入:

$ security import AppleWWDRCA.cer -k jenkins.keychain -A
Run Code Online (Sandbox Code Playgroud)

但是,我们还需要私钥devcertificate.cer.为此,您需要将相应的私钥导出为.p12密钥并设置密码.把它放在你可以从你的Jenkins shell访问它,解锁钥匙串并导入它的地方:

$ security unlock-keychain -p YourKeychainPass jenkins.keychain
$ security import devprivatekey.p12 -k login.keychain -P ThePasswordYouSetWhenExporting -A
Run Code Online (Sandbox Code Playgroud)

导入分发证书的方式相同.我不知道为什么你需要解锁用于导入.p12的钥匙串而不是用于.cer,但是.

您还需要访问配置文件,我将很快将这些说明编辑到此帖子中.


bri*_*tey 5

我遇到了同样的问题,并且一直在寻找答案。这是我学到的一件事。

我正在以jenkins用户(由安装程序创建的用户)运行jenkins,正如其他所有人所提到的那样,他没有访问权限与普通用户相同。我没有尝试以jenkins用户身份登录,而是创建了第二个构建项目,该项目仅具有一个构建步骤,即“ Execute Shell”,在其中运行要作为jenkins用户测试的命令。

设置好之后,我可以运行命令

security list-keychains

这告诉我,詹金斯唯一能看到的就是系统钥匙串。

+ security list-keychains
    "/Library/Keychains/System.keychain"
    "/Library/Keychains/System.keychain"
Run Code Online (Sandbox Code Playgroud)

有了这些知识,然后我打开了钥匙串访问应用程序,并将我的“ iPhone Developer:xxxx”证书复制到了系统钥匙串中(右键单击,从“登录”钥匙串中复制)。

这使我通过了证书/私钥对代码签名错误,但是又打开了一个具有配置文件的文件(似乎是类似但不同的问题)。

  • 我发现Jenkins用户的配置文件存储在“ / Users / Shared / Jenkins / Library / MobileDevice / Provisioning Profiles”中,因此在构建过程中迈出了一步,将配置文件从git repo内部复制到该位置。这使我可以更新配置文件并将其推送到SCM中,Jenkins会自动选择该更改。 (2认同)

Ivo*_*cet 5

要更改密码,您可以使用sudo passwd jenkins <new-pw>.但是我认为最好使用dscl命令来更改密码.

在我的安装中,jenkins(官方安装程序)有一个用户shell/usr/bin/false.将其更改为bash解决了无法登录的问题:

sudo dscl . -change /Users/jenkins UserShell /usr/bin/false /bin/bash
Run Code Online (Sandbox Code Playgroud)

您现在应该可以登录了su jenkins.