diff options
| author | Luke Kanies <luke@madstop.com> | 2008-04-28 12:16:16 -0500 |
|---|---|---|
| committer | Luke Kanies <luke@madstop.com> | 2008-04-28 12:16:16 -0500 |
| commit | 83519f4e59f68f867f8ddbe141ac8bd9a6238ae1 (patch) | |
| tree | a8fbd0e17b70abde2646659bef25b3aff91c7d63 | |
| parent | 0e8a1c9f6ac45e9e6f6dcf6464ad4d2780201ce1 (diff) | |
Interim commit, since I want to work but have no network available.
| -rw-r--r-- | lib/puppet/network/http/webrick.rb | 39 | ||||
| -rw-r--r-- | lib/puppet/ssl/host.rb | 14 | ||||
| -rw-r--r-- | spec/integration/network/server/webrick.rb | 98 | ||||
| -rw-r--r-- | spec/unit/network/http/webrick.rb | 139 | ||||
| -rwxr-xr-x | spec/unit/ssl/host.rb | 45 |
5 files changed, 259 insertions, 76 deletions
diff --git a/lib/puppet/network/http/webrick.rb b/lib/puppet/network/http/webrick.rb index 762c29451..8ccf974c6 100644 --- a/lib/puppet/network/http/webrick.rb +++ b/lib/puppet/network/http/webrick.rb @@ -3,6 +3,9 @@ require 'webrick/https' require 'puppet/network/http/webrick/rest' require 'thread' +require 'puppet/ssl/certificate' +require 'puppet/ssl/certificate_revocation_list' + class Puppet::Network::HTTP::WEBrick def initialize(args = {}) @listening = false @@ -54,7 +57,7 @@ class Puppet::Network::HTTP::WEBrick end end - # Configure out http log file. + # Configure our http log file. def setup_logger # Make sure the settings are all ready for us. Puppet.settings.use(:main, :ssl, Puppet[:name]) @@ -84,39 +87,43 @@ class Puppet::Network::HTTP::WEBrick def setup_ssl results = {} - results[:SSLCertificateStore] = setup_crl if Puppet[:cacrl] != 'false' + host = Puppet::SSL::Host.new + + host.generate unless host.key + + raise Puppet::Error, "Could not retrieve certificate for %s" % host.name unless host.certificate - results[:SSLCertificate] = self.cert - results[:SSLPrivateKey] = self.key + results[:SSLPrivateKey] = host.key.content + results[:SSLCertificate] = host.certificate.content results[:SSLStartImmediately] = true results[:SSLEnable] = true + + unless Puppet::SSL::Certificate.find("ca") + raise Puppet::Error, "Could not find CA certificate" + end + results[:SSLCACertificateFile] = Puppet[:localcacert] results[:SSLVerifyClient] = OpenSSL::SSL::VERIFY_PEER + + # LAK:NOTE I'm not sure why this is this way, actually. results[:SSLCertName] = nil + results[:SSLCertificateStore] = setup_ssl_store if Puppet[:cacrl] != 'false' + results end # Create our Certificate revocation list - def setup_crl - nil - if Puppet[:cacrl] == 'false' - # No CRL, no store needed - return nil - end - unless File.exist?(Puppet[:cacrl]) + def setup_ssl_store + unless crl = Puppet::SSL::CertificateRevocationList.find("ca") raise Puppet::Error, "Could not find CRL; set 'cacrl' to 'false' to disable CRL usage" end - crl = OpenSSL::X509::CRL.new(File.read(Puppet[:cacrl])) store = OpenSSL::X509::Store.new store.purpose = OpenSSL::X509::PURPOSE_ANY store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL|OpenSSL::X509::V_FLAG_CRL_CHECK - unless self.ca_cert - raise Puppet::Error, "Could not find CA certificate" - end store.add_file(Puppet[:localcacert]) - store.add_crl(crl) + store.add_crl(crl.content) return store end diff --git a/lib/puppet/ssl/host.rb b/lib/puppet/ssl/host.rb index 25e31943a..e89f21676 100644 --- a/lib/puppet/ssl/host.rb +++ b/lib/puppet/ssl/host.rb @@ -141,8 +141,18 @@ class Puppet::SSL::Host @certificate end - def initialize(name) - @name = name + # Generate all necessary parts of our ssl host. + def generate + generate_key unless key + generate_certificate_request unless certificate_request + + # Now try to find our actual certificate; this should hopefully get + # the cert from the server and then cache it locally. + certificate() + end + + def initialize(name = nil) + @name = name || Puppet[:certname] @key = @certificate = @certificate_request = nil @ca = (name == self.class.ca_name) end diff --git a/spec/integration/network/server/webrick.rb b/spec/integration/network/server/webrick.rb index 61ccb09aa..bcfdc16ea 100644 --- a/spec/integration/network/server/webrick.rb +++ b/spec/integration/network/server/webrick.rb @@ -1,50 +1,62 @@ require File.dirname(__FILE__) + '/../../../spec_helper' require 'puppet/network/server' +require 'puppet/ssl/certificate_authority' require 'socket' describe Puppet::Network::Server do - describe "when using webrick" do - before :each do - Puppet[:servertype] = 'webrick' - @params = { :address => "127.0.0.1", :port => 34343, :handlers => [ :node ] } - - # LAK:NOTE (4/08) Stub the ssl support for now; we'll remove it once it's actually - # functional. - Puppet::Network::HTTP::WEBrick.any_instance.stubs(:setup_ssl).returns({}) - end - - describe "before listening" do - it "should not be reachable at the specified address and port" do - lambda { TCPSocket.new('127.0.0.1', 34343) }.should raise_error - end - end - - describe "when listening" do - it "should be reachable on the specified address and port" do - @server = Puppet::Network::Server.new(@params.merge(:port => 34343)) - @server.listen - lambda { TCPSocket.new('127.0.0.1', 34343) }.should_not raise_error - end - - it "should not allow multiple servers to listen on the same address and port" do - @server = Puppet::Network::Server.new(@params.merge(:port => 34343)) - @server.listen - @server2 = Puppet::Network::Server.new(@params.merge(:port => 34343)) - lambda { @server2.listen }.should raise_error - end - - after :each do - @server.unlisten if @server.listening? - end - end - - describe "after unlistening" do - it "should not be reachable on the port and address assigned" do - @server = Puppet::Network::Server.new(@params.merge(:port => 34343)) - @server.listen - @server.unlisten - lambda { TCPSocket.new('127.0.0.1', 34343) }.should raise_error(Errno::ECONNREFUSED) - end + describe "when using webrick" do + before :each do + Puppet[:servertype] = 'webrick' + @params = { :address => "127.0.0.1", :port => 34343, :handlers => [ :node ] } + + # Get a safe temporary file + @tmpfile = Tempfile.new("webrick_integration_testing") + @dir = @tmpfile.path + "_dir" + + Puppet.settings[:confdir] = @dir + Puppet.settings[:vardir] = @dir + + ca = Puppet::SSL::CertificateAuthority.new + ca.generate(Puppet[:certname]) unless Puppet::SSL::Certificate.find(Puppet[:certname]) + end + + after do + @tmpfile.delete + Puppet.settings.clear + end + + describe "before listening" do + it "should not be reachable at the specified address and port" do + lambda { TCPSocket.new('127.0.0.1', 34343) }.should raise_error + end + end + + describe "when listening" do + it "should be reachable on the specified address and port" do + @server = Puppet::Network::Server.new(@params.merge(:port => 34343)) + @server.listen + lambda { TCPSocket.new('127.0.0.1', 34343) }.should_not raise_error + end + + it "should not allow multiple servers to listen on the same address and port" do + @server = Puppet::Network::Server.new(@params.merge(:port => 34343)) + @server.listen + @server2 = Puppet::Network::Server.new(@params.merge(:port => 34343)) + lambda { @server2.listen }.should raise_error + end + + after :each do + @server.unlisten if @server.listening? + end + end + + describe "after unlistening" do + it "should not be reachable on the port and address assigned" do + @server = Puppet::Network::Server.new(@params.merge(:port => 34343)) + @server.listen + @server.unlisten + lambda { TCPSocket.new('127.0.0.1', 34343) }.should raise_error(Errno::ECONNREFUSED) + end + end end - end end diff --git a/spec/unit/network/http/webrick.rb b/spec/unit/network/http/webrick.rb index 150e9efbc..1955c3e00 100644 --- a/spec/unit/network/http/webrick.rb +++ b/spec/unit/network/http/webrick.rb @@ -156,17 +156,59 @@ describe Puppet::Network::HTTP::WEBrick do end describe "when configuring an x509 store" do - it "should add the CRL to the store" + before do + @store = stub 'store' + @store.stub_everything + + @crl = stub 'crl', :content => 'real_crl' + Puppet::SSL::CertificateRevocationList.stubs(:find).returns @crl + + @cacert = mock 'cacert' + Puppet::SSL::Certificate.stubs(:find).with('ca').returns @crl + + OpenSSL::X509::Store.stubs(:new).returns @store + end + + it "should create a new x509 store" do + OpenSSL::X509::Store.expects(:new).returns @store + + @server.setup_ssl_store + end + + it "should fail if no CRL can be found" do + Puppet::SSL::CertificateRevocationList.stubs(:find).returns nil + + lambda { @server.setup_ssl_store }.should raise_error(Puppet::Error) + end + + it "should add the CRL to the store" do + @store.expects(:add_crl).with "real_crl" + + @server.setup_ssl_store + end + + it "should add the CA certificate file to the store" do + Puppet.settings.stubs(:value).with(:localcacert).returns "/ca/cert" + @store.expects(:add_file).with "/ca/cert" - it "should create a new x509 store" + @server.setup_ssl_store + end - it "should add the CA certificate to the store" + it "should set the store's flags to 'OpenSSL::X509::V_FLAG_CRL_CHECK_ALL|OpenSSL::X509::V_FLAG_CRL_CHECK'" do + @store.expects(:flags=).with(OpenSSL::X509::V_FLAG_CRL_CHECK_ALL|OpenSSL::X509::V_FLAG_CRL_CHECK) - it "should set the store's flags to 'OpenSSL::X509::V_FLAG_CRL_CHECK_ALL|OpenSSL::X509::V_FLAG_CRL_CHECK'" + @server.setup_ssl_store + end - it "should set the store's purpose to 'OpenSSL::X509::PURPOSE_ANY'" + it "should set the store's purpose to 'OpenSSL::X509::PURPOSE_ANY'" do + @store.expects(:purpose=).with OpenSSL::X509::PURPOSE_ANY - it "should return the store" + @server.setup_ssl_store + end + + it "should return the store" do + @server.setup_ssl_store.should equal(@store) + end end describe "when configuring an http logger" do @@ -250,22 +292,89 @@ describe Puppet::Network::HTTP::WEBrick do end describe "when configuring ssl" do - it "should add an x509 store if the CRL is enabled" + before do + @server.stubs(:setup_ssl_store) + + @key = stub 'key', :content => "mykey" + @cert = stub 'cert', :content => "mycert" + @host = stub 'host', :key => @key, :certificate => @cert, :name => "yay" + + Puppet::SSL::Certificate.stubs(:find).with('ca').returns @cert - it "should not add an x509 store if the CRL is disabled" + Puppet::SSL::Host.stubs(:new).returns @host + end - it "should configure the certificate" + it "should use the key from an SSL::Host instance created with the default name" do + Puppet::SSL::Host.expects(:new).returns @host + @host.expects(:key).returns "mykey" - it "should configure the private key" + @server.setup_ssl[:SSLPrivateKey].should == "mykey" + end - it "should start ssl immediately" + it "should generate a key if no key can be found" do + @host.expects(:key).times(2).returns(nil).then.returns(@key) - it "should enable ssl" + @host.expects(:generate) - it "should specify the path to the CA certificate" + @server.setup_ssl + end - it "should configure the verification method as 'OpenSSL::SSL::VERIFY_PEER'" + it "should fail if no certificate can be found" do + @host.expects(:certificate).returns nil - it "should set the certificate name to 'nil'" + lambda { @server.setup_ssl }.should raise_error(Puppet::Error) + end + + it "should configure the certificate" do + @server.setup_ssl[:SSLCertificate].should == "mycert" + end + + it "should fail if no CA certificate can be found" do + Puppet::SSL::Certificate.stubs(:find).with('ca').returns nil + + lambda { @server.setup_ssl }.should raise_error(Puppet::Error) + end + + it "should specify the path to the CA certificate" do + Puppet.settings.stubs(:value).returns "whatever" + Puppet.settings.stubs(:value).with(:cacrl).returns 'false' + Puppet.settings.stubs(:value).with(:localcacert).returns '/ca/crt' + + @server.setup_ssl[:SSLCACertificateFile].should == "/ca/crt" + end + + it "should start ssl immediately" do + @server.setup_ssl[:SSLStartImmediately].should be_true + end + + it "should enable ssl" do + @server.setup_ssl[:SSLEnable].should be_true + end + + it "should configure the verification method as 'OpenSSL::SSL::VERIFY_PEER'" do + @server.setup_ssl[:SSLVerifyClient].should == OpenSSL::SSL::VERIFY_PEER + end + + it "should add an x509 store if the CRL is enabled" do + Puppet.settings.stubs(:value).returns "whatever" + Puppet.settings.stubs(:value).with(:cacrl).returns '/my/crl' + + @server.expects(:setup_ssl_store).returns("mystore") + + @server.setup_ssl[:SSLCertificateStore].should == "mystore" + end + + it "should not add an x509 store if the CRL is disabled" do + Puppet.settings.stubs(:value).returns "whatever" + Puppet.settings.stubs(:value).with(:cacrl).returns 'false' + + @server.expects(:setup_ssl_store).never + + @server.setup_ssl[:SSLCertificateStore].should be_nil + end + + it "should set the certificate name to 'nil'" do + @server.setup_ssl[:SSLCertName].should be_nil + end end end diff --git a/spec/unit/ssl/host.rb b/spec/unit/ssl/host.rb index 4e0f5c5df..66e21cd79 100755 --- a/spec/unit/ssl/host.rb +++ b/spec/unit/ssl/host.rb @@ -155,6 +155,19 @@ describe Puppet::SSL::Host do end end + describe "when initializing" do + it "should default its name to the :certname setting" do + Puppet.settings.expects(:value).with(:certname).returns "myname" + + Puppet::SSL::Host.new.name.should == "myname" + end + + it "should indicate that it is a CA host if its name matches the ca_name constant" do + Puppet::SSL::Host.stubs(:ca_name).returns "myca" + Puppet::SSL::Host.new("myca").should be_ca + end + end + describe "when managing its private key" do before do @realkey = "mykey" @@ -314,4 +327,36 @@ describe Puppet::SSL::Host do end end end + + it "should have a method for generating all necessary files" do + Puppet::SSL::Host.new("me").should respond_to(:generate) + end + + describe "when generating files" do + before do + @host = Puppet::SSL::Host.new("me") + @host.stubs(:generate_key) + @host.stubs(:generate_certificate_request) + end + + it "should generate a key if one is not present" do + @host.expects(:key).returns nil + @host.expects(:generate_key) + + @host.generate + end + + it "should generate a certificate request if one is not present" do + @host.expects(:certificate_request).returns nil + @host.expects(:generate_certificate_request) + + @host.generate + end + + it "should seek its certificate" do + @host.expects(:certificate) + + @host.generate + end + end end |
