摘要:
使用最新的安装程序(截至2012年3月9日) ,在 OS X 上安装 Jenkins 变得非常容易,但是管理代码签名过程仍然非常困难,没有直接的答案。
动机:
运行一个遵循在 OS X (其中一些在这里用简单的语言解释)上运行服务的常见最佳实践的无头 CI 服务器。
背景:
过程:
通过 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 提示符。
sudo su jenkins
cd ~/Library
mkdir Keychains
cd Keychains
security create-keychain <keychain-name>.keychain
security default-keychain -s <keychain-name>.keychain
好的,很好。我们现在有了一个默认的钥匙链,让我们继续吧?但是,首先我们为什么要费心制作一个默认的密钥链呢?
几乎所有的答案,建议,或对话,我阅读通过研究建议,一个人应该只是扔他们的代码签名证书和密钥到系统的钥匙链。如果您在 Jenkins 中将 security list-keychains
作为一个自由风格的项目来运行,您会看到唯一可用的密钥链是系统密钥链; 我认为这就是大多数人想到将他们的证书和密钥放入其中的想法的地方。但是,这似乎是一个非常糟糕的主意-特别是考虑到 您需要创建一个带密码的纯文本脚本来打开密钥链。
问题2: 添加代码签名证书和私钥
这时候我真的开始觉得恶心了。我有一种直觉,我应该创建一个新的公钥/私钥独特的使用与 Jenkins。我的想法是,如果 jenkins 守护进程被破坏,那么我可以很容易地撤销苹果供应门户中的证书,并生成另一个公钥/私钥。如果我为我的用户帐户和 Jenkins 使用相同的密钥和证书,那么这意味着更多的麻烦(损坏?)如果 Jenkins 服务受到攻击。
指向 Simon Urbanek 的回答,您将从一个脚本中解锁密钥链,该脚本使用纯文本密码。在 Jenkins 守护进程的钥匙链里,除了“一次性”的证书和钥匙,其他东西都留着,似乎是不负责任的。
我对任何相反的讨论都很感兴趣。我是不是过于谨慎了?
为了使一个新的 CSR 作为终端中的 jenkins 守护进程,我做了以下..。
sudo su jenkins
r
(用于 RSA)2048
5
(对于 MD5)security unlock-keychain
security add-certificate ios_development.cer
这让我们更进一步。
问题3: 提供配置文件和钥匙链解锁
我在 Provisioning Portal 做了一个特殊的供应配置文件,只是为了与 CI 一起使用,希望如果发生了什么不好的事情,我会让影响小一点。最佳实践还是过度谨慎?
sudo su jenkins
mkdir ~/Library/MobileDevice
mkdir ~/Library/MobileDevice/Provisioning\ Profiles
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 上的 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>
通过这种设置,我还推荐使用 詹金斯的 Xcode 插件,它使得设置 xcodebuild 脚本变得更容易一些。此时,我还建议您阅读 xcodebuild 的手册页——见鬼,您已经在 Terminal 中做到了这一步,对吗?
这种设置并不完美,任何建议或见解都非常值得赞赏。
我一直很难选择一个“正确”的答案,因为我用来解决我的问题是一个集合了几乎每个人的投入。我试着给每个人至少一张赞成票,但是把答案给西蒙,因为他基本上回答了最初的问题。此外,萨米 提卡值得大力赞扬他的努力,让詹金斯工作通过 AppleScript 作为一个普通的 OSX 应用程序。如果您只对让 Jenkins 在您的用户会话(即不是作为无头服务器)中快速运行感兴趣,那么他的解决方案更像 Mac。
我希望我的努力能够引发进一步的讨论,并且帮助下一个可怜的人,因为他们听说了很多关于詹金斯 CI 的美妙的事情,他们认为他们可以在一个周末为他们的 iOS 项目做好准备。
带着这么多的赞和喜好,我想我会在18个月后带着一些简短的经验教训回到这里。
第一课: 不要把 Jenkins 暴露在公共互联网上
在2012年的 WWDC 上,我向 Xcode 和 OSX 服务器的工程师们提出了这个问题。我听到了“不要那样做!”的不和谐声音不管我问谁。他们一致认为自动构建过程非常棒,但是服务器只能在本地网络上访问。OS X Server 工程师建议允许通过 VPN 进行远程访问。
第2课: 现在有了新的安装选项
最近,我给 CocoaHead 做了一个关于我的 Jenkins 经验的演讲,令我惊讶的是,我发现了一些新的安装方法—— Homebrew,甚至是 Bitnami Mac 应用程序商店版本。这些绝对值得一看。Jonathan Wright有一个要点详细说明获得 自制的 Jenkins 在工作。
第三课: 不,说真的,不要把你的构建框暴露在互联网上
从最初的帖子可以很清楚地看出,我既不是系统管理员,也不是安全专家。关于私人物品(钥匙链、证书、证书等)的常识让我对把我的詹金斯盒子放到互联网上感到非常不安。在被忽视的潜能 Nick Arnott能够确认我的神经过敏相当容易在 这篇文章。
DR
在过去一年半的时间里,我对其他寻求自动化构建过程的人的建议发生了变化。确保你的 Jenkins 机器在防火墙后面。使用安装程序、 Bitnami Mac App Store 版本、 Sami Tikka 的 AppleScript 等,安装并设置 Jenkins 为一个专用的 Jenkins 用户; 这解决了我上面详述的大部分头痛问题。如果需要远程访问,在 OS X Server 中设置 VPN 服务最多需要10分钟。我已经使用这个设置超过一年了,我对它非常满意。祝你好运!