"La interacción del usuario no está permitida" al intentar firmar una aplicación OSX con el código

145

Nuestra compilación automatizada se ejecuta en Jenkins. La construcción en sí se ejecuta en esclavos, y los esclavos se ejecutan a través de SSH.

Me sale un error:

00:03:25.113 [codesign-app] build/App.app: User interaction is not allowed.

He probado todas las sugerencias que he visto hasta ahora en otras publicaciones aquí:

  • Usando el desbloqueo de seguridad-llavero inmediatamente antes de firmar para desbloquear el llavero.
  • Mover la clave de firma a su propio llavero.
  • Mover la clave de firma al llavero de inicio de sesión.
  • Mover la clave de firma en el llavero del sistema.
  • Configuración manual de llaveros de lista solo para el llavero que contiene la clave.

En todos los casos, me sale el mismo error.

En un intento de diagnosticar el problema, intenté ejecutar el comando "security unlock-keychain" en mi terminal local y descubrí que en realidad no desbloquea el llavero; si miro en Keychain Access, el símbolo de bloqueo sigue ahí. Este es el caso si paso la contraseña en la línea de comandos o si dejo que me lo solicite. Desbloquear el mismo llavero con la GUI me solicitará la contraseña y luego la desbloquearé. Además, si me quedo "bloqueo de seguridad llavero", me hago ver el bloqueo de teclas inmediatamente después de ejecutar el comando. Esto me hace pensar que desbloquear llavero en realidad no funciona. Experimento el mismo comportamiento en Lion (que estamos usando para construir esclavos) y Mavericks (en el que estoy desarrollando).

Luego, intenté agregar -v a todos los comandos de seguridad:

list-keychains "-d" "system" "-s" "/Users/tester/.secret/App.keychain"
Listing keychains to see if it was added: ((
        "/Library/Keychains/System.keychain"
))
unlock-keychain "-p" "**PASSWORD**" "/Users/tester/.secret/App.keychain"
build/App.app: User interaction is not allowed.

A partir de esto, parece que la lista de llaveros es lo que no está funcionando. Quizás tampoco funcione. : /

Hay una pregunta similar aquí . La solución es interesante: establezca "SessionCreate" en true en launchctl. Pero no estoy construyendo en el maestro: mi proceso de compilación se inicia desde SSH en una máquina de compilación esclava. ¿Tal vez hay una forma de línea de comandos para hacer lo que está haciendo launchctl cuando ejecuta "SessionCreate"?

Trejkaz
fuente
¿Cómo configurar la contraseña del llavero en circleci?
Sachin Kumaram
@SachinKumaram suena como una nueva pregunta viable?
Trejkaz

Respuestas:

205

Yo también he estado luchando contra esto. Nada ayudó hasta que probé la sugerencia en http://devnet.jetbrains.com/thread/311971 . Gracias ashish agrawal!

Inicie sesión en su usuario de compilación a través de la GUI y abra Keychain Access. Seleccione su clave privada de firma, haga clic con el botón derecho, elija Obtener información, cambie a la pestaña Control de acceso y seleccione "Permitir que todas las aplicaciones accedan a este elemento".

pestaña de control de acceso

bmauter
fuente
2
De nada. También podría considerar agregar el código de código a la lista de aplicaciones en la parte inferior en lugar de permitir todas las aplicaciones como lo hice. Ya está allí en mi captura de pantalla, pero creo que originalmente no lo estaba.
bmauter
3
Tuve que mostrar el directorio / usr con apple.stackexchange.com/a/34872/6052 para poder agregar codesigna la lista "Permitir siempre".
Heath Borders,
24
solo una nota de que además de esto, también tienes que hacer todo el security unlock-keychainasunto
cwd
13
Además, es posible que desee mover sus claves desde el inicio de sesión al sistema para que estén accesibles cuando realice compilaciones remotas en su máquina.
Krystian
8
¿Alguien sabe alguna forma de hacer esto desde la línea de comandos? Mi máquina de compilación remota no me permite hacer esto por compartir pantalla por razones de seguridad .
devios1
78

Bueno, supongo que puedo responder mi propia pregunta hoy, porque después de apuñalarla durante dos días y medio, una de las cosas que intenté parece haber funcionado. Voy a retroceder ahora y espero que siga funcionando.

Esencialmente, parece que todo se reduce a -d systemno funcionar realmente. Entonces, muchas respuestas a otras preguntas por aquí probablemente deberían actualizarse para reflejar eso.

security -v list-keychains -s "$KEYCHAIN" "$HOME/Library/Keychains/login.keychain"
security list-keychains # so we can verify that it was added if it fails again
security -v unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN"
codesign --sign "$SIGNER_IDENTITY" --force --signature-size 9600 \
         --resource-rules src/AppResourceRules.plist --timestamp --verbose \
         "$APP"
Trejkaz
fuente
17
Gracias. He podido reducir esto. Simplemente ejecute el siguiente comando justo antes de intentar compilar: seguridad -v unlock-keychain -p "$ KEYCHAIN_PASSWORD" "$ HOME / Library / Keychains / login.keychain"
pir800
3
Entonces, ¿no hay forma de acceder a codesigntravés de ssh sin almacenar realmente la contraseña de inicio de sesión dentro de algún script?
chakrit
2
@chakrit en el ejemplo anterior, solo paso la contraseña del llavero, no la contraseña de inicio de sesión. Me doy cuenta de que para muchos usuarios, el llavero de inicio de sesión es el único llavero, pero en nuestro caso, mantenemos las claves de firma en un almacén de claves separado para que sea más fácil sincronizarlas para construir máquinas. Pero sí, muchas de estas cosas parecen bastante inconvenientes para las compilaciones automatizadas, lo que me hace preguntarme si Apple incluso hace compilaciones automatizadas.
Trejkaz
@Trejkaz oh está bien, al menos compartir una contraseña de llavero no es tan malo.
chakrit
En mi caso de uso de compilaciones remotas automatizadas, almacenar la contraseña del llavero en un .envarchivo no es tan malo, ya que el .envarchivo ya contiene claves sensibles, por ejemplo. AWS y Heroku. En nuestro caso, las credenciales de signo de código relacionadas con la compilación se almacenan en un llavero recién creado que luego se elimina después de la compilación. Luego se vuelve a crear para la próxima compilación. Sin embargo, el loginllavero aún debe abrirse, por security unlock-keychain -p pass login.keychainlo que el enlace que faltaba aquí. ¡Gracias!
Petrus Repo
19

Ninguna de las otras respuestas funcionó para mí.

Lo que finalmente me salvó fue esta publicación

Para resumir, esto puede ser causado por un tiempo de espera predeterminado de 5 minutos, que desencadenará este error después de una compilación larga.

Arreglar:

security set-keychain-settings -t 3600 -l ~/Library/Keychains/login.keychain
yonix
fuente
2
En El Capitan, también puede hacerlo a través de la interfaz de usuario. Simplemente abra la aplicación de llavero, haga clic con el botón derecho en su llavero (inicio de sesión, sistema, etc.) y haga clic en algo que coincida con 'cambiar la configuración de <your_keychain>' mejor.
rubybeginner
Esto siempre restablece el acceso a mi llavero del sistema Confirmincluso después de cambiar el acceso. : /
Alex Zavatone
¡Fue útil para mí!
Nori
He estado luchando con eso durante 2 días, antes de encontrar tu comentario, ¡¡¡gracias !!!
Gilad Novik
16

Intenta llamar security unlock-keychainy codesigncomo un comando de una línea. Esto me ayudo. Algo como:

security unlock-keychain -p <password> /Users/<user>/Library/Keychains/login.keychain && codesign --force --verify --verbose --sign "<certificate id>" <app name>
ZhekaKozlov
fuente
44
Eso es lo mismo que hacerlo en dos líneas. Supongo que la diferencia es que si el primer comando falla, no ejecutará el segundo.
Trejkaz
1
Para mí no son lo mismo. Los llamo vía hormiga sshexecy cada vez que crea una nueva sesión ssh.
ZhekaKozlov
2
También puede hacer más de una línea a través de una sola sesión ssh, si realmente lo desea. Entonces ... sigue siendo lo mismo, aparte del tratamiento de errores.
Trejkaz
13

Uso de seguridad para crear un llavero para / usr / bin / codesign

Importar el certificado y hacer que funcione con codeign programáticamente no es cuestión de usar el inicio de sesión o los llaveros del sistema o rezar a algún dios del codeign. Solo necesita tener establecidos los permisos correctos. Recomiendo crear un nuevo llavero específicamente para propósitos de código.

En estos días para codesignque no se produzca errSecInternalComponent, debe obtener la lista de particiones (ACL) correcta. Recorreré los pasos:

Crea el llavero

security create-keychain -p "${KEYCHAIN_PASSWORD}" "${KEYCHAIN_NAME}"

en este punto, el llavero está desbloqueado pero no aparecerá Keychain Access.

Agregue el nuevo llavero a la lista de búsqueda

security list-keychains -s "${KEYCHAIN_NAME}" "${OLD_KEYCHAIN_NAMES[@]}"

Agregue el nuevo llavero a la lista. Si no obtiene primero la lista original list-keychains, ya no la tendrá login.keychainen su lista de búsqueda.

Desbloquee el llavero

security unlock-keychain -p "${KEYCHAIN_PASSWORD}" "${KEYCHAIN_NAME}"

Esto es redundante si creó el Llavero anterior, pero si el Llavero ya existía, es necesario.

Eliminar los valores predeterminados del llavero

security set-keychain-settings "${TESTING_KEYCHAIN}"

Al no especificar ningún argumento, esto establecerá el tiempo de espera de bloqueo automático en ilimitado y eliminará el bloqueo automático en suspensión.

Importe sus certificados de firma de un .p12

security import "${DIST_CER}" -P "${CERTIFICATE_PASSWORD}" -k "${KEYCHAIN_NAME}" -T /usr/bin/codesign

Importa los certificados y da codesignacceso a través de la -Topción.

Establecer la ACL en el llavero

security set-key-partition-list -S apple-tool:,apple: -s -k "${KEYCHAIN_PASSWORD}" "${KEYCHAIN_NAME}"

Este es un requisito que mucha gente omite. Puedes ver lo que hace macOS usando dump-keychain. Que en el caso de la firma de códigos requiere apple:y apple-tool:. -sse refiere a la firma de certificados.

Gitlab-Runner, Jenkins y similares

Una cosa muy importante para cualquier corredor de tipo CI o sistema de compilación es asegurarse de que el proceso se inicie launchdcorrectamente. Asegúrese de que su plist contiene <SessionCreate> </true>.

No hacer coincidir correctamente al propietario del llavero con el proceso de compilación y asegurarse de que se cree una sesión de seguridad resultará en todo tipo de dolores de cabeza. En términos de diagnóstico, puede presentar list-keychainsy ver si el resultado coincide con sus expectativas.

Esto es de la launchd.plistpágina de manual:

SessionCreate <boolean>

Esta clave especifica que el trabajo debe generarse en una nueva sesión de auditoría de seguridad en lugar de que pertenezca la sesión predeterminada para el contexto. Ver auditon (2) para más detalles.

UserName <string>

Esta clave opcional especifica el usuario para ejecutar el trabajo como. Esta clave solo es aplicable a los servicios que se cargan en el dominio del sistema privilegiado.

GroupName <string>

Esta clave opcional especifica el grupo para ejecutar el trabajo. Esta clave solo es aplicable a los servicios que se cargan en el dominio del sistema privilegiado. Si UserName está configurado y GroupName no, entonces el grupo se establecerá en el grupo primario del usuario.

Finalmente codeign

Puede buscar el hash de certificados de firma utilizando find-identity

security find-identity -p codesigning -v

Codifique un marco, dylib, etc.

/usr/bin/codesign --verbose=4 -f -s "$SIGNER_HASH" "$SIGNABLE"

Codifica el paquete de aplicaciones

/usr/bin/codesign --verbose=4 -f -s "$SIGNER_HASH" --entitlements entitlements.xcent "$SIGNABLE"

Notas finales: si observa cómo lo hace Xcode, configuran CODESIGN_ALLOCATEpara usar el contenido en Xcode, no en /usr/bin.

export CODESIGN_ALLOCATE="$( xcrun --find codesign_allocate )"

La ruta de búsqueda se establece en ${PLATFORM_PATH}:${TOOLCHAIN_PATH}:${PATH}, donde la ruta PLATAFORMA es el directorio / usr / bin para el SDK de destino dado y TOOLCHAIN_PATH es / usr / bin para las herramientas de host de Xcode.

Cameron Lowell Palmer
fuente
3
Amigo, definitivamente puedes escribir un artículo al respecto, lo estaba buscando desde hace 2 días. No sé cuántas cosas y publicaciones de stackoverflow leo. Muchas gracias a ti !
Damien
¡Gracias por este útil tutorial!
Taras Nikulin el
ACL en llavero fue la parte que faltaba para mí. gracias por la clara explicación señor!
Keuha
11

Pon tus llaves en el llavero del sistema

Alistra
fuente
Pero todavía pide nombre de usuario y contraseña
Durai Amuthan.H
¿Cómo poner claves en el llavero del sistema ....... copiará pegar del trabajo de acceso de llavero?
Ashish Karpe
Arrastra y suelta @AshishKarpe
Alistra
¿Arrastrar y soltar sigue obteniendo el mismo error? .abc.xyz360 '. Se requiere la firma del código para el tipo de producto 'Aplicación' en SDK 'iOS 10.2'
Ashish Karpe
Dice que no tiene un perfil de aprovisionamiento instalado en la máquina, no es que le falten las claves @AshishKarpe
Alistra
5

Entonces este es el comando que funciona. -Aes para evitar que Mac solicite contraseña. Importar a system.keychain no requiere una GUI.

sudo security import <cert.p12> -k "/Library/Keychains/System.keychain" -P <passphrase> -A

Merlin Ran
fuente
3

Mi llavero estaba bloqueado. Se resistió a mis avances para cambiar ese hecho ...

Keychain Access-> Keychain First Aid-> Repair, et voilá !

Alex Gray
fuente
2

Desbloquear el llavero no es suficiente. También debe configurar el acceso de clave privada a "Permitir que todas las aplicaciones accedan a este elemento". Y hacer eso desde la línea de comandos requiere volver a importar la clave. Entonces, para tomar las cosas a la vez:

Desbloquee el llavero de inicio de sesión si está bloqueado. Sin embargo, no debería estar bloqueado, pero de todos modos, así es como lo haces:

security -v unlock-keychain -p "$KEYCHAIN_PASSWORD" "~/Library/Keychains/login.keychain"

Si por alguna razón su máquina de compilación tiene el llavero de inicio de sesión bloqueado, y no desea exponer esa contraseña en un script, entonces debe usar un llavero diferente. Puede crear uno en el acto y usarlo en el comando anterior y en el siguiente. Para crear uno en el acto:

security create-keychain -p 'temporaryPassword' MyKeychain.keychain
security list-keychains -d user -s login.keychain MyKeychain.keychain

Luego importe sus certificados y claves privadas asociadas al llavero de inicio de sesión utilizando el parámetro -A. Tenga en cuenta que no necesita sudo para todo esto ...

security import <cert.p12> -k "~/Library/Keychains/login.keychain" -P <passphrase> -A

El parámetro -A es lo que hará que su clave privada se configure en "Permitir que todas las aplicaciones accedan a este elemento"

Por lo tanto, al usar todo esto, debería poder crear un script que instale el certificado requerido para construir una versión ipa y firmarlo sin solicitarlo. Puede almacenar el archivo .p12 en su repositorio, de modo que cualquier máquina pueda construir su ipa sin requerir una configuración manual.

Radu Simionescu
fuente
2

Además de desbloquear el llavero (como se menciona en otras respuestas), debe permitir el acceso desde todas las aplicaciones al token de autenticación Xcode en el llavero:

  • Seleccione el llavero "iniciar sesión"
  • Seleccione la categoría "Todos los artículos"
  • Busque la palabra clave "xcode"
  • Seleccione "Permitir que todas las aplicaciones accedan a este elemento" para todos los tokens de Xcode
  • No olvides agregar el paso de desbloqueo del llavero (de respuestas anteriores)

Captura de pantalla

Vitaliy Gozhenko
fuente
1

Importe sus llaves al llavero del sistema. Puedes usar este comando:

sudo security import YourKey.p12 -k /Library/Keychains/System.keychain -P PasswordToYourKey -T /usr/bin/codesign
Lukasz Czerwinski
fuente
1

Así que probé todas las respuestas aquí y algo no cuadraba. Finalmente descubrí que cuando reiniciaba mi servicio de CI, se estaba ejecutando con un usuario diferente de lo que esperaba. Cambiar al usuario que realmente tenía acceso a la clave en su cadena de inicio de sesión solucionó todo. Puede que este no sea un problema común, pero quería documentar mi razón específica de este error, en caso de que le ocurra a otros.

Kevin DiTraglia
fuente
Tuve exactamente el mismo problema. Gracias por su respuesta. :)
Paweł K
0

Para mí, nada funcionó parece tener que reinstalar Xcode nuevamente. Jenkins sigue dando el mismo error. Ahorraría mucho tiempo si simplemente mueve la instalación de Xcode a la Papelera y la reinstala. Asegúrese de ejecutar el comando codesign desde la línea de comando al menos una vez.

Incluso después de obtener el mismo error, intente configurar '¿Desbloquear llavero?' propiedad dentro de Jenkins y proporcione la ruta a su login.keychain en /Users/${USER}/Library/Keychains/login.keychain

Espero que Dios esté contigo después de eso.

Kaushik Bhatt
fuente
0

En mi caso, esto fue causado por la creación de un llavero con un tiempo de espera predeterminado de 300 segundos y una compilación xcode larga que duró más de 300 segundos. La solución, para mí, era invocar:

security set-keychain-settings -t <longer timeout in seconds> <keychain>

inmediatamente después de crear el llavero temporal.

Justin Randall
fuente
0

Revisé todas estas sugerencias y seguía teniendo problemas para usar fastlane gym en un trabajo de Jenkins. Tenía el certificado instalado y el llavero desbloqueado, y pude firmar el código en el esclavo cuando ejecuté manualmente el comando del código en la línea de comando.

Como solución alternativa, si Jenkins se conecta al esclavo utilizando JNLP en lugar de SSH, podrá firmar el código.

Dan Stark
fuente
0

Para mí sucede cuando hay un segundo llavero agregado manualmente y está bloqueado. Por alguna razón, codesignintenta acceder al llavero bloqueado y falla a pesar de que los certificados están en el llavero de inicio de sesión (y está desbloqueado). Desbloquear el segundo resuelve el problema. Simplemente no tiene sentido para mí.

Maxime Viargues
fuente
-1

Después de probar varias de las soluciones anteriores. Me di cuenta de que un factor que tenía era que estaba comenzando la compilación usando la Consola ION. Cuando volví a hacer la compilación desde la aplicación Terminal, todo funcionó bien.

Sean Eisenheim
fuente