web-dev-qa-db-fra.com

Jenkins sur OS X: xcodebuild génère une erreur Code Sign

Résumé:

L'installation de Jenkins sous OS X a été considérablement simplifiée avec le dernier programme d'installation ( du 1er mars au 9 mars 2012 ), mais la gestion du processus de signature du code reste très difficile, sans réponse directe.

Motivation:

Exécutez un serveur CI sans tête conforme aux meilleures pratiques courantes pour l'exécution de services sous OS X ( certaines d'entre elles sont expliquées ici en langage simple ).

Contexte:

Processus:

Installez Jenkins CI via OS X package d'installation _. 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 l'indique le titre de cet article, il échoue et:

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

C’est assez évident ce qui doit se passer - vous devez ajouter un certificat 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 niveau de vulnérabilité.

Problème 1: Pas de trousseau par défaut pour le démon Jenkins

Sudo -u jenkins security default-keychain ... donne "Un trousseau par défaut est introuvable"

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

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 mes recherches suggèrent qu'il faut simplement insérer leurs certificats de signature de code dans le trousseau système. Si vous exécutez security list-keychains en tant que projet de style libre dans Jenkins, vous constatez que le seul trousseau disponible est le trousseau système. Je pense que c'est là que la plupart des gens ont eu l'idée de mettre leur certificat et leur clé ici. Mais cela semble être une très mauvaise idée, en particulier étant donné que vous devrez créer un script en texte brut avec le mot de passe pour ouvrir le trousseau .

Problème 2: Ajout de certificats de signature de code et de clé privée

C'est là que je commence vraiment à être affolé. J'ai le pressentiment de créer une nouvelle clé publique/privée à utiliser avec Jenkins. Selon moi, si le démon jenkins est compromis, je peux facilement révoquer le certificat 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 certificat pour mon compte d'utilisateur et Jenkins, cela signifie plus de tracas (dommages?) Si le service Jenkins est attaqué.

En pointant sur la réponse de Simon Urbanek vous déverrouillerez le trousseau d'un script avec un mot de passe en texte brut. Il semble irresponsable de garder 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 une nouvelle CSR en tant que démon Jenkins dans Terminal, j'ai procédé comme suit ...

  1. Sudo su jenkins
  2. certtool r CertificateSigningRequest.certSigningRequest On vous demandera ce qui suit (la plupart d’entre eux jettent des hypothèses éclairées sur la bonne réponse; avez-vous une meilleure idée? Partagez, s'il vous plaît.) ... ...
    • 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 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-certificate ios_development.cer

Cela nous amène un peu plus près ...

Problème 3: Profil d’approvisionnement et déverrouillage du trousseau

J'ai créé un profil de provisioning spécial dans le portail de provisioning, juste pour l'utiliser avec CI, dans l'espoir que si un incident grave se produisait, l'impact serait un peu réduit. Meilleure pratique ou trop prudent?

  1. Sudo su jenkins
  2. mkdir ~/Library/MobileDevice
  3. mkdir ~/Library/MobileDevice/Provisioning\ Profiles
  4. Déplacez le profil de provisioning que vous avez configuré dans le portail de provisioning vers ce nouveau dossier. Nous sommes maintenant à deux pas de pouvoir exécuter xcodebuild à partir de la ligne de commande en tant que jenkins, ce qui signifie que nous sommes également sur le point de pouvoir obtenir les versions en cours d'exécution de Jenkins CI.
  5. security unlock-keychain -p <keychain password>
  6. 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. Par conséquent, si nous créons un projet de style libre et ajoutons les deux dernières étapes (n ° 5 et n ° 6 ci-dessus), nous pourrons automatiser la construction de. notre projet iOS!

Ce n'est peut-être pas nécessaire, mais je me suis senti mieux de remettre jenkins UserShell dans/usr/bin/false après avoir réussi à obtenir toute cette configuration. Suis-je paranoïaque?

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

( EDIT: j'ai posté les modifications de ma question, 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 la plist de lancement de démon à /Library/LaunchDaemons/org.jenkins-ci.plist comme indiqué dans cette réponse . Veuillez noter qu'il s'agit également d'un bug openrdar .

Ça devrait ressembler à ça:

<?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 recommanderais également le plug-in Xcode pour Jenkins , qui facilite la configuration du script xcodebuild. À ce stade, je vous recommanderais également de lire les pages de manuel de xcodebuild - bon sang, vous avez réussi jusque-là dans Terminal, n'est-ce pas?

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

J'ai eu du mal à choisir une réponse "correcte", car ce que je suis parvenu à utiliser pour résoudre mon problème était un recueil des contributions de presque tout le monde. J'ai essayé de donner à chacun au moins un vote positif, mais donnez la réponse à Simon car il a surtout répondu à la question initiale. En outre, (Sami } _ Tikka mérite beaucoup de mérite pour ses efforts visant à amener Jenkins à utiliser AppleScript comme une simple application OS X. Si vous souhaitez uniquement que Jenkins soit opérationnel rapidement dans votre session utilisateur (c’est-à-dire pas en tant que serveur sans tête), sa solution est bien plus semblable à celle d’un Mac.

J'espère que mes efforts susciteront de nouvelles discussions et aideront le prochain pauvre âme qui pense pouvoir obtenir le paramétrage de Jenkins CI pour ses projets iOS en un week-end grâce à toutes les merveilleuses choses dont ils ont entendu parler.


Mise à jour: 9 août 2013

Avec autant de votes positifs et favoris, je pensais revenir 18 mois plus tard avec quelques leçons apprises.

Leçon 1: N'exposez pas 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 quiconque j'ai demandé. Ils ont tous convenu qu'un processus de construction automatisé était une bonne chose, mais que le serveur ne devrait être accessible que sur le réseau local. Les ingénieurs OS X Server ont suggéré d'autoriser l'accès à distance via un réseau privé virtuel.

Leçon 2: Il existe de nouvelles options d'installation maintenant

J'ai récemment parlé de mon expérience de Jenkins avec CocoaHeads et, à ma grande surprise, j'ai découvert de nouvelles méthodes d'installation - Homebrew et même une version { Bitnami Mac App Store . Ce sont certainement la peine de vérifier. Jonathan Wright a un Gist détaillant le Homebrew Jenkins qui travaille .

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

D'après le message original, il est clair que je ne suis ni administrateur système ni expert en sécurité. Le bon sens des choses privées (porte-clés, identifiants, certificats, etc.) m'a laissé mal à l'aise de mettre ma boîte Jenkins sur Internet. Nick Arnott chez Neglected Potential a pu confirmer assez facilement mes heebie-jeebies dans cet article .

TL; DR

Ma recommandation aux autres 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 configurez Jenkins en tant qu'utilisateur dédié Jenkins à l'aide du programme d'installation, de la version du Mac App Store de Bitnami, du script 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 accès à distance, la configuration des services VPN sous OS X Server prend dix minutes maximum. J'utilise cette configuration depuis plus d'un an et j'en suis très heureux. Bonne chance!

107
edelaney05

Les porte-clés doivent être déverrouillés avant de pouvoir être utilisés. Vous pouvez utiliser 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 (non sécurisé), par exemple:

security unlock-keychain -p mySecretPassword...

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

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

28
Simon Urbanek

Supposons que vous souhaitiez également effectuer une distribution ad hoc via Jenkins. Cela suppose que Jenkins ait accès à un certificat de distribution et à l'identité de l'administrateur de l'équipe, en plus des profils d'approvisionnement.

En utilisant une identité exportée dans un fichier .cer, vous pouvez l'importer par programme comme si, 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’accès codesign et xcodebuild:

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

Bien entendu, nous devrions également avoir le certificat 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 devcertificate.cer. Pour ce faire, vous devez exporter la clé privée correspondante en tant que clé .p12 et définir un mot de passe. Placez-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 certificat de distribution fonctionne de la même manière. Je ne sais pas pourquoi vous devez déverrouiller le trousseau pour importer un fichier .p12 et non pour un fichier .cer, mais bien.

Vous aurez également besoin d'accéder aux profils d'approvisionnement, je modifierai ces instructions dans cet article sous peu.

12
Zsub

Pour changer le mot de passe, vous pouvez utiliser Sudo passwd jenkins <new-pw>. 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 utilisateur Shell/usr/bin/false. Le changer en bash résolvait 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.

5
Ivo Dancet

J'ai utilisé le plugin Xcode pour créer une application iOS . Dans la configuration d'un projet.

choisissez Ajoutez une étape de construction> Xcode> options de signature de code et de trousseau OS X.

cocher Déverrouiller le trousseau et ajouter comme suit (pour des exemples) enter image description here

parfois, si j'obtiens l'erreur 

Erreur de signe de code: ...

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

4
biolinh

J'ai le même problème et je cherche une réponse depuis un certain temps. Voici une chose que j'ai apprise.

J'exécute jenkins en tant qu'utilisateur jenkins, utilisateur créé par le programme d'installation, et comme tout le monde l'a mentionné, il n'a pas accès au même trousseau que votre utilisateur normal. Au lieu d'essayer de vous connecter en tant qu'utilisateur jenkins, j'ai créé un deuxième projet de construction comportant simplement une étape de construction, à savoir "Exécuter Shell" dans lequel j'exécute les 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 trousseau de clés du système.

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

Sachant cela, j'ai ensuite ouvert l'application Keychain Access et copié mon certificat "iPhone Developer: xxxx" dans le trousseau Système (clic droit, copie depuis le trousseau "Connexion").

Cela m'a permis de dépasser l'erreur de signature du code paire certificat/clé privée, mais d'en ouvrir une autre avec le profil d'approvisionnement (cela semble être un problème similaire, mais différent).

4
brianestey

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

Jenkins.app exécute Jenkins dans votre session utilisateur. Les problèmes d'accès au trousseau ne sont donc pas un problème :)

3
sti

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. 

Aussi, 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:

<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>
2
Feasoron

Pour une raison quelconque, l'utilitaire "sécurité" 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 en silence toutes les commandes "default-keychain -s ..." ou "unlock" ne renvoyant aucun état de sortie et n'imprimant rien sur la console. La liste des trousseaux par défaut ou de connexion ne donnait rien, la liste de recherche de trousseaux ne contenait que le trousseau système et je ne pouvais pas changer cela, quoi que je tape.

Après que je me suis connecté au bureau de cet utilisateur et que j'ai lancé Keychain Utility, il a bien montré mon trousseau créé et ensuite tout a fonctionné comme décrit dans les publications supérieures.

Je me demande si certains comportements du trousseau initial ont changé dans Lion ou si je manque quelque chose?

1
jazzcat

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

  1. installez jenkins en utilisant l’installateur officiel ( https://jenkins-ci.org/ )
    • Cliquez sur Suivant
    • Cliquez sur "Personnaliser"
    • Désélectionnez "Démarrer au démarrage en tant que" jenkins "" - * IMPORTANT * cette option autorise normalement un jenkins sans tête qui ne fonctionne pas bien avec l'accès 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 up
  4. Ouvrez http://127.0.0.1:8080
    • vérifier qu'il fonctionne maintenant
0
scotopic

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

Ça m'a aidé.

0
Vlad

J'ai ajouté la clé privée et la clé publique de la société au trousseau ..__ J'ai ajouté les profils de provision pour la production que je vais créer. 

Comme cet utilisateur n'avait pas de compte, je me suis connecté à devcenter avec mon compte. Téléchargé les certificats de provisioning et les charge dans Xcode.

Je n'ai pas ajouté de certificat spécifiquement pour le compte de rôle de construction, ex. Jenkins.

J'ai ajouté ceci au script de construction: Security unlock-keychain -p mySecretPassword comme ci-dessus, mais ...

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

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

Les constructions fonctionnent comme un champion. Je reçois le fichier ipa, il se charge sur l'application centrale et fonctionne sur l'appareil.

0
mpechner