PuppetのSSL関連のエラーについて

puppetをmaster/agent構成で利用していると、agentからmasterへの通信でSSLが使われるため、証明書関連のエラーではまりがち。証明書はmasterやegentを起動した際に自動的に作ってくれるし、master側がCAとして署名してくれるので設定自体の手間はないが、その証明書のSubjectのCNと、ネットワーク的に逆解決できる名前が一致しないと?エラーになってしまう。

問題への対処法のひとつとして、masterやagentの起動時に --certnameオプションを指定することで、証明書のSubjectを任意の値に変えることができる。

$ sudo puppet agent --certname=hoge ...
...
$ sudo openssl x509 -in /var/lib/puppet/ssl/certs/hoge.pem -text | grep Subject
        Subject: CN=hoge

この場合、マニフェストのnode定義に、--certnameオプションで指定した値を書くと、マッチするようになる。

node hoge {
  ...

ただし、masterのサーバ証明書のSubjectを変更した場合には、その名前とagent実行時に--serverオプションで指定する接続先のホスト名が一致しなければ、以下のようなエラーになるため、/etc/hostsで対応をとるなどする必要がある。

Error: Failed to apply catalog: hostname does not match the server certificate
Error: Could not send report: hostname does not match the server certificate

SSLをoffにする方法がないかと思ったが、コードのいろいろな部分でSSLの利用が前提になっているようにみえる。
agentのコードでは、必ず証明書を取得しにいく。Puppet::Application::Agent#setup_host::

  def setup_host
    @host = Puppet::SSL::Host.new
    waitforcert = options[:waitforcert] || (Puppet[:onetime] ? 0 : Puppet[:waitforcert])
    cert = @host.wait_for_cert(waitforcert) unless options[:fingerprint]
  end

managerへのアクセスのためのモジュールでは、常ににuse_sslがtrueで呼び出されている。Puppet::Network::HTTP::Connection#initialize::

    class Connection
      include Puppet::Network::Authentication
  
      def initialize(host, port, use_ssl = true)
        @host = host
        @port = port
        @use_ssl = use_ssl
      end

puppetがバージョン2の頃は、master側だけは--servertype=mongrelとすることでSSLをoffにできたが、バージョン3になってからはMongrelはサポートされなくなっていた。

そもそもmaster/agent構成を使わず、各ノードにマニフェストが格納された/etc/puppet以下をコピーし、各ノードのローカルでpuppet applyコマンドを実行して適用するのが、多くの場合に無難な気もする。
マニフェストの配置はrsyncを使うか、subversionやgitを利用してチェックアウトすればよい。psshなどを利用すれば、puppet applyコマンドの実行も含めて、割と楽にできる。

puppet applyコマンドでも--certnameオプションは指定可能で、nodeのマッチングも変わるようなので、EC2のようなホスト名が変わりやすい環境でも、役に立つかもしれない。

(上記はpuppet-3.1.1で調べた結果にもとづく。)