摘要:
使用最新的安装程序(截至1.449-2012年3月9日),在OS X上设置Jenkins变得非常容易,但是,管理代码签名的过程仍然非常困难,没有简单的答案。
动机:
运行无头CI服务器,该服务器遵循在OS X上运行服务的常见最佳实践(此处以通俗的语言进行了解释)。
背景:
- 2009年10月12日- 如何使用Hudson使您的iPhone应用程序构建自动化
- 2011年6月15日-Jenkins在Mac OS X上;git w / ssh公钥
- 2011年6月23日- 通过Jenkins和TestFlight持续部署iOS应用
- 2011年7月26日- 使用Jenkins / Hudson作为iOS和Mac开发的持续集成时,缺少钥匙串中的证书和密钥
- 2011年8月30日-Jenkins找不到Xcode Provisioning文件
- 2011年9月20日- 如何在Mac上设置Jenkins CI
- 2011年9月14日- 在Mac上运行Jenkins
- 2011年11月12日 -Howto:在OS X上安装Jenkins并使其构建Mac系统
- 2012年1月23日- 即将推出的Jenkins OSX安装程序更改
- 2012年3月7日- 感谢您使用OSX安装程序
处理:
通过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(我认为这是一个功能,而不是错误)。按照他的回答将UserShell更改为bash。然后,您可以使用sudo su jenkins
以jenkins用户身份登录并获得bash提示。
sudo su jenkins
cd ~/Library
mkdir Keychains
cd Keychains
security create-keychain <keychain-name>.keychain
security default-keychain -s <keychain-name>.keychain
好,太棒了。现在,我们有了一个默认的钥匙串。让我们继续吧?但是,首先,为什么我们还要打扰默认钥匙串?
在整个研究过程中,我阅读的几乎所有答案,建议或对话都表明,应该将他们的代码签名证书和密钥丢到系统钥匙串中。如果您security list-keychains
在Jenkins中作为自由样式项目运行,则将看到唯一可用的钥匙串是系统钥匙串。我认为大多数人想到了将证书和密钥放入其中的想法。但是,这似乎是一个非常糟糕的主意-特别是考虑到您需要使用密码创建纯文本脚本来打开钥匙串。
问题2:添加代码签名证书和私钥
这就是我真正开始变得娇气的地方。我有一种直觉,我应该创建一个新的专用于詹金斯的公共/私人密钥。我的想法是,如果jenkins守护程序受到威胁,那么我可以轻松地在Apple的Provisioning Portal中吊销证书,并生成另一个公钥/私钥。如果我为我的用户帐户和Jenkins使用相同的密钥和证书,那么如果jenkins服务受到攻击,则意味着更加麻烦(损坏?)。
指向Simon Urbanek的答案,您将使用纯文本密码从脚本中解锁钥匙串。在jenkins守护程序的钥匙串中保留“一次性”证书和钥匙以外的任何东西似乎是不负责任的。
我对任何相反的讨论都非常感兴趣。我是否过于谨慎?
为了在Terminal中创建新的CSR作为jenkins守护进程,我做了以下工作...
sudo su jenkins
certtool r CertificateSigningRequest.certSigningRequest
系统会提示您输入以下内容(其中大多数是我对正确答案所作的有根据的猜测;您有更好的见解吗?请分享。)...- 输入密钥和证书标签:
- 选择算法:(
r
对于RSA) - 以位为单位输入密钥大小:
2048
- 选择签名算法:(
5
用于MD5) - 输入挑战字符串:
- 然后是有关RDN的一系列问题
- 使用新的Apple ID将生成的CSR文件(CertificateSigningRequest.certSigningRequest)提交到Apple的Provisioning Portal
- 批准请求并下载.cer文件
security unlock-keychain
security add-certificate ios_development.cer
这使我们更近了一步...
问题3:配置配置文件和钥匙串解锁
我在Provisioning Portal中创建了一个特殊的配置文件,以供CI使用,希望如果发生一些问题,我可以将影响减小一些。最佳做法还是过于谨慎?
sudo su jenkins
mkdir ~/Library/MobileDevice
mkdir ~/Library/MobileDevice/Provisioning\ Profiles
- 将您在Provisioning Portal中设置的供应配置文件移动到该新文件夹中。现在,距离能够以jenkins的形式从命令行运行xcodebuild尚有两步之遥,这意味着我们也即将获得运行Jenkins CI的构建。
security unlock-keychain -p <keychain password>
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>
通过此设置,我还将推荐用于Jenkins的Xcode插件,它使设置xcodebuild脚本更加容易。在这一点上,我还建议您阅读xcodebuild的手册页-到此为止,您在Terminal中做到了,对吧?
此设置不是完美的,非常感谢您提供任何建议或见解。
我很难选择一个“正确”的答案,因为我用来解决问题的方法是收集几乎每个人的意见。我试图至少给每个人一个投票,但将答案授予西蒙,因为他主要回答了原始问题。此外,萨米· 蒂卡(Sami Tikka)为使詹金斯(Jenkins)通过AppleScript作为普通的OS X应用程序而付出的努力值得称赞。如果您只想让Jenkins起来并在用户会话中快速运行(即不作为无头服务器),则他的解决方案更像Mac。
我希望我的努力能够引发进一步的讨论,并帮助下一个可怜的人,他们认为他们可以在一个周末为他们的iOS项目安装Jenkins CI,因为他们听说过很多奇妙的事情。
更新:2013年8月9日
有了这么多的赞誉和喜爱,我想我会在18个月后回到这里,并吸取一些简短的经验教训。
第1课:不要让詹金斯接触公共互联网
在2012年的WWDC上,我向Xcode和OS X Server工程师提出了这个问题。我听到“不要那样做!”的刺耳声音。我问过的任何人。他们都认为自动构建过程很棒,但是只能在本地网络上访问服务器。OS X Server工程师建议允许通过VPN进行远程访问。
第2课:现在有新的安装选项
我最近在CocoaHeads上介绍了我的詹金斯经历,而令我惊讶的是,我发现了一些新的安装方法-Homebrew甚至Bitnami Mac App Store版本。这些绝对值得一试。乔纳森•赖特(Jonathan Wright)有一个要点,详细说明了让Homebrew Jenkins工作。
第3课:不,认真的说,不要将构建箱暴露给互联网
从原始帖子中可以很明显地看出,我既不是系统管理员,也不是安全专家。关于私人物品的常识(钥匙串,证书,证书等)使我对将我的詹金斯盒子放在互联网上感到非常不安。在这篇文章中,《被忽视的潜力》的尼克·阿诺特(Nick Arnott)能够很容易地确认我的希比·吉比斯。
TL; DR
在过去的一年半中,我对其他希望自动化构建过程的人的建议发生了变化。确保您的Jenkins机器位于防火墙后面。使用安装程序,Bitnami Mac App Store版本,Sami Tikka的AppleScript等将Jenkins安装并设置为Jenkins专用用户;这解决了我上面详述的大多数头痛问题。如果需要远程访问,则在OS X Server中设置VPN服务需要十分钟的时间。我已经使用此设置一年多了,对此我感到非常满意。祝好运!