Validando a confiança da assinatura com o gpg?

13

Gostaríamos de usar assinaturas gpg para verificar alguns aspectos de nossas ferramentas de gerenciamento de configuração do sistema. Além disso, gostaríamos de usar um modelo de "confiança" em que chaves sysadmin individuais são assinadas com uma chave de assinatura principal e, em seguida, nossos sistemas confiam nessa chave mestra (e usam a "rede de confiança" para validar assinaturas por nossos administradores de sistema).

Isso nos dá muita flexibilidade, como a capacidade de revogar facilmente a confiança em uma chave quando alguém sai, mas encontramos um problema. Embora o gpgcomando diga se uma chave não é confiável, ela não parece retornar um código de saída indicando esse fato. Por exemplo:

# 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

A parte com a qual nos preocupamos é a seguinte:

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

O código de saída retornado por gpg nesse caso é 0, apesar da falha de confiança:

# echo $?
0

Como fazemos com que o gpg falhe no caso de algo ser assinado com uma assinatura não confiável?

Eu já vi algumas sugestões de que o gpgvcomando retornará um código de saída adequado, mas infelizmente gpgvnão sabe como buscar chaves dos servidores de chaves. Eu acho que podemos analisar a saída de status (usando --status-fd) gpg, mas existe uma maneira melhor?

larsks
fonte

Respostas:

6

Isto é o que acabou com:

#!/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

Isso procura as informações de confiança que são gpgexibidas --status-fd. O script sai com um erro na presença de uma assinatura não confiável (ou inválida / sem assinatura):

$ 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

O script sai sem erro na presença de uma assinatura confiável e válida:

$ 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
fonte
5

Então, deixe-me tentar dividir o problema:

A primeira questão parece que a chave contra a qual você está testando não é confiável.

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

Eu assumi que isso é intencional ... mas antes de começarmos a consertar, deixe-me sugerir que você use gpgv em vez de gpg -v ? Você verá o porquê em um 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

Nenhuma chave, nenhuma confiança ... Não, nós importamos a chave para confiávelkeys.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 que ajude

Andre de Miranda
fonte
Comentei sobre o gpgv na minha pergunta - o problema com o gpgv é que, embora ele retorne um código de erro mais útil, ele não sabe como buscar chaves de um servidor de chaves.
Larsks
1

Duas opções vêm à mente (além de analisar a saída).

Uma maneira rápida e suja seria executar ambos gpg e gpgv. A primeira execução gpggarantiria que a chave fosse buscada no servidor de chaves e gpgvforneceria o código de retorno desejado.

Uma maneira mais elegante e controlada (embora isso envolvesse mais trabalho) seria usar a biblioteca gpgme para verificar a assinatura. É uma biblioteca C, embora haja wrappers para Perl , PHP , Python e Ruby . (O Python é de nível bastante baixo, enquanto o Ruby tem algumas abstrações de nível superior, não tenho certeza sobre Perl ou PHP).

A biblioteca GPGME parece conversar com os servidores de chaves quando eu a usei, embora você queira confirmar isso. Eu escrevi um pouco de código que usa a biblioteca ruby ​​gpgme (pesquise verifye identifique overified_ok? código que verifica uma assinatura, e procure sig_output_linesalgum código que verifique se uma assinatura é confiável).

Hamish Downer
fonte
-1

Que tal migrar a configuração do sistema para uma ferramenta como Puppet ou Chef ?

Enquanto uma quantidade não trivial de trabalho, Chef (eu não usei o Puppet), você deve criar contas de usuário (e chaves públicas / privadas são geradas). Embora isso não impeça as pessoas de modificar os arquivos locais no servidor, o chef-client é executado periodicamente e substituirá as alterações na próxima execução. (Execuções periódicas periódicas ocorrem por padrão.)

gWaldo
fonte