Назад | Перейти на главную страницу

Подтверждение доверия подписи с помощью gpg?

Мы хотели бы использовать подписи gpg для проверки некоторых аспектов наших инструментов управления конфигурацией системы. Кроме того, мы хотели бы использовать модель «доверия», в которой отдельные ключи системного администратора подписываются с помощью главного ключа подписи, а затем наши системы доверяют этому главному ключу (и используют «сеть доверия» для проверки подписей нашими системными администраторами).

Это дает нам большую гибкость, например, возможность легко отозвать доверие к ключу, когда кто-то уходит, но мы столкнулись с проблемой. В то время gpg команда будет сказать вам, если ключ не является доверенным, он, похоже, не возвращает код выхода, указывающий на этот факт. Например:

# 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 <someone@example.com>"
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

Мы заботимся о следующем:

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

Код выхода, возвращаемый gpg, в этом случае равен 0, несмотря на отказ доверия:

# echo $?
0

Как мы можем заставить gpg выйти из строя, если что-то подписано ненадежной подписью?

Я видел некоторые предположения, что gpgv команда вернет правильный код выхода, но, к сожалению gpgv не знает, как получить ключи с серверов ключей. Думаю, мы можем проанализировать вывод состояния (используя --status-fd) из gpg, но есть ли способ лучше?

Вот что получилось:

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

Это ищет информацию о доверии, которая gpg выходы на --status-fd. Скрипт завершается с ошибкой при наличии недоверенной подписи (или недействительной / нет подписи):

$ 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 <testuser@example.com>"
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

Скрипт завершается без ошибок при наличии действующей доверенной подписи:

$ 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

Итак, позвольте мне попытаться разделить проблему:

Первая проблема заключается в том, что ключ, который вы тестируете, не является надежным.

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 <jdoe@noemail.com>"
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

Я предположил, что это сделано намеренно ... но прежде чем мы перейдем к тому, как исправить, позвольте мне предложить вам использовать gpgv вместо того gpg -v? Вы поймете почему через минуту:

$ 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

Нет ключа, нет доверия ... Нет, мы импортируем ключ в trustkeys.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 <jdoe@noemail.com>" 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 <jdoe@noemail.com>"

$ echo $?
0

Надеюсь, поможет

На ум приходят два варианта (кроме анализа вывода).

Быстрый и грязный способ - бежать обе gpg и gpgv. Первый запуск gpg обеспечит выборку ключа с сервера ключей, а затем gpgv предоставит вам код возврата, который вы хотите.

Более элегантным и контролируемым способом (хотя для этого потребуется больше работы) было бы использование gpgme библиотека для проверки подписи. Это библиотека C, хотя есть оболочки для Perl, PHP, Python и Рубин. (У Python довольно низкий уровень, в то время как у Ruby есть некоторые абстракции более высокого уровня, не уверен в Perl или PHP).

Библиотека GPGME, кажется, общается с серверами ключей, когда я ее использовал, хотя вы хотите это подтвердить. Я написал немного код, использующий библиотеку ruby ​​gpgme (ищи verify и verified_ok? для кода, который проверяет подпись, и для sig_output_lines для некоторого кода, который определяет, доверяет ли подпись).

Как насчет переноса конфигурации вашей системы на такой инструмент, как Puppet или Повар?

Хотя это нетривиальный объем работы, Chef (я не использовал Puppet) вы должны создать учетные записи пользователей (и генерируются паб / закрытые ключи). Хотя это не мешает людям изменять файлы локально на сервере, chef-client запускается периодически и перезапишет свои изменения при следующем запуске. (По умолчанию выполняются периодические повторяющиеся запуски.)