Résumé :
La configuration de Jenkins sous OS X a été considérablement simplifiée avec le plus récent installateur ( à partir de 1.449 - 9 mars 2012 ), mais la gestion du processus de signature du code reste très difficile et il n'y a pas de réponse directe.
Motivation :
Exécuter un serveur CI sans tête qui suit les meilleures pratiques courantes pour l'exécution de services sur OS X ( Certaines d'entre elles sont expliquées ici en langage clair ).
Le contexte :
- Le 12 octobre 2009 - Comment automatiser la création de vos applications iPhone avec Hudson ?
- Le 15 juin 2011 - Jenkins sur Mac OS X ; git avec clé publique ssh
- Le 23 juin 2011 - Déploiement continu d'applications iOS avec Jenkins et TestFlight
- 26 juillet 2011 - Certificats et clés manquants dans le trousseau de clés lors de l'utilisation de Jenkins/Hudson comme intégration continue pour le développement iOS et Mac
- Le 30 août 2011 - Fichier de provisionnement Xcode non trouvé avec Jenkins
- Le 20 septembre 2011 - Comment configurer Jenkins CI sur un Mac
- Le 14 septembre 2011 - Faire fonctionner Jenkins sur un Mac
- Le 12 novembre 2011 - Comment faire : Installer Jenkins sur OS X et lui faire construire des choses pour Mac
- Le 23 janvier 2012 - Prochaines modifications de l'installateur OSX de Jenkins
- Le 7 mars 2012 - Merci d'utiliser OSX Installer
Processus :
Installer Jenkins CI via OS X paquet d'installation . Pour l'étape "Type d'installation", cliquez sur le bouton Personnaliser, et choisissez "Démarrer au démarrage en tant que 'jenkins'".
Discussion :
L'attente naïve à ce stade était qu'un projet de style libre avec la construction script. xcodebuild -target MyTarget -sdk iphoneos
devrait fonctionner. Comme l'indique le titre de ce post, ce n'est pas le cas et il échoue avec :
Code Sign error: The identity 'iPhone Developer' doesn't match any valid certificate/private key pair in the default keychain
Ce qui doit se passer est assez évident : vous devez ajouter un certificat de signature de code valide et une clé privée dans le trousseau de clés par défaut. En cherchant comment accomplir cela, je n'ai pas trouvé de solution qui n'ouvre pas le système à un certain niveau de vulnérabilité.
Problème 1 : Pas de trousseau de clés par défaut pour le démon jenkins
sudo -u jenkins security default-keychain
...donne "Un trousseau par défaut n'a pas pu être trouvé".
Comme le souligne ci-dessous Ivo Dancet le UserShell est défini par défaut sur /usr/bin/false pour le daemon jenkins (je pense que c'est une fonctionnalité, pas un bug) ; suivez sa réponse pour changer le UserShell en bash. Vous pouvez alors utiliser sudo su jenkins
pour être connecté en tant qu'utilisateur de jenkins et obtenir une invite bash.
sudo su jenkins
cd ~/Library
mkdir Keychains
cd Keychains
security create-keychain <keychain-name>.keychain
security default-keychain -s <keychain-name>.keychain
Ok, super. Nous avons maintenant un trousseau par défaut, passons à autre chose, d'accord ? Mais d'abord, pourquoi avons-nous pris la peine de faire un trousseau par défaut ?
Presque toutes les réponses, suggestions ou conversations que j'ai lues au cours de mes recherches suggèrent que l'on devrait simplement balancer ses certificats de signature de code et ses clés dans le trousseau du système. Si vous exécutez security list-keychains
en tant que projet de style libre dans Jenkins, vous voyez que le seul trousseau disponible est le trousseau du système ; je pense que c'est là que la plupart des gens ont eu l'idée d'y placer leur certificat et leur clé. Mais, cela semble être une très mauvaise idée - surtout si l'on considère que vous devrez créer un script en texte brut avec le mot de passe pour ouvrir le trousseau. .
Problème 2 : Ajout des certs de signature de code et de la clé privée
C'est là que je commence vraiment à être dégoûté. J'ai l'intuition que je devrais créer une nouvelle clé publique/privée unique pour l'utilisation de Jenkins. Je pense que si le démon Jenkins est compromis, je peux facilement révoquer le certificat dans le portail de provisionnement d'Apple et générer une autre clé publique/privée. Si j'utilise la même clé et le même certificat pour mon compte d'utilisateur et Jenkins, cela signifie plus de tracas (dommages ?) si le service jenkins est attaqué.
Pointer vers La réponse de Simon Urbanek vous déverrouillerez le trousseau de clés à partir d'un script avec un mot de passe en texte clair. Il semble irresponsable de conserver autre chose que des certificats et des clés "jetables" dans le trousseau de clés du démon jenkins.
Je suis très intéressé par toute discussion contraire. Suis-je trop prudent ?
Pour créer un nouveau CSR en tant que démon jenkins dans le Terminal, j'ai fait ce qui suit...
sudo su jenkins
-
certtool r CertificateSigningRequest.certSigningRequest
Vous serez invité à répondre aux questions suivantes (pour la plupart, j'ai fait des suppositions sur la bonne réponse ; avez-vous une meilleure idée ? Veuillez partager.)...- Entrez la clé et l'étiquette du certificat :
- Sélectionnez l'algorithme :
r
(pour RSA) - Entrez la taille de la clé en bits :
2048
- Sélectionnez l'algorithme de signature :
5
(pour MD5) - Entrez la chaîne de défi :
- Puis une série de questions pour RDN
- Soumettez le fichier CSR généré (CertificateSigningRequest.certSigningRequest) au portail d'approvisionnement d'Apple sous un nouvel identifiant Apple.
- Approuver la demande et télécharger le fichier .cer.
security unlock-keychain
security add-certificate ios_development.cer
Cela nous rapproche un peu plus...
Problème 3 : Profil de provisionnement et déverrouillage du trousseau de clés
J'ai créé un profil de provisionnement spécial dans le portail de provisionnement uniquement pour l'utilisation de CI, dans l'espoir que si quelque chose de grave se produit, l'impact sera un peu plus faible. Meilleure pratique ou excès de prudence ?
sudo su jenkins
mkdir ~/Library/MobileDevice
mkdir ~/Library/MobileDevice/Provisioning\ Profiles
- Déplacez le profil de provisionnement que vous avez configuré dans le portail de provisionnement dans ce nouveau dossier. Nous sommes maintenant à deux petits pas de pouvoir exécuter xcodebuild à partir de la ligne de commande comme jenkins, et donc cela signifie que nous sommes également proches de pouvoir obtenir le CI de Jenkins exécutant des constructions.
security unlock-keychain -p <keychain password>
xcodebuild -target MyTarget -sdk iphoneos
Maintenant, nous obtenons une construction réussie à partir d'une ligne de commande lorsque nous sommes connectés en tant que démon jenkins, donc si nous créons un projet de style libre et ajoutons ces deux dernières étapes (#5 et #6 ci-dessus), nous serons en mesure d'automatiser la construction de notre projet iOS !
Ce n'est peut-être pas nécessaire, mais je me suis senti mieux en remettant jenkins UserShell à /usr/bin/false après avoir réussi à configurer tout cela. Suis-je paranoïaque ?
Problème 4 : le trousseau par défaut n'est toujours pas disponible !
( EDIT : J'ai posté les modifications apportées à ma question, j'ai redémarré pour m'assurer que ma solution était à 100%, et bien sûr, j'avais oublié une étape. )
Même après toutes les étapes ci-dessus, vous devrez modifier le plist du Launch Daemon dans /Library/LaunchDaemons/org.jenkins-ci.plist comme indiqué dans cette réponse . Veuillez noter qu'il s'agit également d'un bug d'openrdar .
Il devrait ressembler à ceci :
<?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>
Avec cette configuration, je recommande également le Plugin Xcode pour Jenkins ce qui rend la mise en place du script de xcodebuild un peu plus facile. A ce stade, je vous recommande également de lire les pages de manuel de xcodebuild - vous êtes arrivé jusqu'ici dans le Terminal, non ?
Cette configuration n'est pas parfaite, et tout conseil ou avis est grandement apprécié.
J'ai eu du mal à choisir une réponse "correcte", car ce que j'ai utilisé pour résoudre mon problème était une collection des contributions de tout le monde. J'ai essayé de donner à chacun au moins un vote positif, mais j'ai attribué la réponse à Simon parce qu'il a surtout répondu à la question originale. En outre, Sami Tikka mérite beaucoup de crédit pour ses efforts visant à faire fonctionner Jenkins avec AppleScript en tant qu'application OS X ordinaire. Si vous souhaitez uniquement faire fonctionner Jenkins rapidement dans votre session utilisateur (c'est-à-dire pas en tant que serveur sans tête), sa solution est beaucoup plus proche de celle du Mac.
J'espère que mes efforts susciteront d'autres discussions et qu'ils aideront la prochaine pauvre âme qui se présente en pensant qu'elle peut configurer Jenkins CI pour ses projets iOS en un week-end grâce à toutes les merveilleuses choses qu'elle a entendues à son sujet.
Mise à jour : 9 août 2013
Avec autant de votes positifs et de favoris, j'ai pensé que je reviendrais sur ce sujet 18 mois plus tard avec quelques brèves leçons apprises.
Leçon 1 : Ne pas exposer Jenkins à l'internet public
Lors de la WWDC 2012, j'ai soumis cette question aux ingénieurs de Xcode et d'OS X Server. J'ai reçu une cacophonie de "ne faites pas ça !" de la part de tous ceux à qui j'ai posé la question. Ils étaient tous d'accord pour dire qu'un processus de construction automatisé était formidable, mais que le serveur ne devait être accessible que sur le réseau local. Les ingénieurs d'OS X Server ont suggéré d'autoriser l'accès à distance via un VPN.
Leçon 2 : il existe désormais de nouvelles options d'installation
J'ai récemment donné une conférence à CocoaHeads sur mon expérience de Jenkins, et à ma grande surprise, j'ai découvert de nouvelles méthodes d'installation - Homebrew et même une Bitnami Mac App Store version. Elles valent vraiment la peine d'être vérifiées. Jonathan Wright a un aperçu détaillant l'obtention Homebrew Jenkins fonctionne .
Leçon 3 : Non, sérieusement, n'exposez pas votre boîtier de montage à l'internet.
Il est clair, d'après le message original, que je ne suis ni administrateur système ni expert en sécurité. Le bon sens à propos des choses privées (trousseaux de clés, informations d'identification, certificats, etc.) m'a laissé un sentiment de malaise à l'idée de mettre ma boîte Jenkins sur Internet. Nick Arnott à Neglected Potential a pu confirmer mes frissons assez facilement en cet article .
TL;DR
Mes recommandations aux personnes qui cherchent à automatiser leur processus de construction ont changé au cours des 18 derniers mois. Assurez-vous que votre machine Jenkins est derrière votre pare-feu. Installez et configurez Jenkins en tant qu'utilisateur Jenkins dédié, en utilisant le programme d'installation, la version Mac App Store de Bitnami, l'AppleScript de Sami Tikka, etc. Si vous avez besoin d'un accès à distance, la configuration des services VPN dans OS X Server prend dix minutes au maximum. J'utilise cette configuration depuis plus d'un an et j'en suis très satisfait. Bonne chance !