Jenkins在OS X上:xcodebuild给出了Code Sign的错误

概要:

使用最新的安装程序( 截至2012年3月9日1.449 ),在OS X上设置Jenkins非常容易,但pipe理代码签名过程仍然非常困难,没有直接的答案。

动机:

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

背景:

  • 2009年10月12日 – 如何自动化您的iPhone应用程序与哈德森build立
  • 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的Xcodeconfiguration文件找不到
  • 2011年9月20日 – 如何在Mac上设置Jenkins CI
  • 2011年9月14日 – 让jenkins在Mac上运行
  • 2011年11月12日 – Howto:在OS X上安装Jenkins,并使其构buildMac的东西
  • 2012年1月23日 – 即将推出的Jenkins OSX安装程序更改
  • 2012年3月7日 – 感谢您使用OSX安装程序

处理:

通过OS X 安装程序包安装Jenkins CI。 对于“安装types”步骤,单击“自定义”button,然后select“在启动时作为'jenkins'开始。”

讨论:

在这一点上的天真的期望是一个自由风格的项目与构build脚本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

很明显,需要发生什么 – 您需要将有效的代码签名证书和私钥添加到默认的钥匙串中。 在研究如何做到这一点,我还没有find一个解决scheme,不开放系统到一定程度的漏洞。

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

sudo -u jenkins security default-keychain …产生“找不到默认钥匙串”

正如下面Ivo Dancet指出的那样, 默认情况下 ,UserShell被设置为/ usr / bin / false作为jenkins守护进程(我认为这是一个function,而不是bug)。 按照他的答案将UserShell更改为bash。 然后你可以使用sudo su jenkins以jenkins用户身份login,并得到一个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

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

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

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

这是我真正开始变得娇气的地方。 我有一个直觉,我应该创build一个新的公钥/私钥与Jenkins一起使用。 我的思考过程是,如果jenkins守护进程受到威胁,那么我可以很容易地撤销苹果Provisioning Portal中的证书并生成另一个公钥/私钥。 如果我为我的用户帐户和jenkins使用相同的密钥和证书,那么如果jenkins服务受到攻击,则意味着更多的麻烦(损害?)。

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

我对任何相反的讨论都非常感兴趣。 我过于谨慎吗?

为了在terminal做一个新的CSR作为jenkins守护进程,做了以下…

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

这使我们更近了一步…

问题3:configuration文件和钥匙串解锁

我在configuration门户中提供了一个特殊的configuration文件,只是为了配合CI使用,希望如果发生不好的事情,我已经使影响变小了。 最佳做法还是过于谨慎?

  1. sudo su jenkins
  2. mkdir ~/Library/MobileDevice
  3. mkdir ~/Library/MobileDevice/Provisioning\ Profiles
  4. 将在Provisioning Portal中设置的供应configuration文件移动到此新文件夹中。 我们现在距离能够像jenkins一样从命令行运行xcodebuild只需要两步,所以这意味着我们也接近于能够运行Jenkins CI的构build。
  5. security unlock-keychain -p <keychain password>
  6. xcodebuild -target MyTarget -sdk iphoneos

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

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

问题4:默认钥匙串仍然不可用!

编辑:我发布了编辑我的问题,重新启动,以确保我的解决scheme是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脚本更容易一些。 在这一点上,我还build议阅读xcodebuild的手册页 – 你到底在terminal做到了这一点,对吗?

这种设置是不完美的,任何意见或见解,非常感谢。

我很难select一个“正确”的答案,因为我已经用来解决我的问题是一个几乎每个人的投入的集合。 我曾试图给每个人至less一个投票,但是把答案给了西蒙,因为他主要回答了原来的问题。 而且, Sami Tikka在努力让Jenkins通过AppleScript成为一个普通的OS X应用程序方面值得赞扬。 如果你只想让Jenkins在你的用户会话中快速启动(即不是一个无头的服务器),他的解决scheme更像Mac。

我希望我的努力能够引发进一步的讨论,并帮助下一个可怜的灵魂,他们认为他们可以在周末的时候为他们的iOS项目获得Jenkins CI的设置,因为他们听说过的所有奇妙的事情。


更新:2013年8月9日

有了这么多的赞扬和喜爱,我想我会回到这18个月后,一些简短的经验教训。

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

在2012年的WWDC上,我把这个问题交给了Xcode和OS X Server工程师。 我收到了一句不要那样做的杂音 从我问的任何人。 他们都同意自动构build过程非常好,但是服务器只能在本地networking上访问。 OS X Server工程师build议允许通过VPN进行远程访问。

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

我最近给了一个CocoaHeads关于我的Jenkins经验的讨论,而且让我惊讶的是我发现了一些新的安装方法 – Homebrew,甚至还有一个Bitnami Mac App Store版本。 这些绝对值得一试。 乔纳森·赖特(Jonathan Wright )的主旨是详细说明让jenkins(James Jenkins)在工作 。

第三课:不,严肃地说,不要把你的构build箱暴露给互联网

从原来的post可以看出,我既不是系统pipe理员,也不是安全专家。 关于private-y东西(keychains,证书,证书等)的常识让我感觉到把我的Jenkins盒子放在互联网上感到很不安。 尼克·阿诺特在被忽视的潜力能够很容易地在这篇文章中确认我的heebie-jeebies。

TL; DR

在过去一年半的时间里,我向其他人推荐的将自动化构build过程的build议改变了。 确保你的jenkins机器在你的防火墙后面。 使用安装程序,Bitnami Mac App Store版本,Sami Tikka的AppleScript等安装并设置Jenkins作为专门的Jenkins用户; 这解决了我上面详细介绍的大部分头痛。 如果您需要远程访问,则在OS X Server中设置VPN服务需要十分钟的时间。 我一直在使用这个设置一年多,并且非常满意。 祝你好运!

钥匙串在使用前需要解锁。 您可以使用security unlock-keychain解锁。 您可以交互式(更安全)或通过在命令行上指定密码(不安全)来做到这一点,例如:

 security unlock-keychain -p mySecretPassword... 

很明显,将这个脚本join到脚本中会危及到这个钥匙串的安全性,所以人们通常只用签名凭证来设置一个单独的钥匙串来减less这种损害。

通常在Terminal ,钥匙串已被您的会话解锁,因为默认钥匙串在login时被解锁,所以您不需要这样做。 然而,任何不会在你的会话中运行的进程都不会解锁钥匙串,即使它以用户身份(通常这会影响到ssh ,还有其他进程)。

假设您还想通过Jenkins进行临时分配,那么除了configurationconfiguration文件外,Jenkins还有权访问分发证书和团队pipe理员身份。

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

 $ security import devcertificate.cer -k jenkins.keychain -A 

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

 $ security import AppleWWDRCA.cer -k jenkins.keychain -A 

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

 $ security unlock-keychain -p YourKeychainPass jenkins.keychain $ security import devprivatekey.p12 -k login.keychain -P ThePasswordYouSetWhenExporting -A 

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

您还需要访问configuration文件,我将很快在这篇文章中编辑这些说明。

要更改密码,您可以使用sudo passwd jenkins <new-pw> 。 不过,我认为使用dscl命令来更改密码会更好。

在我的安装jenkins(官方安装程序)有一个用户shell / usr / bin / false。 更改为bash解决了无法login的问题:

 sudo dscl . -change /Users/jenkins UserShell /usr/bin/false /bin/bash 

你现在应该可以用su jenkinslogin了。

我有同样的问题,一直在四处寻找答案。 这是我学到的一件事。

我正在运行jenkins作为jenkins用户,由安装程序创build的用户,以及其他所有人都提到的,他无法访问与普通用户相同的钥匙串。 我没有试图以jenkins用户的身份login,而是创build了另一个构build项目,它只有一个构build步骤,即“Execute Shell”,我在其中运行要作为jenkins用户testing的命令。

一旦我build立了,我就可以运行命令

security list-keychains

这让我意识到jenkins唯一能看到的就是系统钥匙扣。

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

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

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

对于有钥匙链问题的人,我build议你在https://github.com/stisti/jenkins-app下试试我另类的Jenkins安装程序,在https://github.com/stisti/jenkins-app/downloads下载;

Jenkins.app在用户会话中运行Jenkins,所以钥匙串访问问题不是问题:)

我已经使用Xcode插件来构buildiOS应用程序。 在一个项目的configuration。

select添加构build步骤> Xcode>代码签名和OS X钥匙串选项。

打勾解锁钥匙串框,并添加如下(举例) 在这里输入图像说明

somtimes,如果我得到错误

代码签名错误:…

我将重新打开jenkins,并再次input密码解锁

如果你有sudo,你可以使用passwd来改变Jenkins用户的密码。 然后你可以得到jenkins的密码。

另外,我不确定这是否是您的问题,但我通过Jenkins使用的ANT脚本有这样的:

 <target name="unlock_keychain"> <exec executable="security"> <arg value="-v"/> <arg value="unlock-keychain"/> <arg value="-p"/> <arg value="<My Password>"/> <arg value="/Users/macbuild/Library/Keychains/login.keychain"/> </exec> </target> 

出于某种原因,“安全”实用程序不适用于我与新鲜的jenkins安装狮子。

在“sudo su jenkins”之后,它能够创build新的钥匙串,但是默默地忽略了所有返回零退出状态的“default-keychain -s …”或“unlock”命令并且不向控制台打印任何东西。 上市的默认或login钥匙链没有给予,钥匙串search列表只包含系统钥匙串,我不能改变这一点,无论我input。

login到该用户的桌面并启动钥匙串实用程序后,它确实显示了我创build的钥匙串,之后所有工作都按照上面的post中的描述进行。

我想知道在Lion中是否有一些初始钥匙串行为发生了变化,或者我错过了什么?

我将公司的私钥和公钥添加到了钥匙链中。 我添加了我将要生产的产品的configuration文件。

由于这个用户没有一个帐户,我login到devcenter与我的帐户。 下载configuration证书并将其加载到Xcode中。

我没有专门为构buildangular色帐户添加证书,例如。 jenkins。

我没有把这个添加到构build脚本:security unlock-keychain -p mySecretPassword如上,但…

我创build了一个文件〜/ .ssh / mypass并将密码添加到文件中。

然后命令变成:security unlock-keychain -p cat ~/.ssh/mypass

构build工作就像一个冠军。 我得到的ipa文件,它加载在应用程序中央,并在设备上工作。

也可以安装和启动JenkinsCI作为OS X用户而不是守护进程:

  1. 使用官方安装程序( https://jenkins-ci.org/ )安装jenkins
    • 点击下一步
    • 点击“自定义”
    • 取消select“开始启动为'jenkins'” – *重要*此选项通常允许无法使用jenkins,无法使用钥匙串访问
  2. 启动http://127.0.0.1:8080
    • validation它不会启动
    • 可能需要停止jenkins sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plist org.jenkins- sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plist
  3. 双击/Applications/Jenkins/jenkins.war
    • 当然这应该是自动启动@启动
  4. 打开http://127.0.0.1:8080
    • validation它现在正在运行