摘要:
使用最新的安装程序(截至1.449-2012年3月9日),在OS X上设置Jenkins变得非常容易,但是,管理代码签名的过程仍然非常困难,没有简单的答案。
动机:
运行无头CI服务器,该服务器遵循在OS X上运行服务的常见最佳实践(此处以通俗的语言进行了解释)。
背景:
处理:
通过OS X 安装程序包安装Jenkins CI 。对于“安装类型”步骤,单击“自定义”按钮,然后选择“以’jenkins身份启动”。
讨论:
此时的天真期望是,带有构建脚本的自由样式项目xcodebuild -target MyTarget -sdk iphoneos应该可以工作。如该帖子的标题所示,它不是,并且失败:
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 …产生“找不到默认钥匙串”
sudo -u jenkins security default-keychain
正如Ivo Dancet在下面指出的那样,默认情况下,jenkins守护程序的UserShell设置为/ usr / bin / false(我认为这是一个功能,而不是错误)。按照他的回答将UserShell更改为bash。然后,您可以使用sudo sujenkins以jenkins用户身份登录并获得bash提示。
sudo sujenkins
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中作为自由样式项目运行,则将看到唯一可用的钥匙串是系统钥匙串。我认为这是大多数人想到的将证书和密钥放入其中的想法。但是,这似乎是一个非常糟糕的主意- 特别是考虑到您需要使用密码创建纯文本脚本来打开钥匙串。
security list-keychains
问题2:添加代码签名证书和私钥
这就是我真正开始变得娇气的地方。我有一种直觉,我应该创建一个新的专用于Jenkins的公共/私有密钥。我的想法是,如果jenkins守护程序受到威胁,那么我可以轻松地在Apple的Provisioning Portal中吊销证书并生成另一个公共/私有密钥。如果我为我的用户帐户和Jenkins使用相同的密钥和证书,那么如果jenkins服务受到攻击,则意味着更加麻烦(损坏?)。
指向Simon Urbanek的答案,您将使用纯文本密码从脚本中解锁钥匙串。在jenkins守护程序的钥匙串中保留“一次性”证书和钥匙以外的任何东西似乎是不负责任的。
我对任何相反的讨论都非常感兴趣。 我是否过于谨慎?
为了在Terminal中创建新的CSR作为jenkins守护进程,我做了以下工作…
certtool r CertificateSigningRequest.certSigningRequest
r
2048
5
security unlock-keychain
security add-certificate ios_development.cer
这使我们更近了一步…
问题3:配置配置文件和钥匙串解锁
我在Provisioning Portal中创建了一个特殊的配置文件,以供CI使用,希望如果发生一些问题,我的影响会减小一些。最佳做法还是过于谨慎?
mkdir ~/Library/MobileDevice
mkdir ~/Library/MobileDevice/Provisioning\ Profiles
security unlock-keychain -p <keychain password>
现在,当以jenkins守护程序身份登录时,可以从命令行获得成功的构建,因此,如果我们创建一个自由样式项目并添加最后两个步骤(上述#5和#6),我们将能够自动构建我们的iOS项目!
可能没有必要,但是在我成功完成所有设置之后,我感觉最好将jenkins UserShell设置回/ usr / bin / false。我是偏执狂吗?
问题4:默认钥匙串仍然不可用!
( 编辑:我将修改发布到我的问题上,重新启动以确保我的解决方案是100%,当然,我省去了一步 )
即使完成上述所有步骤,您仍需要按照此答案中的说明在/Library/LaunchDaemons/org.jenkins-ci.plist上修改LaunchDaemon 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中做到了,对吧?
此设置不是完美的,非常感谢您提供任何建议或见解。
我很难选择一个“正确”的答案,因为我用来解决问题的方法是收集几乎每个人的意见。我已经尝试过至少给所有人投票,但将答案授予西蒙,因为他主要回答了原始问题。此外,萨米·蒂卡(SamiTikka)为使詹金斯(Jenkins)通过AppleScript作为普通的OSX应用程序而付出的努力值得称赞。如果您只想让Jenkins起来并在用户会话中快速运行(即不作为无头服务器),则他的解决方案更像Mac。
我希望我的努力能够引发进一步的讨论,并帮助下一个可怜的人,他们认为他们可以在一个周末为他们的iOS项目安装JenkinsCI,因为他们听说过许多奇妙的事情。
有了这么多的赞誉和喜爱,我想我会在18个月后回到这里,并吸取一些简短的经验教训。
第1课:不要让詹金斯接触到公共互联网
在2012年的WWDC上,我将这个问题带给了Xcode和OS XServer工程师。我听到“不要那样做!”的刺耳声音。我问过的任何人。他们都认为自动构建过程很棒,但是只能在本地网络上访问服务器。OS XServer工程师建议允许通过VPN进行远程访问。
第2课:现在有新的安装选项
我最近在CocoaHeads上介绍了我的詹金斯经历,而令我惊讶的是,我发现了一些新的安装方法-Homebrew甚至Bitnami Mac AppStore版本。这些绝对值得一试。乔纳森•赖特(Jonathan Wright)的要点是详细说明如何使Homebrew Jenkins工作。
第3课:不,认真的说,不要将构建箱暴露给互联网
从原始帖子中可以很明显地看出,我既不是系统管理员,也不是安全专家。关于私人物品的常识(钥匙串,凭证,证书等)使我对将我的詹金斯盒子放在互联网上感到不安。在这篇文章中,《被忽视的潜力》的尼克·阿诺特(Nick Arnott)可以很容易地确认我的希比·吉比斯。
TL; DR
在过去的一年半中,我对其他希望自动化其构建过程的人的建议发生了变化。确保您的Jenkins机器位于防火墙后面。使用安装程序,Bitnami Mac App Store版本,SamiTikka的AppleScript等将Jenkins安装并设置为Jenkins专用用户;这解决了我上面详述的大多数头痛问题。如果需要远程访问,则在OSXServer中设置VPN服务需要十分钟的时间。我已经使用此设置一年多了,对此我感到非常满意。祝好运!
钥匙串在使用前需要先解锁。您可以security unlock- keychain用来解锁。您可以以交互方式(更安全)或通过在命令行上指定密码(不安全)来执行此操作,例如:
security unlock- keychain
security unlock-keychain -p mySecretPassword...
显然,将其放入脚本会损害该钥匙串的安全性,因此人们经常使用仅签名凭证来设置单个钥匙串,以最大程度地减少此类损坏。
通常,Terminal钥匙串已被您的会话解锁,因为默认的钥匙串在登录时已解锁,因此您无需这样做。但是,即使会话没有在您的会话中运行,也不会将其解锁(最常见的情况是ssh,但也会影响其他任何进程)。
Terminal
ssh