diff options
| -rw-r--r-- | lib/puppet/ssl/host.rb | 15 | ||||
| -rwxr-xr-x | spec/unit/ssl/host.rb | 78 |
2 files changed, 91 insertions, 2 deletions
diff --git a/lib/puppet/ssl/host.rb b/lib/puppet/ssl/host.rb index a65490c40..acd27edb6 100644 --- a/lib/puppet/ssl/host.rb +++ b/lib/puppet/ssl/host.rb @@ -167,14 +167,27 @@ class Puppet::SSL::Host def certificate unless @certificate + generate_key unless key + # get the CA cert first, since it's required for the normal cert # to be of any use. return nil unless Certificate.find("ca") unless ca? - @certificate = Certificate.find(name) + return nil unless @certificate = Certificate.find(name) + + unless certificate_matches_key? + raise Puppet::Error, "Retrieved certificate does not match private key; please remove certificate from server and regenerate it with the current key" + end end @certificate end + def certificate_matches_key? + return false unless key + return false unless certificate + + return certificate.content.check_private_key(key.content) + end + # Generate all necessary parts of our ssl host. def generate generate_key unless key diff --git a/spec/unit/ssl/host.rb b/spec/unit/ssl/host.rb index 646f7b55b..e4140f44c 100755 --- a/spec/unit/ssl/host.rb +++ b/spec/unit/ssl/host.rb @@ -90,6 +90,55 @@ describe Puppet::SSL::Host do Puppet::SSL::Host.localhost.should equal(two) end + it "should be able to verify its certificate matches its key" do + Puppet::SSL::Host.new("foo").should respond_to(:certificate_matches_key?) + end + + it "should consider the certificate invalid if it cannot find a key" do + host = Puppet::SSL::Host.new("foo") + host.expects(:key).returns nil + + host.should_not be_certificate_matches_key + end + + it "should consider the certificate invalid if it cannot find a certificate" do + host = Puppet::SSL::Host.new("foo") + host.expects(:key).returns mock("key") + host.expects(:certificate).returns nil + + host.should_not be_certificate_matches_key + end + + it "should consider the certificate invalid if the SSL certificate's key verification fails" do + host = Puppet::SSL::Host.new("foo") + + key = mock 'key', :content => "private_key" + sslcert = mock 'sslcert' + certificate = mock 'cert', :content => sslcert + + host.stubs(:key).returns key + host.stubs(:certificate).returns certificate + + sslcert.expects(:check_private_key).with("private_key").returns false + + host.should_not be_certificate_matches_key + end + + it "should consider the certificate valid if the SSL certificate's key verification succeeds" do + host = Puppet::SSL::Host.new("foo") + + key = mock 'key', :content => "private_key" + sslcert = mock 'sslcert' + certificate = mock 'cert', :content => sslcert + + host.stubs(:key).returns key + host.stubs(:certificate).returns certificate + + sslcert.expects(:check_private_key).with("private_key").returns true + + host.should be_certificate_matches_key + end + describe "when specifying the CA location" do before do [Puppet::SSL::Key, Puppet::SSL::Certificate, Puppet::SSL::CertificateRequest, Puppet::SSL::CertificateRevocationList].each do |klass| @@ -360,6 +409,9 @@ describe Puppet::SSL::Host do before do @realcert = mock 'certificate' @cert = stub 'cert', :content => @realcert + + @host.stubs(:key).returns mock("key") + @host.stubs(:certificate_matches_key?).returns true end it "should find the CA certificate if it does not have a certificate" do @@ -384,6 +436,22 @@ describe Puppet::SSL::Host do @host.certificate.should be_nil end + it "should find the key if it does not have one" do + Puppet::SSL::Certificate.stubs(:find) + @host.expects(:key).returns mock("key") + + @host.certificate + end + + it "should generate the key if one cannot be found" do + Puppet::SSL::Certificate.stubs(:find) + + @host.expects(:key).returns nil + @host.expects(:generate_key) + + @host.certificate + end + it "should find the certificate in the Certificate class and return the Puppet certificate instance" do Puppet::SSL::Certificate.expects(:find).with("ca").returns mock("cacert") Puppet::SSL::Certificate.expects(:find).with("myname").returns @cert @@ -391,6 +459,14 @@ describe Puppet::SSL::Host do @host.certificate.should equal(@cert) end + it "should fail if the found certificate does not match the private key" do + @host.expects(:certificate_matches_key?).returns false + + Puppet::SSL::Certificate.stubs(:find).returns @cert + + lambda { @host.certificate }.should raise_error(Puppet::Error) + end + it "should return any previously found certificate" do Puppet::SSL::Certificate.expects(:find).with("ca").returns mock("cacert") Puppet::SSL::Certificate.expects(:find).with("myname").returns(@cert).once @@ -468,7 +544,7 @@ describe Puppet::SSL::Host do end it "should generate a key if one is not present" do - @host.expects(:key).returns nil + @host.stubs(:key).returns nil @host.expects(:generate_key) @host.generate |
