summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/puppet/ssl/host.rb15
-rwxr-xr-xspec/unit/ssl/host.rb78
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