我们希望使用gpg签名来validation我们的系统configurationpipe理工具的某些方面。 另外,我们希望使用一个“信任”模型,在这个模型中,使用主签名密钥对各个系统pipe理员密钥进行签名,然后我们的系统相信该主密钥(并使用“信任网”来validation我们的系统pipe理员签名)。
这给了我们很大的灵活性,比如当某人离开时轻松地撤销对某个密钥的信任的能力,但是我们遇到了问题。 虽然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 <[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
我们关心的部分是这样的:
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,尽pipe信任失败:
# echo $? 0
如果用不可信签名签名的话,我们如何获得gpg失败呢?
我见过一些build议gpgv
命令将返回一个适当的退出代码,但不幸的是gpgv
不知道如何从密钥服务器获取密钥。 我想我们可以parsing从gpg
的状态输出(使用–status-fd),但有没有更好的方法?
所以让我试着分解这个问题:
第一个问题似乎是你testing的关键是不可信的。
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
我认为这是故意的…但在我们得到如何解决之前,让我build议你使用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
没有钥匙,不信任…不,我们将密钥导入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
希望它有帮助
这是结束于:
#!/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 <[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
该脚本在有效的可信签名存在的情况下不会出错:
$ 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
想到两个选项(除了parsing输出)。
一个快速和肮脏的方式将运行gpg
和gpgv
。 第一次运行gpg
将确保密钥从密钥服务器获取,然后gpgv
会给你你想要的返回码。
一个更优雅,控制的方式(尽pipe它会涉及更多的工作)将是使用gpgme库来validation签名。 这是一个C库,虽然有Perl , PHP , Python和Ruby的包装。 (Python是一个相当低的水平,而Ruby有一些更高层次的抽象,不知道Perl或PHP)。
当我使用GPGME库时,似乎要与密钥服务器通信,尽pipe您想确认一下。 我已经写了一些使用ruby gpgme库的代码 (searchverify
和verified_ok?
来validation签名,而sig_output_lines
是找出签名是否可信的代码)。
将系统configuration迁移到像Puppet或Chef这样的工具怎么样?
虽然工作量不大,厨师(我没有使用木偶),你必须创build用户帐户(并生成发布/私钥)。 虽然这不会阻止人们在服务器上本地修改文件,但是chef-client会定期运行,并会在下次运行时覆盖其更改。 (定期重复运行默认情况下发生。)