Jenkins sous OS X: xcodebuild donne une erreur de code

Résumé:

La mise en place de Jenkins sur OS X a été grandement facilitée par le dernier programme d’installation (à partir du 1.449 – 9 mars 2012 ), mais la gestion du processus de signature de code rest très difficile sans réponse simple.

Motivation:

Exécutez un serveur CI sans tête qui suit les meilleures pratiques courantes pour exécuter des services sous OS X (dont certains sont expliqués ici en langage clair ).

Contexte:

  • 12 octobre 2009 – Comment automatiser la création de votre application iPhone avec Hudson
  • 15 juin 2011 – Jenkins sur Mac OS X; git w / ssh clé publique
  • 23 juin 2011 – Déploiement continu d’applications iOS avec Jenkins et TestFlight
  • 26 juillet 2011 – Certificats et clés manquants dans le trousseau lors de l’utilisation de Jenkins / Hudson en tant qu’continuous integration pour le développement iOS et Mac
  • 30 août 2011 – Fichier d’approvisionnement Xcode introuvable avec Jenkins
  • 20 septembre 2011 – Comment configurer le CI Jenkins sur un Mac
  • 14 septembre 2011 – Faire fonctionner Jenkins sur un Mac
  • 12 novembre 2011 – Guide pratique: Installez Jenkins sur OS X et faites en sorte qu’il comstack des éléments Mac
  • 23 janvier 2012 – Changement du programme d’installation de Jenkins OSX
  • 7 mars 2012 – Merci d’avoir utilisé l’installateur OSX

Processus:

Installez le package Jenkins CI via le programme d’installation OS X. Pour l’étape “Type d’installation”, cliquez sur le bouton Personnaliser, puis 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 le script de construction xcodebuild -target MyTarget -sdk iphoneos devrait fonctionner. Comme indiqué par le titre de cet article, il ne fonctionne pas et échoue avec:

Code Sign error: The identity 'iPhone Developer' doesn't match any valid certificatee/private key pair in the default keychain

Il est assez évident de savoir ce qu’il faut faire: vous devez append un certificate de signature de code valide et une clé privée dans le trousseau par défaut. En recherchant comment y parvenir, 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 par défaut pour le démon jenkins

sudo -u jenkins security default-keychain … cède “Un trousseau par défaut est introuvable”

Comme indiqué ci-dessous par Ivo Dancet , UserShell est défini sur / usr / bin / false par défaut pour le démon jenkins (je pense que c’est une fonctionnalité, pas un bogue); suivez sa réponse pour changer le UserShell en bash. Vous pouvez ensuite utiliser sudo su jenkins pour vous connecter en tant qu’utilisateur jenkins et obtenir une invite de bash.

  1. sudo su jenkins
  2. cd ~/Library
  3. mkdir Keychains
  4. cd Keychains
  5. security create-keychain .keychain
  6. security default-keychain -s .keychain

D’accord! Super. Nous avons un trousseau par défaut maintenant; passons à droite? Mais d’abord, pourquoi avons-nous même pris la peine de créer un trousseau par défaut?

Presque toutes les réponses, suggestions ou conversations que j’ai lues tout au long de la recherche suggèrent que l’on devrait simplement jeter leurs codes et signatures de code dans le trousseau du système. Si vous exécutez security list-keychains 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 de mettre leur certificate et leur clé à l’intérieur. Mais, cela semble être une très mauvaise idée, surtout si vous devez créer un script en texte brut avec le mot de passe pour ouvrir le trousseau .

Problème 2: Ajout de certificates de signature de code et d’une clé privée

C’est là que je commence vraiment à me faire mal. J’ai l’impression que je devrais créer une nouvelle clé publique / privée unique à utiliser avec Jenkins. Mon processus de pensée est que si le démon jenkins est compromis, alors je peux facilement révoquer le certificate dans le portail d’approvisionnement d’Apple et générer une autre clé publique / privée. Si j’utilise la même clé et le même certificate pour mon compte d’utilisateur et Jenkins, cela signifie plus de problèmes (dommages?) Si le service jenkins est attaqué.

En faisant référence à la réponse de Simon Urbanek, vous débloquerez le trousseau d’un script avec un mot de passe en texte brut. Il semble irresponsable de conserver autre chose que des certificates et des clés “jetables” dans le trousseau 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 Terminal, j’ai fait ce qui suit …

  1. sudo su jenkins
  2. certtool r CertificateSigningRequest.certSigningRequest Vous serez invité à fournir les informations suivantes (la plupart d’entre elles ont formulé des suppositions concernant la bonne réponse; avez-vous une meilleure idée? S’il vous plaît partagez.) …
    • Entrez la clé et le label du certificate:
    • 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 challenge:
    • Puis un tas de questions pour RDN
  3. Soumettez le fichier CSR généré (CertificateSigningRequest.certSigningRequest) au portail d’approvisionnement d’Apple sous un nouvel identifiant Apple.
  4. Approuver la demande et télécharger le fichier .cer
  5. security unlock-keychain
  6. security add-certificatee ios_development.cer

Cela nous rapproche un peu …

Problème 3: déblocage du profil d’approvisionnement et du trousseau

J’ai créé un profil de provisioning spécial dans le portail de provisionnement, à utiliser avec CI, dans l’espoir que si quelque chose de mauvais se produisait, je réduisais l’impact. Meilleure pratique ou trop prudent?

  1. sudo su jenkins
  2. mkdir ~/Library/MobileDevice
  3. mkdir ~/Library/MobileDevice/Provisioning\ Profiles
  4. Déplacez le profil d’approvisionnement que vous avez configuré dans le portail de provisionnement dans ce nouveau dossier. Nous sums maintenant à deux pas de l’exécution de xcodebuild à partir de la ligne de commande sous le nom de jenkins, ce qui signifie que nous sums également en mesure d’obtenir les versions exécutées du CI Jenkins.
  5. security unlock-keychain -p
  6. xcodebuild -target MyTarget -sdk iphoneos

Maintenant, nous obtenons une génération réussie à partir d’une ligne de commande lorsque vous êtes connecté en tant que démon jenkins, donc si nous créons un projet de style libre et ajoutons les deux dernières étapes (# 5 et # 6 ci-dessus), nous pourrons automatiser la construction notre projet iOS!

Ce n’est peut-être pas nécessaire, mais je me suis senti mieux en réglant jenkins UserShell sur / usr / bin / false après avoir réussi à obtenir toute cette configuration. Est-ce que je suis paranoïaque?

Problème 4: Le trousseau par défaut n’est toujours pas disponible!

( EDIT: j’ai posté les modifications apscopes à ma question, redémarré pour m’assurer que ma solution était à 100%, et bien sûr, j’avais omis une étape )

Même après toutes les étapes ci-dessus, vous devrez modifier le plist Launch Daemon dans /Library/LaunchDaemons/org.jenkins-ci.plist comme indiqué dans cette réponse . S’il vous plaît noter que c’est aussi un bug openrdar .

Ça devrait ressembler à ça:

     EnvironmentVariables  JENKINS_HOME /Users/Shared/Jenkins/Home  GroupName daemon KeepAlive  Label org.jenkins-ci ProgramArguments  /bin/bash /Library/Application Support/Jenkins/jenkins-runner.sh  RunAtLoad  UserName jenkins  SessionCreate    

Avec cette configuration, je recommanderais également le plug-in Xcode pour Jenkins , qui facilite la configuration du script xcodebuild. À ce stade, je vous recommande également de lire les pages de manuel relatives à xcodebuild.

Cette configuration n’est pas parfaite, et tout conseil ou idée est grandement apprécié.

J’ai eu du mal à sélectionner une réponse “correcte”, car ce que je suis venu utiliser pour résoudre mon problème était une collection de commentaires de presque tout le monde. J’ai essayé de donner à tout le monde un vote au moins, mais j’atsortingbue la réponse à Simon car il a surtout répondu à la question initiale. De plus, Sami Tikka mérite beaucoup de reconnaissance pour ses efforts pour que Jenkins travaille avec AppleScript comme une application simple d’OS X. Si vous souhaitez uniquement installer 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 de Mac.

J’espère que mes efforts susciteront de nouvelles discussions, et aiderai la prochaine âme pauvre qui pense pouvoir obtenir la configuration de Jenkins CI pour leurs projets iOS en un week-end en raison de toutes les choses merveilleuses dont ils ont entendu parler.


Mise à jour: 9 août 2013

Avec autant de citations et de favoris, je pensais y revenir 18 mois plus tard avec quelques brèves leçons apsockets.

Leçon 1: Ne pas exposer Jenkins à l’Internet public

Lors de la WWDC 2012, j’ai posé cette question aux ingénieurs Xcode et OS X Server. J’ai reçu une cacophonie de “ne fais pas ça!” de quelqu’un que j’ai demandé. Ils ont tous convenu qu’un processus de génération automatisé était excellent, mais que le serveur ne devrait être accessible que sur le réseau local. Les ingénieurs d’OS X Server ont suggéré d’autoriser l’access à distance via VPN.

Leçon 2: Il y a de nouvelles options d’installation maintenant

J’ai récemment donné une conférence sur CocoaHeads à propos de mon expérience avec Jenkins, et à ma grande surprise, j’ai trouvé de nouvelles méthodes d’installation – Homebrew et même une version de Bitnami Mac App Store . Celles-ci valent vraiment la peine d’être vérifiées. Jonathan Wright a une idée détaillée du travail de Homebrew Jenkins .

Leçon 3: Non, sérieusement, n’exposez pas votre boîte de assembly à Internet

Il ressort clairement du message original que je ne suis ni administrateur système ni expert en sécurité. Le bon sens concernant les trucs privés (porte-clés, identifiants, certificates, etc.) m’a laissé mal à l’aise de mettre ma boîte Jenkins sur Internet. Nick Arnott de Neglected Potential a été en mesure de confirmer mes heebie-jeebies assez facilement dans cet article .

TL; DR

Ma recommandation aux personnes cherchant à automatiser leur processus de construction a changé au cours des 18 derniers mois. Assurez-vous que votre machine Jenkins est derrière votre pare-feu. Installez et définissez Jenkins en tant qu’utilisateur Jenkins dédié en utilisant l’installateur, la version de Bitnami Mac App Store, l’AppleScript de Sami Tikka, etc. Cela résout la plupart des maux de tête que je détaille ci-dessus. Si vous avez besoin d’un access à distance, la configuration des services VPN dans OS X Server prend dix minutes maximum. J’utilise cette configuration depuis plus d’un an et j’en suis très satisfaite. Bonne chance!

Les porte-clés doivent être déverrouillés avant de pouvoir être utilisés. Vous pouvez utiliser le security unlock-keychain pour déverrouiller. Vous pouvez le faire de manière interactive (plus sûre) ou en spécifiant le mot de passe sur la ligne de commande (dangereux), par exemple:

 security unlock-keychain -p mySecretPassword... 

Évidemment, mettre cela dans un script compromet la sécurité de ce trousseau, de sorte que souvent, les gens installent un trousseau individuel avec uniquement les informations d’identification de signature pour minimiser ces dommages.

Généralement, dans le Terminal le trousseau est déjà déverrouillé par votre session, puisque le trousseau par défaut est déverrouillé lors de la connexion, vous n’avez donc pas besoin de le faire. Cependant, tout processus non exécuté dans votre session n’aura pas de trousseau de clés déverrouillé, même si cela vous concerne en tant qu’utilisateur (le plus souvent, cela affecte ssh , mais également tout autre processus).

Supposons que vous souhaitiez également effectuer une dissortingbution ad hoc via Jenkins, cela nécessite que Jenkins ait access à un certificate de dissortingbution et à l’identité de l’administrateur de l’équipe, en plus des profils de configuration.

En utilisant une identité exscope dans un fichier .cer, vous pouvez l’importer par programmation comme cela, le commutateur -A permet à tous les programmes d’accéder à cette entrée. Vous pouvez également utiliser plusieurs commutateurs -T /path/to/program pour autoriser l’access à codesign et xcodebuild .:

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

Bien sûr, nous devrions également avoir le certificate Apple WWDCRA, importé à peu près de la même manière:

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

Cependant, nous avons également besoin de la clé privée pour le devcertificatee.cer . Pour ce faire, vous devez exporter la clé privée correspondante en tant que clé .p12 et définir un mot de passe. Mettez-le quelque part, vous pouvez y accéder depuis votre shell Jenkins, déverrouiller le trousseau et l’importer:

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

L’importation du certificate de dissortingbution fonctionne de la même manière. Je ne sais pas pourquoi vous devez déverrouiller le trousseau pour importer un .p12 et pas pour un .cer, mais bien.

Vous aurez également besoin d’accéder aux profils d’approvisionnement, je vais modifier ces instructions dans ce post sous peu.

Pour changer le mot de passe, vous pouvez utiliser sudo passwd jenkins . Cependant, je pense qu’il serait préférable d’utiliser la commande dscl pour changer le mot de passe.

Dans mon installation, jenkins (installateur officiel) avait un shell utilisateur / usr / bin / false. Le changer en bash a résolu le problème de l’impossibilité de se connecter:

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

Vous devriez maintenant pouvoir vous connecter avec su jenkins .

J’ai eu le même problème et je cherchais une réponse depuis quelque temps. Voici une chose que j’ai apprise.

Je suis jenkins en tant qu’utilisateur de jenkins, utilisateur créé par l’installateur, et comme tout le monde l’a mentionné, il n’a pas access au même trousseau que votre utilisateur normal. Au lieu d’essayer de me connecter en tant qu’utilisateur jenkins, j’ai créé un deuxième projet de génération qui comporte simplement une étape de construction appelée “Execute Shell” dans laquelle je lance des commandes que je souhaite tester en tant qu’utilisateur jenkins.

Une fois que j’ai eu cette configuration, je pouvais exécuter la commande

security list-keychains

Et cela m’a révélé que la seule chose que jenkins pouvait voir était le porte-clés du système.

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

Avec cette connaissance, j’ai ensuite ouvert l’application Keychain Access et copié mon certificate “iPhone Developer: xxxx” dans le trousseau système (clic droit, copie du trousseau “login”).

Cela m’a permis de passer l’erreur du signe du code de la paire de clés privée / certificate, mais j’ai ouvert une autre erreur avec le profil de provisionnement (semble être un problème similaire, mais différent).

J’ai utilisé le plug-in Xcode pour créer une application iOS. En configuration d’un projet.

choisissez Ajouter une étape de construction> Xcode> Options de signature de code et de trousseau OS X.

cochez la case Déverrouiller la boîte de trousseau et ajoutez-la comme suit (pour des exemples) entrer la description de l'image ici

parfois, si je reçois l’erreur

Erreur de code: …

Je vais rouvrir Jenkins et entrer à nouveau le mot de passe pour déverrouiller

Pour les personnes ayant des problèmes avec les porte-clés, je vous recommande d’essayer mon autre programme d’installation de Jenkins à l’ adresse https://github.com/stisti/jenkins-app , à l’ adresse https://github.com/stisti/jenkins-app/downloads.

Jenkins.app exécute Jenkins dans votre session utilisateur, les problèmes d’access au trousseau ne sont donc pas un problème 🙂

Si vous avez sudo, vous pouvez utiliser passwd pour changer le mot de passe de l’utilisateur Jenkins. Ensuite, vous pouvez obtenir le mot de passe Jenkins.

En outre, je ne suis pas sûr que ce soit le problème pour vous, mais le script ANT que j’utilise via Jenkins a ceci:

          

Pour une raison quelconque, l’utilitaire “security” ne fonctionnait pas pour moi sur Lion avec une nouvelle installation de Jenkins.

Après “sudo su jenkins”, il était capable de créer un nouveau trousseau, mais ignorait silencieusement toutes les commandes “default-keychain -s …” ou “unlock” renvoyant zéro état de sortie et n’imprimant rien sur la console. La liste par défaut ou les trousseaux de connexion ne donnaient rien, la liste de recherche des trousseaux ne contenait que le trousseau du système, et je ne pouvais pas changer ce que je tapais.

Après avoir ouvert une session sur le bureau de cet utilisateur et lancé Keychain Utility, il a montré mon trousseau créé et ensuite tout a fonctionné comme décrit dans les articles les plus importants.

Je me demande si certains comportements de porte-clés initiaux ont changé dans Lion, ou est-ce que je manque quelque chose?

J’ai ajouté la clé privée et publique pour l’entreprise au porte-clés. J’ai ajouté les profils de provision pour la production que je vais construire.

Comme cet utilisateur n’avait pas de compte, je me suis connecté à devcenter avec mon compte. Téléchargé les certificates d’approvisionnement et les a chargés dans Xcode.

Je n’ai pas ajouté de cert pour le compte de rôle de construction, ex. jenkins.

J’ai ajouté ceci au script de compilation: security unlock-keychain -p mySecretPassword comme ci-dessus, mais …

J’ai créé un fichier ~ / .ssh / mypass et ajouté le mot de passe au fichier.

La commande devient alors: security unlock-keychain -p cat ~/.ssh/mypass

Les builds fonctionnent comme un champion. J’obtiens le fichier ipa, il se charge sur l’application centrale et fonctionne sur l’appareil.

Peut également installer et lancer JenkinsCI en tant qu’utilisateur OS X au lieu d’un démon:

  1. installer jenkins en utilisant l’installateur officiel ( https://jenkins-ci.org/ )
    • Cliquez sur Suivant
    • Cliquez sur “Personnaliser”
    • Désélectionner “Commencer au démarrage en tant que” Jenkins “” – * IMPORTANT * cette option permet normalement à un Jenkins sans tête qui ne fonctionne pas bien avec l’access au trousseau
  2. Lancer http://127.0.0.1:8080
    • vérifiez qu’il NE LANCE PAS
    • peut avoir besoin d’arrêter jenkins sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plist
  3. Double-cliquez sur /Applications/Jenkins/jenkins.war
    • bien sûr, cela devrait être automatisé pour démarrer @ start
  4. Ouvrez http://127.0.0.1:8080
    • vérifier qu’il est en cours d’exécution

Pour résoudre ce problème, essayez de vous connecter à http://appleid.apple.com et de mettre à jour vos questions de sécurité.

Ça m’a aidé.