summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2008-03-19 17:30:39 -0500
committerLuke Kanies <luke@madstop.com>2008-04-15 21:34:05 -0500
commitee07d0b7f198857f700b9ad09713fe6b992ffee8 (patch)
tree48b5606de64d9c315d56ef1fc0c797045a762188
parentdc5c73bc72810bf63236581cdc9407b039ea135d (diff)
downloadpuppet-ee07d0b7f198857f700b9ad09713fe6b992ffee8.tar.gz
puppet-ee07d0b7f198857f700b9ad09713fe6b992ffee8.tar.xz
puppet-ee07d0b7f198857f700b9ad09713fe6b992ffee8.zip
Adding tests for the certificate serial numbers
-rw-r--r--lib/puppet/ssl/certificate_authority.rb20
-rwxr-xr-xspec/unit/ssl/certificate_authority.rb184
2 files changed, 194 insertions, 10 deletions
diff --git a/lib/puppet/ssl/certificate_authority.rb b/lib/puppet/ssl/certificate_authority.rb
index 971a9965e..19887c70b 100644
--- a/lib/puppet/ssl/certificate_authority.rb
+++ b/lib/puppet/ssl/certificate_authority.rb
@@ -61,28 +61,28 @@ class Puppet::SSL::CertificateAuthority < Puppet::SSL::Host
end
# Sign a given certificate request.
- def sign(host, cert_type = :service, self_signed = false)
- # This is only used by the CA for self-signing.
- if host.is_a?(Puppet::SSL::CertificateRequest)
- csr = host
- host = csr.name
+ def sign(host, cert_type = :server, self_signing_csr = nil)
+
+ # This is a self-signed certificate
+ if self_signing_csr
+ csr = self_signing_csr
issuer = csr.content
else
+ raise ArgumentError, "Cannot find CA certificate; cannot sign certificate for %s" % host unless certificate
unless csr = Puppet::SSL::CertificateRequest.find(host, :in => :ca_file)
- raise Puppet::Error, "Could not find certificate request for %s" % host
+ raise ArgumentError, "Could not find certificate request for %s" % host
end
issuer = certificate.content
end
- raise Puppet::Error, "Certificate request for #{host} does not match its own public key" unless csr.content.verify(csr.content.public_key)
- raise ArgumentError, "Cannot find CA certificate; cannot sign certificate for %s" % host unless self_signed or certificate
-
cert = Puppet::SSL::Certificate.new(host)
cert.content = Puppet::SSL::CertificateFactory.new(cert_type, csr.content, issuer, next_serial).result
# Save the now-signed cert, unless it's a self-signed cert, since we
# assume it goes somewhere else.
- cert.save(:in => :ca_file) unless self_signed
+ cert.save(:in => :ca_file) unless self_signing_csr
+
+ return cert
end
# Do all of the initialization necessary to set up our
diff --git a/spec/unit/ssl/certificate_authority.rb b/spec/unit/ssl/certificate_authority.rb
index b1b33f8b9..8fb23d883 100755
--- a/spec/unit/ssl/certificate_authority.rb
+++ b/spec/unit/ssl/certificate_authority.rb
@@ -113,4 +113,188 @@ describe Puppet::SSL::CertificateAuthority do
end
end
end
+
+ describe "when signing" do
+ before do
+ Puppet.settings.stubs(:value).with(:certname).returns "whatever"
+
+ Puppet::SSL::CertificateAuthority.any_instance.stubs(:password?).returns true
+
+ # Set up the CA
+ @key = mock 'key'
+ @key.stubs(:content).returns "cakey"
+ Puppet::SSL::CertificateAuthority.any_instance.stubs(:key).returns @key
+ @cacert = mock 'certificate'
+ @cacert.stubs(:content).returns "cacertificate"
+ Puppet::SSL::CertificateAuthority.any_instance.stubs(:certificate).returns @cacert
+ @ca = Puppet::SSL::CertificateAuthority.new
+
+ # Stub out the factory
+ @name = "myhost"
+ @cert = stub 'certificate', :content => "mycert"
+ Puppet::SSL::Certificate.stubs(:new).returns @cert
+
+ @cert.stubs(:content=)
+
+ @factory = stub 'factory', :result => "my real cert"
+ Puppet::SSL::CertificateFactory.stubs(:new).returns @factory
+
+ @request = stub 'request', :content => "myrequest"
+ end
+
+ describe "and calculating the next certificate serial number" do
+ before do
+ @path = "/path/to/serial"
+ Puppet.settings.stubs(:value).with(:serial).returns @path
+
+ @filehandle = stub 'filehandle', :<< => @filehandle
+ Puppet.settings.stubs(:readwritelock).with(:serial).yields @filehandle
+ end
+
+ it "should default to 0x0 for the first serial number" do
+ @ca.next_serial.should == 0x0
+ end
+
+ it "should return the current content of the serial file" do
+ FileTest.expects(:exist?).with(@path).returns true
+ File.expects(:read).with(@path).returns "0002"
+
+ @ca.next_serial.should == 2
+ end
+
+ it "should write the next serial number to the serial file as hex" do
+ @filehandle.expects(:<<).with("0001")
+
+ @ca.next_serial
+ end
+
+ it "should lock the serial file while writing" do
+ Puppet.settings.expects(:readwritelock).with(:serial)
+
+ @ca.next_serial
+ end
+ end
+
+ describe "its own certificate" do
+ before do
+ @serial = 10
+ @ca.stubs(:next_serial).returns @serial
+ end
+
+ it "should not look up a certificate request for the host" do
+ Puppet::SSL::CertificateRequest.expects(:find).never
+
+ @ca.sign(@name, :ca, @request)
+ end
+
+ it "should use a certificate type of :ca" do
+ Puppet::SSL::CertificateFactory.expects(:new).with do |*args|
+ args[0] == :ca
+ end.returns @factory
+ @ca.sign(@name, :ca, @request)
+ end
+
+ it "should pass the provided CSR as the CSR" do
+ Puppet::SSL::CertificateFactory.expects(:new).with do |*args|
+ args[1] == "myrequest"
+ end.returns @factory
+ @ca.sign(@name, :ca, @request)
+ end
+
+ it "should use the provided CSR's content as the issuer" do
+ Puppet::SSL::CertificateFactory.expects(:new).with do |*args|
+ args[2] == "myrequest"
+ end.returns @factory
+ @ca.sign(@name, :ca, @request)
+ end
+
+ it "should pass the next serial as the serial number" do
+ Puppet::SSL::CertificateFactory.expects(:new).with do |*args|
+ args[3] == @serial
+ end.returns @factory
+ @ca.sign(@name, :ca, @request)
+ end
+
+ it "should not save the resulting certificate" do
+ @cert.expects(:save).never
+ end
+ end
+
+ describe "another host's certificate" do
+ before do
+ @serial = 10
+ @ca.stubs(:next_serial).returns @serial
+
+ Puppet::SSL::CertificateRequest.stubs(:find).with(@name, :in => :ca_file).returns @request
+ @cert.stubs :save
+ end
+
+ it "should fail if the CA certificate cannot be found" do
+ @ca.expects(:certificate).returns nil
+
+ Puppet::SSL::CertificateRequest.stubs(:find).returns "csr"
+
+ lambda { @ca.sign("myhost") }.should raise_error(ArgumentError)
+ end
+
+ it "should use a certificate type of :server" do
+ Puppet::SSL::CertificateFactory.expects(:new).with do |*args|
+ args[0] == :server
+ end.returns @factory
+
+ @ca.sign(@name)
+ end
+
+ it "should use look up a CSR for the host in the :ca_file terminus" do
+ Puppet::SSL::CertificateRequest.expects(:find).with(@name, :in => :ca_file).returns @request
+
+ @ca.sign(@name)
+ end
+
+ it "should fail if no CSR can be found for the host" do
+ Puppet::SSL::CertificateRequest.expects(:find).with(@name, :in => :ca_file).returns nil
+
+ lambda { @ca.sign(@name) }.should raise_error(ArgumentError)
+ end
+
+ it "should use the CA certificate as the issuer" do
+ Puppet::SSL::CertificateFactory.expects(:new).with do |*args|
+ args[2] == @cacert.content
+ end.returns @factory
+ @ca.sign(@name)
+ end
+
+ it "should pass the next serial as the serial number" do
+ Puppet::SSL::CertificateFactory.expects(:new).with do |*args|
+ args[3] == @serial
+ end.returns @factory
+ @ca.sign(@name)
+ end
+
+ it "should save the resulting certificate in the :ca_file terminus" do
+ @cert.expects(:save).with(:in => :ca_file)
+ @ca.sign(@name)
+ end
+ end
+
+ it "should create a certificate instance with the content set to the newly signed x509 certificate" do
+ @serial = 10
+ @ca.stubs(:next_serial).returns @serial
+
+ Puppet::SSL::CertificateRequest.stubs(:find).with(@name, :in => :ca_file).returns @request
+ @cert.stubs :save
+ Puppet::SSL::Certificate.expects(:new).with(@name).returns @cert
+
+ @ca.sign(@name)
+ end
+
+ it "should return the certificate instance" do
+ @serial = 10
+ @ca.stubs(:next_serial).returns @serial
+
+ Puppet::SSL::CertificateRequest.stubs(:find).with(@name, :in => :ca_file).returns @request
+ @cert.stubs :save
+ @ca.sign(@name).should equal(@cert)
+ end
+ end
end