¿Validar la firma de confianza con gpg?

13

Nos gustaría utilizar las firmas gpg para verificar algunos aspectos de nuestras herramientas de administración de configuración del sistema. Además, nos gustaría usar un modelo de "confianza" en el que las claves individuales del administrador de sistemas se firman con una clave maestra de firma, y ​​luego nuestros sistemas confían en esa clave maestra (y usan la "red de confianza" para validar las firmas de nuestros administradores de sistemas).

Esto nos da mucha flexibilidad, como la capacidad de revocar fácilmente la confianza en una clave cuando alguien se va, pero nos hemos encontrado con un problema. Si bien el gpgcomando le dirá si una clave no es confiable, no parece devolver un código de salida que indique este hecho. Por ejemplo:

# gpg -v < foo.asc
Version: GnuPG v1.4.11 (GNU/Linux)
gpg: armor header: 
gpg: original file name=''
this is a test
gpg: Signature made Fri 22 Jul 2011 11:34:02 AM EDT using RSA key ID ABCD00B0
gpg: using PGP trust model
gpg: Good signature from "Testing Key <[email protected]>"
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: ABCD 1234 0527 9D0C 3C4A  CAFE BABE DEAD BEEF 00B0
gpg: binary signature, digest algorithm SHA1

La parte que nos importa es esta:

gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.

El código de salida devuelto por gpg en este caso es 0, a pesar de la falla de confianza:

# echo $?
0

¿Cómo conseguimos que gpg falle en caso de que algo esté firmado con una firma no confiable?

He visto algunas sugerencias de que el gpgvcomando devolverá un código de salida adecuado, pero desafortunadamente gpgvno sabe cómo obtener claves de los servidores de claves. Supongo que podemos analizar la salida de estado (usando --status-fd) desde gpg, pero ¿hay una mejor manera?

larsks
fuente

Respuestas:

6

Esto es lo que terminó con:

#!/bin/sh

tmpfile=$(mktemp gpgverifyXXXXXX)
trap "rm -f $tmpfile" EXIT

gpg --status-fd 3 --verify "$@" 3> $tmpfile || exit 1
egrep -q '^\[GNUPG:] TRUST_(ULTIMATE|FULLY)' $tmpfile

Esto busca la información de confianza que se gpggenera --status-fd. El script sale con un error en presencia de una firma no confiable (o inválida / sin firma):

$ sh checksig sample.sh.bad 
gpg: Signature made Mon 24 Jun 2013 11:42:58 AM EDT using RSA key ID DCD5C569
gpg: Good signature from "Test User <[email protected]>"
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 6FCD 3CF0 8BBC AD50 662E  5070 E33E D53C DCD5 C569
$ echo $?
1

El script sale sin error en presencia de una firma válida y confiable:

$ sh checksig sample.sh.good
gpg: Signature made Mon 24 Jun 2013 11:38:49 AM EDT using RSA key ID 5C2864A8
gpg: Good signature from "Lars Kellogg-Stedman <...>"
$ echo $?
0
larsks
fuente
5

Así que déjame intentar dividir el problema:

El primer problema parece que la clave con la que está probando no es de confianza.

gpg -v < test.txt.asc 
gpg: armor header: Version: GnuPG v1.4.11 (GNU/Linux)
gpg: original file name='test.txt'
this is a test
gpg: Signature made Thu 11 Aug 2011 09:09:35 PM EST using RSA key ID FE1B770E
gpg: using PGP trust model
gpg: Good signature from "John Doe <[email protected]>"
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 5DD8 216D ADB1 51E8 4326  3ACA 1DED BB72 FE1B 770E
gpg: binary signature, digest algorithm SHA1

Asumí que esto es intencional ... pero antes de que veamos cómo solucionarlo, ¿puedo sugerirle que use gpgv en lugar de gpg -v ? Verás por qué en un minuto:

$ gpgv < test.txt.asc 
gpgv: keyblock resource `/user/.gnupg/trustedkeys.gpg': file open error
gpgv: Signature made Thu 11 Aug 2011 09:09:35 PM EST using RSA key ID FE1B770E
gpgv: Can't check signature: public key not found

$ echo $?
2

Sin clave, sin confianza ... No, importamos la clave en Trustedkeys.gpg

$ gpg --no-default-keyring --keyring trustedkeys.gpg --import jdoe_pub.gpg
gpg: keyring `/user/.gnupg/trustedkeys.gpg' created
gpg: key FE1B770E: public key "John Doe <[email protected]>" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
$ gpgv < test.txt.asc 
gpgv: Signature made Thu 11 Aug 2011 09:09:35 PM EST using RSA key ID FE1B770E
gpgv: Good signature from "John Doe <[email protected]>"

$ echo $?
0

Espero eso ayude

Andre de Miranda
fuente
Comenté sobre gpgv en mi pregunta: el problema con gpgv es que si bien devuelve un código de error más útil, no sabe cómo obtener claves de un servidor de claves.
Larsks
1

Se me ocurren dos opciones (aparte de analizar la salida).

Una forma rápida y sucia sería ejecutar ambos gpg y gpgv. La primera ejecución de gpggarantizaría que la clave se obtuviera del servidor de claves, y luego gpgvle daría el código de retorno que desea.

Una forma más elegante y controlada (aunque implicaría más trabajo) sería utilizar la biblioteca gpgme para verificar la firma. Es una biblioteca C, aunque hay contenedores para Perl , PHP , Python y Ruby . (El Python tiene un nivel bastante bajo, mientras que el Ruby tiene algunas abstracciones de mayor nivel, no estoy seguro acerca de Perl o PHP).

La biblioteca GPGME parece hablar con los servidores de claves cuando la he usado, aunque querría confirmar eso. He escrito un poco de código que usa la biblioteca ruby ​​gpgme (busca verifyy verified_ok?busca código que verifique una firma, y sig_output_linespara algún código que determine si una firma es confiable).

Hamish Downer
fuente
-1

¿Qué pasa con la migración de la configuración de su sistema a una herramienta como Puppet o Chef ?

Si bien es una cantidad de trabajo no trivial, Chef (no he usado Puppet) debe crear cuentas de usuario (y se generan claves de pub / privadas). Si bien esto no impide que las personas modifiquen los archivos locales en el servidor, chef-client se ejecuta periódicamente y sobrescribirá sus cambios en la próxima ejecución. (Las ejecuciones periódicas periódicas se producen de forma predeterminada).

gWaldo
fuente