Zusammenfassung:
Das Einrichten von Jenkins unter OS X wurde mit dem neuesten Installationsprogramm ( Stand: 1.449 - 9. März 2012 ) erheblich vereinfacht. Die Verwaltung des Codesignaturprozesses ist jedoch ohne einfache Antwort immer noch sehr schwierig.
Motivation:
Führen Sie einen kopflosen CI-Server aus, der den gängigen Best Practices für die Ausführung von Diensten unter OS X folgt ( von denen einige hier im Klartext erläutert werden ).
Hintergrund:
- 12. Oktober 2009 - So automatisieren Sie die Erstellung Ihrer iPhone-App mit Hudson
- 15. Juni 2011 - Jenkins unter Mac OS X; Git w / ssh öffentlichen Schlüssel
- 23. Juni 2011 - Kontinuierliche Bereitstellung von iOS-Apps mit Jenkins und TestFlight
- 26. Juli 2011 - Fehlende Zertifikate und Schlüssel im Schlüsselbund bei Verwendung von Jenkins / Hudson als kontinuierliche Integration für die iOS- und Mac-Entwicklung
- 30. August 2011 - Xcode-Bereitstellungsdatei bei Jenkins nicht gefunden
- 20. September 2011 - So richten Sie Jenkins CI auf einem Mac ein
- 14. September 2011 - Jenkins auf einem Mac zum Laufen bringen
- 12. November 2011 - Howto: Installieren Sie Jenkins unter OS X und lassen Sie es Mac-Inhalte erstellen
- 23. Januar 2012 - Bevorstehende Änderungen am Jenkins OSX-Installationsprogramm
- 7. März 2012 - Vielen Dank, dass Sie OSX Installer verwenden
Prozess:
Installieren Sie Jenkins CI über das OS X- Installationspaket . Klicken Sie für den Schritt "Installationstyp" auf die Schaltfläche "Anpassen" und wählen Sie "Beim Booten als" Jenkins "beginnen."
Diskussion:
Die naive Erwartung an diesem Punkt war, dass ein Projekt im freien Stil mit dem Build-Skript xcodebuild -target MyTarget -sdk iphoneos
funktionieren sollte. Wie aus dem Titel dieses Beitrags hervorgeht, funktioniert und schlägt dies nicht mit:
Code Sign error: The identity 'iPhone Developer' doesn't match any valid certificate/private key pair in the default keychain
Es ist offensichtlich genug, was passieren muss - Sie müssen dem Standardschlüsselbund ein gültiges Codesignaturzertifikat und einen privaten Schlüssel hinzufügen. Bei der Untersuchung, wie dies erreicht werden kann, habe ich keine Lösung gefunden, die das System nicht für ein gewisses Maß an Sicherheitslücke öffnet.
Problem 1: Kein Standardschlüsselbund für Jenkins Daemon
sudo -u jenkins security default-keychain
... ergibt "Ein Standardschlüsselbund konnte nicht gefunden werden"
Wie unten von Ivo Dancet ausgeführt , ist die UserShell für den Jenkins-Daemon standardmäßig auf / usr / bin / false eingestellt (ich denke, dies ist eine Funktion, kein Fehler). Folgen Sie seiner Antwort, um die UserShell in Bash zu ändern. Sie können sich dann sudo su jenkins
als Jenkins-Benutzer anmelden und eine Bash-Eingabeaufforderung erhalten.
sudo su jenkins
cd ~/Library
mkdir Keychains
cd Keychains
security create-keychain <keychain-name>.keychain
security default-keychain -s <keychain-name>.keychain
OK großartig. Wir haben jetzt einen Standardschlüsselbund. Lass uns weitermachen, oder? Aber warum haben wir uns überhaupt die Mühe gemacht, einen Standardschlüsselbund zu erstellen?
Fast alle Antworten, Vorschläge oder Konversationen, die ich während der Recherche gelesen habe, deuten darauf hin, dass man nur die Codesignaturzertifikate und -schlüssel in den Systemschlüsselbund stecken sollte. Wenn Sie security list-keychains
in Jenkins als Projekt im freien Stil ausgeführt werden, sehen Sie, dass der einzige verfügbare Schlüsselbund der Systemschlüsselbund ist. Ich denke, dort kamen die meisten Leute auf die Idee, ihr Zertifikat und ihren Schlüssel dort abzulegen. Dies scheint jedoch nur eine sehr schlechte Idee zu sein - insbesondere, da Sie zum Öffnen des Schlüsselbunds ein Nur- Text-Skript mit dem Kennwort erstellen müssen .
Problem 2: Hinzufügen von Codesignaturzertifikaten und privatem Schlüssel
Hier fange ich wirklich an, zimperlich zu werden. Ich habe das Gefühl, dass ich einen neuen öffentlichen / privaten Schlüssel erstellen sollte, der für die Verwendung mit Jenkins einzigartig ist. Mein Denkprozess ist, wenn der Jenkins-Daemon kompromittiert ist, kann ich das Zertifikat im Apple Provisioning Portal problemlos widerrufen und einen weiteren öffentlichen / privaten Schlüssel generieren. Wenn ich denselben Schlüssel und dasselbe Zertifikat für mein Benutzerkonto und Jenkins verwende, bedeutet dies mehr Aufwand (Schaden?), Wenn der Jenkins-Dienst angegriffen wird.
Wenn Sie auf die Antwort von Simon Urbanek zeigen , entsperren Sie den Schlüsselbund aus einem Skript mit einem Nur-Text-Passwort. Es scheint unverantwortlich, alles andere als "Einweg" -Zertifikate und -Schlüssel im Schlüsselbund des Jenkins-Dämons zu behalten.
Ich bin sehr an gegenteiligen Diskussionen interessiert. Bin ich übermäßig vorsichtig?
Um einen neuen CSR als Jenkins-Daemon im Terminal zu erstellen, habe ich Folgendes getan ...
sudo su jenkins
certtool r CertificateSigningRequest.certSigningRequest
Sie werden zu Folgendem aufgefordert (die meisten davon habe ich bei der richtigen Antwort gut erraten; haben Sie bessere Einsichten? Bitte teilen Sie.) ...- Schlüssel und Zertifikatetikett eingeben:
- Algorithmus auswählen:
r
(für RSA) - Geben Sie die Schlüsselgröße in Bit ein:
2048
- Signaturalgorithmus auswählen:
5
(für MD5) - Geben Sie die Herausforderungszeichenfolge ein:
- Dann ein paar Fragen an RDN
- Senden Sie die generierte CSR-Datei (CertificateSigningRequest.certSigningRequest) unter einer neuen Apple ID an das Apple Provisioning Portal
- Genehmigen Sie die Anforderung und laden Sie die CER-Datei herunter
security unlock-keychain
security add-certificate ios_development.cer
Dies bringt uns einen Schritt näher ...
Problem 3: Bereitstellungsprofil und Entsperren des Schlüsselbunds
Ich habe im Provisioning Portal ein spezielles Provisioning-Profil erstellt, das nur für die Verwendung mit CI bestimmt ist, in der Hoffnung, dass ich die Auswirkungen etwas verringert habe, wenn etwas Schlimmes passiert. Best Practice oder übermäßig vorsichtig?
sudo su jenkins
mkdir ~/Library/MobileDevice
mkdir ~/Library/MobileDevice/Provisioning\ Profiles
- Verschieben Sie das im Bereitstellungsportal eingerichtete Bereitstellungsprofil in diesen neuen Ordner. Wir sind jetzt zwei kurze Schritte davon entfernt, xcodebuild über die Befehlszeile als Jenkins auszuführen, und das bedeutet, dass wir auch kurz davor sind, die Jenkins CI-Builds zum Laufen zu bringen.
security unlock-keychain -p <keychain password>
xcodebuild -target MyTarget -sdk iphoneos
Jetzt erhalten wir eine erfolgreiche Erstellung über eine Befehlszeile, wenn wir als Jenkins-Daemon angemeldet sind. Wenn wir also ein Projekt im freien Stil erstellen und die letzten beiden Schritte (Nr. 5 und Nr. 6 oben) hinzufügen, können wir die Erstellung von automatisieren unser iOS Projekt!
Es ist vielleicht nicht notwendig, aber ich fühlte mich besser, jenkins UserShell wieder auf / usr / bin / false zu setzen, nachdem ich all dieses Setup erfolgreich erhalten hatte. Bin ich paranoid?
Problem 4: Standardschlüsselbund immer noch nicht verfügbar!
( BEARBEITEN: Ich habe die Änderungen an meiner Frage veröffentlicht, neu gestartet, um sicherzustellen, dass meine Lösung 100% ist, und natürlich habe ich einen Schritt ausgelassen. )
Selbst nach allen oben genannten Schritten müssen Sie die Launch Daemon-Liste unter /Library/LaunchDaemons/org.jenkins-ci.plist wie in dieser Antwort angegeben ändern . Bitte beachten Sie, dass dies auch ein openrdar-Fehler ist .
Es sollte so aussehen:
<?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>
Mit diesem Setup würde ich auch das Xcode-Plugin für Jenkins empfehlen , was das Einrichten des xcodebuild-Skripts ein wenig erleichtert. An dieser Stelle würde ich auch empfehlen, die Manpages für xcodebuild zu lesen - verdammt, Sie haben es so weit im Terminal geschafft, oder?
Dieses Setup ist nicht perfekt und jeder Rat oder jede Einsicht wird sehr geschätzt.
Es fiel mir schwer, eine "richtige" Antwort auszuwählen, da ich zur Lösung meines Problems eine Sammlung von nahezu allen Eingaben verwendet habe. Ich habe versucht, allen mindestens eine Gegenstimme zu geben, aber Simon die Antwort zugesprochen, weil er meistens die ursprüngliche Frage beantwortet hat. Darüber hinaus verdient Sami Tikka viel Anerkennung für seine Bemühungen, Jenkins dazu zu bringen, AppleScript als einfache alte OS X-App zu verwenden. Wenn Sie nur daran interessiert sind, Jenkins in Ihrer Benutzersitzung schnell zum Laufen zu bringen (dh nicht als kopfloser Server), ist seine Lösung viel Mac-ähnlicher.
Ich hoffe, dass meine Bemühungen weitere Diskussionen anregen und der nächsten armen Seele helfen, zu glauben, dass sie Jenkins CI-Setup für ihre iOS-Projekte an einem Wochenende erhalten können, aufgrund all der wunderbaren Dinge, die sie darüber gehört haben.
Update: 9. August 2013
Bei so vielen positiven Stimmen und Favoriten dachte ich, ich würde 18 Monate später mit einigen kurzen Lektionen darauf zurückkommen.
Lektion 1: Setzen Sie Jenkins nicht dem öffentlichen Internet aus
Auf der WWDC 2012 habe ich diese Frage an die Ingenieure von Xcode und OS X Server weitergeleitet. Ich erhielt die Kakophonie "Tu das nicht!" von jemandem, den ich gefragt habe. Alle waren sich einig, dass ein automatisierter Erstellungsprozess großartig war, dass der Server jedoch nur über das lokale Netzwerk zugänglich sein sollte. Die Ingenieure von OS X Server schlugen vor, den Remotezugriff über VPN zuzulassen.
Lektion 2: Es gibt jetzt neue Installationsoptionen
Ich habe kürzlich einen CocoaHeads-Vortrag über meine Jenkins-Erfahrung gehalten und zu meiner großen Überraschung einige neue Installationsmethoden gefunden - Homebrew und sogar eine Bitnami Mac App Store- Version. Diese sind definitiv einen Besuch wert. Jonathan Wright hat einen Überblick darüber, wie Homebrew Jenkins funktioniert .
Lektion 3: Nein, im Ernst, setzen Sie Ihre Build-Box nicht dem Internet aus
Aus dem ursprünglichen Beitrag geht ziemlich klar hervor, dass ich weder Systemadministrator noch Sicherheitsexperte bin. Der gesunde Menschenverstand in Bezug auf private Dinge (Schlüsselanhänger, Anmeldeinformationen, Zertifikate usw.) ließ mich ziemlich unruhig werden, wenn ich meine Jenkins-Box ins Internet stellte. Nick Arnott von Neglected Potential konnte meine Heebie-Jeebies in diesem Artikel ziemlich leicht bestätigen .
TL; DR
Meine Empfehlung an andere, die ihren Erstellungsprozess automatisieren möchten, hat sich in den letzten anderthalb Jahren geändert. Stellen Sie sicher, dass sich Ihr Jenkins-Computer hinter Ihrer Firewall befindet. Installieren und einrichten Sie Jenkins als dedizierten Jenkins-Benutzer, entweder mithilfe des Installationsprogramms, der Bitnami Mac App Store-Version, des AppleScript von Sami Tikka usw.; Dies löst die meisten der oben beschriebenen Kopfschmerzen. Wenn Sie Remotezugriff benötigen, dauert das Einrichten von VPN-Diensten in OS X Server höchstens zehn Minuten. Ich benutze dieses Setup seit über einem Jahr und bin sehr zufrieden damit. Viel Glück!