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!
Respuestas:
Los llaveros deben desbloquearse antes de poder usarse. Puede usar
security unlock-keychain
para desbloquear. Puede hacerlo de forma interactiva (más seguro) o especificando la contraseña en la línea de comando (inseguro), por ejemplo:Obviamente, poner esto en un script compromete la seguridad de ese llavero, por lo que a menudo las personas configuran un llavero individual con solo las credenciales de firma para minimizar dicho daño.
Normalmente,
Terminal
el llavero ya está desbloqueado por su sesión, ya que el llavero predeterminado se desbloquea al iniciar sesión, por lo que no es necesario que lo haga. Sin embargo, cualquier proceso que no se ejecute en su sesión no tendrá el llavero desbloqueado incluso si lo tiene a usted como usuario (lo más común es que esto afectessh
, pero también a cualquier otro proceso).fuente
security unlock-keychain -p password -k /path/codesign.keychain
no funciona.-k
argumento paraunlock-keychain
que lo que esté tratando de hacer no parezca correcto (versecurity help unlock-keychain
).sudo -u jenkins bash
) y verificar que tiene los permisos en toda la ruta correcta. Hiciste muchas cosas que no dijiste (como usardscl
para crear el usuario), así que estás realmente solo. También querrá verificar la configuración de inicio (dependiendo de si configura el shell o no, puede usarlosudo -u jenkins -i
para obtener la configuración de inicio de sesión correspondiente).Suponga que también desea realizar una distribución ad hoc a través de Jenkins, esto requiere que Jenkins tenga acceso a un certificado de distribución y la identidad del administrador del equipo, además de los perfiles de aprovisionamiento.
Al usar una identidad exportada en un archivo .cer, puede importarlo mediante programación de esta manera, el interruptor -A permite que todos los programas accedan a esta entrada. Alternativamente, puede usar varios
-T /path/to/program
interruptores para permitircodesign
yxcodebuild
acceder:Por supuesto, también deberíamos tener el certificado WWDCRA de Apple, importado prácticamente de la misma manera:
Sin embargo, también necesitamos la clave privada para
devcertificate.cer
. Para hacer esto, necesita exportar la clave privada correspondiente como clave .p12 y establecer una contraseña. Colóquelo en un lugar donde pueda acceder a él desde su caparazón de Jenkins, desbloquee el llavero e impórtelo:La importación del certificado de distribución funciona de la misma manera. No sé por qué necesitas desbloquear el llavero para importar un .p12 y no para un .cer, pero bueno.
También necesitará acceso a los perfiles de aprovisionamiento, editaré esas instrucciones en esta publicación en breve.
fuente
Tuve el mismo problema y he estado buscando una respuesta durante algún tiempo. Aquí hay una cosa que he aprendido.
Estoy ejecutando jenkins como usuario de jenkins, usuario creado por el instalador y, como todos los demás han mencionado, no tiene acceso al mismo llavero que su usuario normal. En lugar de intentar iniciar sesión como usuario de jenkins, creé un segundo proyecto de compilación que simplemente tiene un paso de compilación que es "Ejecutar Shell" en el que ejecuto los comandos que quiero probar como usuario de jenkins.
Una vez que lo tuve configurado, pude ejecutar el comando
security list-keychains
Y esto me reveló que lo único que Jenkins podía ver era el llavero del sistema.
Con ese conocimiento, abrí la aplicación Keychain Access y copié mi certificado "iPhone Developer: xxxx" en el llavero del sistema (clic derecho, copia del llavero de "inicio de sesión").
Esto hizo que pasara el error de firma del código del par certificado / clave privada, pero abrió otro con el perfil de aprovisionamiento (parece un problema similar, pero diferente).
fuente
Para cambiar la contraseña puede utilizar
sudo passwd jenkins <new-pw>
. Sin embargo, creo que sería mejor usar el comando dscl para cambiar la contraseña.En mi instalación, jenkins (instalador oficial) tenía un usuario shell / usr / bin / false. Cambiarlo a bash resolvió el problema de no poder iniciar sesión:
Ahora debería poder iniciar sesión con
su jenkins
.fuente
create-keychain
comando que no funcionaba con el usuario de jenkins. La ejecución de este comando pareció solucionar el problema.He usado el complemento Xcode para crear una aplicación iOS. En configuración de un proyecto.
elija Agregar paso de compilación> Xcode> firma de código y opciones de llavero de OS X.
marque la casilla Desbloquear llavero y agregue lo siguiente (para ejemplos)
a veces, si me sale el error
Volveré a abrir Jenkins e ingresaré la contraseña nuevamente para desbloquear
fuente
Para las personas que tienen problemas con los llaveros, les recomendaría que prueben mi instalador alternativo de Jenkins en https://github.com/stisti/jenkins-app , descargas en https://github.com/stisti/jenkins-app/downloads
Jenkins.app ejecuta Jenkins en su sesión de usuario, por lo que los problemas de acceso al llavero no son un problema :)
fuente
Si tiene sudo, puede usar passwd para cambiar la contraseña del usuario de Jenkins. Entonces puede obtener la contraseña de Jenkins.
Además, no estoy seguro de si este es su problema, pero el script ANT que uso a través de Jenkins tiene esto:
fuente
Por alguna razón, la utilidad de "seguridad" no me funcionaba en Lion con una instalación nueva de Jenkins.
Después de "sudo su jenkins" fue capaz de crear un nuevo llavero, pero silenciosamente ignoró todos los comandos "default-keychain -s ..." o "desbloquear" que devolvieron el estado de salida cero y no imprimieron nada en la consola. La lista de llaveros predeterminados o de inicio de sesión no dio nada, la lista de búsqueda de llaveros solo contenía el llavero del sistema, y no pude cambiar esto sin importar lo que escriba.
Después de iniciar sesión en el escritorio de ese usuario e iniciar Keychain Utility, mostró mi llavero creado y luego todo funcionó como se describe en las publicaciones superiores.
Me pregunto si algunos de los comportamientos iniciales de llaveros cambiaron en Lion, o me estoy perdiendo algo.
fuente
Agregué la clave pública y privada de la empresa al llavero. Agregué los perfiles de provisión para la producción que construiré.
Dado que este usuario no tenía una cuenta, inicié sesión en devcenter con mi cuenta. Descargó los certificados de aprovisionamiento y los cargó en Xcode.
No agregué un certificado específicamente para la cuenta de rol de compilación, ej. jenkins.
Agregué esto al script de construcción: desbloqueo de seguridad-llavero -p mySecretPassword como arriba, pero ...
Creé un archivo ~ / .ssh / mypass y agregué la contraseña al archivo.
Entonces el comando se convierte en: desbloqueo de seguridad-llavero -p
cat ~/.ssh/mypass
Las construcciones funcionan como un campeón. Obtengo el archivo ipa, se carga en la central de aplicaciones y funciona en el dispositivo.
fuente
También podría instalar y ejecutar JenkinsCI como un usuario de OS X en lugar de un demonio:
http://127.0.0.1:8080
sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plist
/Applications/Jenkins/jenkins.war
http://127.0.0.1:8080
fuente
Para resolver este problema, intente iniciar sesión en http://appleid.apple.com y actualice sus preguntas de seguridad.
Me ayudó.
fuente