Resumen:
La configuración de Jenkins en OS X se ha simplificado significativamente con el instalador más reciente ( desde 1.449 hasta el 9 de marzo de 2012 ), sin embargo, administrar el proceso de firma de código sigue siendo muy difícil sin una respuesta sencilla.
Motivación:
Ejecute un servidor CI sin cabeza que siga las mejores prácticas comunes para ejecutar servicios en OS X ( algunas de las cuales se explican aquí en lenguaje sencillo ).
Antecedentes:
- 12 de octubre de 2009: cómo automatizar las compilaciones de aplicaciones para iPhone con Hudson
- 15 de junio de 2011: Jenkins en Mac OS X; git con clave pública ssh
- 23 de junio de 2011: implementación continua de aplicaciones iOS con Jenkins y TestFlight
- 26 de julio de 2011: faltan certificados y claves en el llavero mientras se usa Jenkins / Hudson como integración continua para el desarrollo de iOS y Mac
- 30 de agosto de 2011: no se encuentra el archivo de aprovisionamiento de Xcode con Jenkins
- 20 de septiembre de 2011: cómo configurar Jenkins CI en una Mac
- 14 de septiembre de 2011: Ejecución de Jenkins en una Mac
- 12 de noviembre de 2011 - Howto: Instale Jenkins en OS X y haga que compile cosas de Mac
- 23 de enero de 2012 - Próximos cambios en el instalador de Jenkins OSX
- 7 de marzo de 2012 - Gracias por usar OSX Installer
Proceso:
Instalar Jenkins CI a través de OS X paquete de instalación . Para el paso "Tipo de instalación", haga clic en el botón Personalizar y seleccione "Iniciar al arrancar como 'jenkins'".
Discusión:
La expectativa ingenua en este punto era que un proyecto de estilo libre con el script de compilación xcodebuild -target MyTarget -sdk iphoneos
debería funcionar. Como indica el título de esta publicación, no lo hace y falla con:
Code Sign error: The identity 'iPhone Developer' doesn't match any valid certificate/private key pair in the default keychain
Es bastante obvio lo que debe suceder: debe agregar un certificado de firma de código válido y una clave privada en el llavero predeterminado. Al investigar cómo lograr esto, no he encontrado una solución que no abra el sistema a algún nivel de vulnerabilidad.
Problema 1: No hay llavero predeterminado para el demonio jenkins
sudo -u jenkins security default-keychain
... produce "No se pudo encontrar un llavero predeterminado"
Como señala Ivo Dancet a continuación , UserShell está configurado en / usr / bin / false para el demonio jenkins de forma predeterminada (creo que esta es una característica, no un error); siga su respuesta para cambiar UserShell a bash. Luego puede usar sudo su jenkins
para iniciar sesión como usuario de jenkins y obtener un indicador de bash.
sudo su jenkins
cd ~/Library
mkdir Keychains
cd Keychains
security create-keychain <keychain-name>.keychain
security default-keychain -s <keychain-name>.keychain
Ok genial. Ahora tenemos un llavero predeterminado; sigamos adelante, ¿verdad? Pero, primero, ¿por qué nos molestamos en hacer un llavero predeterminado?
Casi todas las respuestas, sugerencias o conversaciones que leí a lo largo de la investigación sugieren que uno debería simplemente arrojar sus certificados y claves de firma de código en el llavero del sistema. Si ejecuta security list-keychains
como un proyecto de estilo libre en Jenkins, verá que el único llavero disponible es el llavero del sistema; Creo que ahí es donde a la mayoría de la gente se le ocurrió la idea de poner su certificado y clave allí. Pero, esto parece una muy mala idea, especialmente dado que necesitará crear un script de texto sin formato con la contraseña para abrir el llavero .
Problema 2: agregar certificados de firma de código y clave privada
Aquí es donde realmente empiezo a sentirme aprensivo. Tengo el presentimiento de que debería crear una nueva clave pública / privada única para usar con Jenkins. Mi proceso de pensamiento es que si el demonio jenkins está comprometido, entonces puedo revocar fácilmente el certificado en el portal de aprovisionamiento de Apple y generar otra clave pública / privada. Si utilizo la misma clave y certificado para mi cuenta de usuario y Jenkins, significa más molestias (¿daños?) Si el servicio de jenkins es atacado.
Al señalar la respuesta de Simon Urbanek, desbloqueará el llavero de un script con una contraseña de texto sin formato. Parece irresponsable mantener cualquier cosa que no sean certificados y claves "desechables" en el llavero del demonio jenkins.
Estoy muy interesado en cualquier discusión en sentido contrario. ¿Estoy siendo demasiado cauteloso?
Para hacer una nueva CSR como el demonio jenkins en Terminal, hice lo siguiente ...
sudo su jenkins
certtool r CertificateSigningRequest.certSigningRequest
Se le pedirá lo siguiente (la mayoría de ellos hice conjeturas fundamentadas sobre la respuesta correcta; ¿tiene una mejor idea? Por favor, comparta) ...- Ingrese la clave y la etiqueta del certificado:
- Seleccionar algoritmo:
r
(para RSA) - Ingrese el tamaño de la clave en bits:
2048
- Seleccionar algoritmo de firma:
5
(para MD5) - Ingrese la cadena de desafío:
- Luego, un montón de preguntas para RDN.
- Envíe el archivo CSR generado (CertificateSigningRequest.certSigningRequest) al portal de aprovisionamiento de Apple con un nuevo ID de Apple
- Apruebe la solicitud y descargue el archivo .cer
security unlock-keychain
security add-certificate ios_development.cer
Esto nos acerca un paso más ...
Problema 3: perfil de aprovisionamiento y desbloqueo del llavero
Hice un perfil de aprovisionamiento especial en el Portal de aprovisionamiento solo para usar con CI con la esperanza de que, si ocurre algo malo, haya reducido un poco el impacto. ¿Mejores prácticas o demasiado cauteloso?
sudo su jenkins
mkdir ~/Library/MobileDevice
mkdir ~/Library/MobileDevice/Provisioning\ Profiles
- Mueva el perfil de aprovisionamiento que configuró en el portal de aprovisionamiento a esta nueva carpeta. Ahora estamos a dos pasos de poder ejecutar xcodebuild desde la línea de comandos como jenkins, y eso significa que también estamos cerca de poder ejecutar las compilaciones de Jenkins CI.
security unlock-keychain -p <keychain password>
xcodebuild -target MyTarget -sdk iphoneos
Ahora obtenemos una compilación exitosa desde una línea de comando cuando iniciamos sesión como el demonio jenkins, por lo que si creamos un proyecto de estilo libre y agregamos esos dos pasos finales (# 5 y # 6 arriba) podremos automatizar la compilación de nuestro proyecto iOS!
Puede que no sea necesario, pero me sentí mejor configurando jenkins UserShell de nuevo en / usr / bin / false después de haber logrado toda esta configuración. ¿Me estoy volviendo paranoico?
Problema 4: ¡El llavero predeterminado aún no está disponible!
( EDITAR: publiqué las ediciones de mi pregunta, reinicié para asegurarme de que mi solución estaba al 100% y, por supuesto, había omitido un paso )
Incluso después de todos los pasos anteriores, deberá modificar la lista Launch Daemon en /Library/LaunchDaemons/org.jenkins-ci.plist como se indica en esta respuesta . Tenga en cuenta que esto también es un error de openrdar .
Debe tener un aspecto como este:
<?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>
Con esta configuración, también recomendaría el complemento Xcode para Jenkins , que facilita un poco la configuración del script xcodebuild. En este punto, también recomendaría leer las páginas de manual de xcodebuild; diablos, llegaste tan lejos en Terminal, ¿verdad?
Esta configuración no es perfecta y cualquier consejo o conocimiento es muy apreciado.
Me ha costado mucho seleccionar una respuesta "correcta", ya que lo que he llegado a utilizar para resolver mi problema fue una recopilación de las opiniones de todos. Intenté darles a todos al menos un voto positivo, pero le doy la respuesta a Simon porque él respondió principalmente a la pregunta original. Además, Sami Tikka merece mucho crédito por sus esfuerzos para que Jenkins funcione a través de AppleScript como una simple aplicación OS X. Si solo está interesado en poner a Jenkins en funcionamiento e ir rápidamente dentro de su sesión de usuario (es decir, no como un servidor sin cabeza), su solución es mucho más parecida a Mac.
Espero que mis esfuerzos susciten más discusiones y ayuden al próximo pobre que venga pensando que pueden configurar Jenkins CI para sus proyectos de iOS en un fin de semana debido a todas las cosas maravillosas que han escuchado sobre él.
Actualización: 9 de agosto de 2013
Con tantos votos positivos y favoritos, pensé que volvería a esto 18 meses después con algunas breves lecciones aprendidas.
Lección 1: No exponga a Jenkins a la Internet pública
En la WWDC de 2012, llevé esta pregunta a los ingenieros de Xcode y OS X Server. Recibí una cacofonía de "¡no hagas eso!" de cualquiera a quien le pregunté. Todos estuvieron de acuerdo en que un proceso de construcción automatizado era excelente, pero que el servidor solo debería ser accesible en la red local. Los ingenieros de OS X Server sugirieron permitir el acceso remoto a través de VPN.
Lección 2: ahora hay nuevas opciones de instalación
Recientemente di una charla de CocoaHeads sobre mi experiencia con Jenkins y, para mi sorpresa, encontré algunos métodos de instalación nuevos: Homebrew e incluso una versión de Bitnami Mac App Store . Definitivamente vale la pena echarle un vistazo. Jonathan Wright tiene una esencia que detalla cómo funciona Homebrew Jenkins .
Lección 3: No, en serio, no exponga su caja de compilación a Internet
De la publicación original queda bastante claro que no soy administrador de sistemas ni experto en seguridad. El sentido común acerca de las cosas privadas (llaveros, credenciales, certificados, etc.) me hizo sentir bastante incómodo acerca de poner mi caja Jenkins en Internet. Nick Arnott de Neglected Potential fue capaz de confirmar mis heebie-jeebies con bastante facilidad en este artículo .
TL; DR
Mi recomendación para otros que buscan automatizar su proceso de construcción ha cambiado durante el último año y medio. Asegúrese de que su máquina Jenkins esté detrás de su firewall. Instale y configure Jenkins como un usuario dedicado de Jenkins, ya sea utilizando el instalador, la versión de Bitnami Mac App Store, el AppleScript de Sami Tikka, etc. esto resuelve la mayor parte del dolor de cabeza que detallo anteriormente. Si necesita acceso remoto, configurar los servicios VPN en OS X Server toma diez minutos como máximo. He estado usando esta configuración durante más de un año y estoy muy contento con ella. ¡Buena suerte!