summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/puppetd33
-rw-r--r--lib/puppet/executables/client/certhandler.rb68
-rwxr-xr-xspec/unit/executables/client/certhandler.rb80
3 files changed, 151 insertions, 30 deletions
diff --git a/bin/puppetd b/bin/puppetd
index 96d0e5ee8..2a71c3a8d 100755
--- a/bin/puppetd
+++ b/bin/puppetd
@@ -162,6 +162,7 @@ trap(:INT) do
end
require 'puppet'
+require 'puppet/executables/client/certhandler'
require 'puppet/network/client'
require 'getoptlong'
@@ -342,36 +343,8 @@ if Puppet[:daemonize]
client.daemonize
end
-unless Puppet::Network::HttpPool.read_cert
- # If we don't already have the certificate, then create a client to
- # request one. Use the special ca stuff, don't use the normal server and port.
- caclient = Puppet::Network::Client.ca.new()
- if options[:waitforcert] > 0
- begin
- while ! caclient.request_cert do
- Puppet.notice "Did not receive certificate"
- sleep options[:waitforcert]
- end
- rescue => detail
- Puppet.err "Could not request certificate: %s" % detail.to_s
- exit(23)
- end
- else
- unless caclient.request_cert
- Puppet.notice "No certificates; exiting"
- exit(1)
- end
- end
-
- # Now read the new cert in.
- if Puppet::Network::HttpPool.read_cert
- # If we read it in, then get rid of our existing http connection.
- client.recycle_connection
- Puppet.notice "Got signed certificate"
- else
- Puppet.err "Could not read certificates after retrieving them"
- exit(34)
- end
+unless Puppet::Executables::Client::CertHandler.new(options[:waitforcert], options[:onetime]).read_retrieve
+ client.recycle_connection
end
objects = []
diff --git a/lib/puppet/executables/client/certhandler.rb b/lib/puppet/executables/client/certhandler.rb
new file mode 100644
index 000000000..d2ead3950
--- /dev/null
+++ b/lib/puppet/executables/client/certhandler.rb
@@ -0,0 +1,68 @@
+
+module Puppet
+ module Executables
+ module Client
+ class CertHandler
+ attr_writer :wait_for_cert, :one_time
+
+ def initialize(wait_time, is_one_time)
+ @wait_for_cert = wait_time
+ @one_time = is_one_time
+ @new_cert = false
+ end
+
+ def read_retrieve
+ #NOTE: ACS this is checking that a file exists, maybe next time just do that?
+ unless read_cert
+ # If we don't already have the certificate, then create a client to
+ # request one. Use the special ca stuff, don't use the normal server and port.
+ retrieve_cert
+ end
+
+ !@new_cert
+ end
+
+ def retrieve_cert
+ caclient = Puppet::Network::Client.ca.new()
+
+ while true do
+ begin
+ if caclient.request_cert
+ break if read_new_cert
+ else
+ Puppet.notice "Did not receive certificate"
+ if @one_time
+ Puppet.notice "Set to run 'one time'; exiting with no certificate"
+ exit(1)
+ end
+ end
+ rescue StandardError => detail
+ Puppet.err "Could not request certificate: %s" % detail.to_s
+ exit(23) if @one_time
+ end
+
+ sleep @wait_for_cert
+ end
+ end
+
+ def read_cert
+ Puppet::Network::HttpPool.read_cert
+ end
+
+ def read_new_cert
+ if Puppet::Network::HttpPool.read_cert
+ # If we read it in, then we need to get rid of our existing http connection.
+ # The @new_cert flag will help us do that
+ @new_cert = true
+ Puppet.notice "Got signed certificate"
+ else
+ Puppet.err "Could not read certificates after retrieving them"
+ exit(34) if @one_time
+ end
+
+ return @new_cert
+ end
+ end
+ end
+ end
+end
diff --git a/spec/unit/executables/client/certhandler.rb b/spec/unit/executables/client/certhandler.rb
new file mode 100755
index 000000000..d12c51c1b
--- /dev/null
+++ b/spec/unit/executables/client/certhandler.rb
@@ -0,0 +1,80 @@
+#!/usr/bin/env ruby
+
+Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
+
+require 'puppet/executables/client/certhandler'
+
+cert_handler = Puppet::Executables::Client::CertHandler
+
+describe cert_handler, "when handling certificates" do
+ before do
+ @caclient = mock('caclient')
+ caclient_class = mock('caclient_class')
+ caclient_class.stubs(:new).returns(@caclient)
+ Puppet::Network::Client.stubs(:ca).returns(caclient_class)
+ end
+
+ it "should return true if the certificate exists" do
+ Puppet::Network::HttpPool.expects(:read_cert).returns(true)
+ cert_handler.new(1,true).read_retrieve.should be_true
+ end
+
+ it "should return false when getting a new cert" do
+ Puppet::Network::HttpPool.expects(:read_cert).returns(true)
+ @caclient.stubs(:request_cert).returns(true)
+ ch = cert_handler.new(1,true)
+ ch.stubs(:read_cert).returns(false)
+ ch.read_retrieve.should be_false
+ end
+
+ describe "when waiting for cert" do
+ it "should loop when the cert request fails" do
+ @caclient.stubs(:request_cert).times(2).returns(false).then.returns(true)
+ ch = cert_handler.new(1,false)
+ ch.expects(:sleep)
+ ch.expects(:read_new_cert).returns(true)
+ ch.read_retrieve
+ end
+
+ it "should loop when the cert request raises an Error" do
+ @caclient.stubs(:request_cert).times(2).raises(StandardError, 'Testing').then.returns(true)
+ ch = cert_handler.new(1,false)
+ ch.expects(:sleep)
+ ch.expects(:read_new_cert).returns(true)
+ ch.read_retrieve
+ end
+
+ it "should loop when the new cert can't be read" do
+ @caclient.stubs(:request_cert).returns(true)
+ ch = cert_handler.new(1,false)
+ ch.expects(:sleep)
+ ch.expects(:read_new_cert).times(2).returns(false).then.returns(true)
+ ch.read_retrieve
+ end
+ end
+
+ describe "when in one time mode" do
+ it "should exit if the cert request fails" do
+ @caclient.stubs(:request_cert).returns(false)
+ ch = cert_handler.new(1,true)
+ ch.expects(:exit).with(1).raises(SystemExit)
+ lambda { ch.read_retrieve }.should raise_error(SystemExit)
+ end
+
+
+ it "should exit if the cert request raises an exception" do
+ @caclient.stubs(:request_cert).raises(StandardError, 'Testing')
+ ch = cert_handler.new(1,true)
+ ch.expects(:exit).with(23).raises(SystemExit)
+ lambda { ch.read_retrieve }.should raise_error(SystemExit)
+ end
+
+ it "should exit if the new cert can't be read" do
+ @caclient.stubs(:request_cert).returns(true)
+ Puppet::Network::HttpPool.stubs(:read_cert).returns(false)
+ ch = cert_handler.new(1,true)
+ ch.expects(:exit).with(34).raises(SystemExit)
+ lambda { ch.read_retrieve }.should raise_error(SystemExit)
+ end
+ end
+end