puppet の通信の仕組みにちょっと立ち入ってみる

puppet のクライアント/サーバ間通信は https + XMLRPC で、認証は SSLv3 の証明書認証が利用されています。

通常、SSLv3 で証明書認証とかいうと、CA とか、自己署名証明書とか、色々めんどくさかったりしますが、puppet はこの辺りはほとんど自動で処理してくれるので、とても楽です。

例えば、puppet サーバ側では、puppetmasterd をはじめて起動した時に、CA 関連ファイルや自己署名証明書などを、/etc/puppet/ssl 以下に勝手に作ってくれます。

$ ls -R /etc/puppet/ssl
/etc/puppet/ssl:
ca/  certs/  csr_kenny.southpark.pem  private/  private_keys/  public_keys/

/etc/puppet/ssl/ca:
ca_crl.pem  ca_key.pem  inventory.txt  requests/  signed/
ca_crt.pem  ca_pub.pem  private/       serial

/etc/puppet/ssl/ca/private:
ca.pass

/etc/puppet/ssl/ca/requests:

/etc/puppet/ssl/ca/signed:
kenny.southpark.pem

/etc/puppet/ssl/certs:
ca.pem  kenny.southpark.pem

/etc/puppet/ssl/private:

/etc/puppet/ssl/private_keys:
kenny.southpark.pem

/etc/puppet/ssl/public_keys:
kenny.southpark.pem 

あれ、CA 証明書っぽいものが二つある、と思ったら、ca/ca_crt.pem と certs/ca.pem はまったく同じものでした。

また、CA 証明書とは別に、kenny.southpark.pem というものができていますが、これはおそらく、自身が puppet クライアントになる時に利用するものと思われます。

CA 証明書の中身を覗いてみるとこんな感じ。

$ sudo openssl x509 -text -in /etc/puppet/ssl/ca/ca_crt.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 0 (0x0)
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: CN=kenny.southpark
        Validity
            Not Before: Mar 20 14:29:16 2007 GMT
            Not After : Mar 18 14:29:16 2012 GMT
        Subject: CN=kenny.southpark
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:ea:83:02:5a:83:08:02:c8:bc:cd:d0:26:07:e7:
                    44:f7:a0:0e:0f:26:23:82:ba:e4:ed:d7:c8:88:c6:
                    43:b7:0a:5d:16:39:a2:6a:48:f9:8f:a5:9d:35:2f:
                    24:1e:ec:38:6b:73:0f:23:17:84:70:7e:08:08:96:
                    bd:e6:51:53:f2:fe:1d:ec:2f:d0:9a:5b:3d:ea:92:
                    8a:39:f5:ff:02:ff:6b:e4:d2:ef:9f:d2:c3:d6:35:
                    d8:5c:51:42:d9:16:59:62:c5:da:9a:9d:cd:f7:91:
                    a7:06:0b:28:8e:7f:4a:52:bc:5f:c3:5c:cb:b3:e3:
                    81:d0:1b:ca:b6:7f:73:b2:3f
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            Netscape Comment:
            Puppet Ruby/OpenSSL Generated Certificate
            X509v3 Basic Constraints: critical
            CA:TRUE
            X509v3 Subject Key Identifier:
            82:0D:36:AD:29:30:30:2D:CC:2D:EB:EA:F9:32:07:44:80:11:D3:E6
            X509v3 Key Usage:
            Certificate Sign, CRL Sign
    Signature Algorithm: sha1WithRSAEncryption
        e0:0b:a7:28:39:8e:09:cc:91:85:ce:13:19:c1:9b:ba:21:c3:
        d8:09:c2:ee:93:ac:8d:76:91:18:7a:31:01:fc:55:8b:84:e6:
        69:3f:f5:a3:62:ce:cc:af:87:21:42:d4:0d:ab:02:62:26:4f:
        c2:f4:a2:22:4f:52:a5:06:bd:88:4c:65:89:9e:98:4c:cb:82:
        ce:09:50:e0:4b:67:59:1e:d7:26:75:2f:6f:3d:d3:d4:92:55:
        79:06:5e:56:39:2b:15:b0:67:d9:00:79:09:37:86:1a:a1:30:
        e0:ce:e8:2b:0a:16:92:73:a3:b8:1f:16:c8:60:f7:7d:c5:24:
        09:66
-----BEGIN CERTIFICATE-----
MIICIzCCAYygAwIBAgIBADANBgkqhkiG9w0BAQUFADAaMRgwFgYDVQQDDA9rZW5u
eS5zb3V0aHBhcmswHhcNMDcwMzIwMTQyOTE2WhcNMTIwMzE4MTQyOTE2WjAaMRgw
FgYDVQQDDA9rZW5ueS5zb3V0aHBhcmswgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
AoGBAOqDAlqDCALIvM3QJgfnRPegDg8mI4K65O3XyIjGQ7cKXRY5ompI+Y+lnTUv
JB7sOGtzDyMXhHB+CAiWveZRU/L+Hewv0JpbPeqSijn1/wL/a+TS75/Sw9Y12FxR
QtkWWWLF2pqdzfeRpwYLKI5/SlK8X8Ncy7PjgdAbyrZ/c7I/AgMBAAGjeTB3MDgG
CWCGSAGG+EIBDQQrFilQdXBwZXQgUnVieS9PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0
aWZpY2F0ZTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSCDTatKTAwLcwt6+r5
MgdEgBHT5jALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEFBQADgYEA4AunKDmOCcyR
hc4TGcGbuiHD2AnC7pOsjXaRGHoxAfxVi4TmaT/1o2LOzK+HIULUDasCYiZPwvSi
Ik9SpQa9iExliZ6YTMuCzglQ4EtnWR7XJnUvbz3T1JJVeQZeVjkrFbBn2QB5CTeG
GqEw4M7oKwoWknOjuB8WyGD3fcUkCWY=
-----END CERTIFICATE-----    

次にクライアント側ですが、こちらもはじめて puppetd(クライアント側で起動するデーモン)を実行した時に、秘密鍵、公開鍵、CSR を自動的に作成し、サーバに対して CSR への署名を求めることが、起動時のメッセージから読み取れます。

$ sudo /usr/sbin/puppetd --server mizzy.org --test
err: No certificate; running with reduced functionality.
info: Creating a new SSL key at /var/lib/puppet/ssl/private_keys/cartman.southpark.pem
info: Creating a new certificate request for cartman.southpark
info: Requesting certificate
warning: peer certificate won't be verified in this SSL session
notice: Did not receive certificate

サーバ側では、証明書リクエストが来ていることを、次のようなコマンドで確認できます。

$ sudo puppetca --list
cartman.southpark

これに署名するには、

$ sudo puppetca --sign cartman.southpark

と実行するだけです。これで puppet クライアント/サーバ間で無事通信できるようになります。

セキュアな通信が割りと簡単に実現できていい感じ。