summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2008-04-17 15:50:40 -0500
committerLuke Kanies <luke@madstop.com>2008-04-17 15:50:40 -0500
commit3d24b12d73aad0bac74e4b2f1e214b79f3ca9231 (patch)
tree2a7f1c027bcd168f86ea3872fd1074a03e70db97
parentdaa8cd57b9f61c40c1b4e6954533f197ee5a2f1d (diff)
downloadpuppet-3d24b12d73aad0bac74e4b2f1e214b79f3ca9231.tar.gz
puppet-3d24b12d73aad0bac74e4b2f1e214b79f3ca9231.tar.xz
puppet-3d24b12d73aad0bac74e4b2f1e214b79f3ca9231.zip
The certificate authority now uses a Host instance named 'ca'.
It previously was a subclass of Host, but this should make it easier to separate between the thing doing the signing and the thing managing the necessary files.
-rw-r--r--lib/puppet/ssl/certificate_authority.rb91
-rw-r--r--spec/integration/network/server/mongrel.rb2
-rwxr-xr-xspec/unit/ssl/certificate_authority.rb147
3 files changed, 84 insertions, 156 deletions
diff --git a/lib/puppet/ssl/certificate_authority.rb b/lib/puppet/ssl/certificate_authority.rb
index 3192c2844..f4bc6fe31 100644
--- a/lib/puppet/ssl/certificate_authority.rb
+++ b/lib/puppet/ssl/certificate_authority.rb
@@ -1,65 +1,40 @@
require 'puppet/ssl/host'
-
-# The class that knows how to sign certificates. It's just a
-# special case of the SSL::Host -- it's got a sign method,
-# and it reads its info from a different location.
-class Puppet::SSL::CertificateAuthority < Puppet::SSL::Host
+require 'puppet/ssl/certificate_request'
+
+# The class that knows how to sign certificates. It creates
+# a 'special' SSL::Host whose name is 'ca', thus indicating
+# that, well, it's the CA. There's some magic in the
+# indirector/ssl_file terminus base class that does that
+# for us.
+# This class mostly just signs certs for us, but
+# it can also be seen as a general interface into all of the
+# SSL stuff.
+class Puppet::SSL::CertificateAuthority
require 'puppet/ssl/certificate_factory'
- # Provide the path to our password, and read our special ca key.
- def read_key
- return nil unless FileTest.exist?(Puppet[:cakey])
-
- key = Puppet::SSL::Key.new(name)
- key.password_file = Puppet[:capass]
- key.read(Puppet[:cakey])
-
- return key
- end
-
- # Generate and write the key out.
- def generate_key
- @key = Key.new(name)
- @key.password_file = Puppet[:capass]
- @key.generate
- Puppet.settings.write(:cakey) do |f|
- f.print @key.to_s
- end
- true
- end
-
- # Read the special path to our key.
- def read_certificate
- return nil unless FileTest.exist?(Puppet[:cacert])
- cert = Puppet::SSL::Certificate.new(name)
- cert.read(Puppet[:cacert])
+ attr_reader :name, :host
- return cert
- end
+ # Generate our CA certificate.
+ def generate_ca_certificate
+ generate_password unless password?
- # The CA creates a self-signed certificate, rather than relying
- # on someone else to do the work.
- def generate_certificate
- request = CertificateRequest.new(name)
- request.generate(key)
+ # Create a new cert request. We do this
+ # specially, because we don't want to actually
+ # save the request anywhere.
+ request = Puppet::SSL::CertificateRequest.new(host.name)
+ request.generate(host.key)
# Create a self-signed certificate.
@certificate = sign(name, :ca, request)
-
- Puppet.settings.write(:cacert) do |f|
- f.print @certificate.to_s
- end
-
- return true
end
def initialize
Puppet.settings.use :main, :ssl, :ca
- # Always name the ca after the host we're running on.
- super(Puppet[:certname])
+ @name = Puppet[:certname]
- setup_ca()
+ @host = Puppet::SSL::Host.new(Puppet::SSL::Host.ca_name)
+ @host.password_file = Puppet[:capass]
end
# Sign a given certificate request.
@@ -83,27 +58,13 @@ class Puppet::SSL::CertificateAuthority < Puppet::SSL::Host
Puppet.notice "Signed certificate request for %s" % host
- # 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_signing_csr
+ # Save the now-signed cert. This should get routed correctly depending
+ # on the certificate type.
+ cert.save
return cert
end
- # Do all of the initialization necessary to set up our
- # ca.
- def setup_ca
- # Make sure we've got a password protecting our private key.
- generate_password unless password?
-
- generate_key unless key
-
- # And then make sure we've got the whole kaboodle. This will
- # create a self-signed CA certificate if we don't already have one,
- # and it will just read it in if we do.
- generate_certificate unless certificate
- end
-
# Generate a new password for the CA.
def generate_password
pass = ""
diff --git a/spec/integration/network/server/mongrel.rb b/spec/integration/network/server/mongrel.rb
index 65caf78c9..a4089585e 100644
--- a/spec/integration/network/server/mongrel.rb
+++ b/spec/integration/network/server/mongrel.rb
@@ -43,4 +43,4 @@ describe Puppet::Network::Server do
@server.unlisten if @server.listening?
end
end
-end \ No newline at end of file
+end
diff --git a/spec/unit/ssl/certificate_authority.rb b/spec/unit/ssl/certificate_authority.rb
index e9624f218..37832ecf2 100755
--- a/spec/unit/ssl/certificate_authority.rb
+++ b/spec/unit/ssl/certificate_authority.rb
@@ -6,126 +6,91 @@ require 'puppet/ssl/certificate_authority'
describe Puppet::SSL::CertificateAuthority do
describe "when initializing" do
- it "should always set its name to the value of :certname" do
+ before do
Puppet.settings.stubs(:use)
- Puppet.settings.expects(:value).with(:certname).returns "whatever"
-
- Puppet::SSL::CertificateAuthority.any_instance.stubs(:setup_ca)
-
- Puppet::SSL::CertificateAuthority.new.name.should == "whatever"
- end
+ Puppet.settings.stubs(:value).returns "whatever"
- it "should use the :main, :ca, and :ssl settings sections" do
- Puppet.settings.expects(:use).with(:main, :ssl, :ca)
- Puppet::SSL::CertificateAuthority.any_instance.stubs(:setup_ca)
- Puppet::SSL::CertificateAuthority.new
+ Puppet::SSL::CertificateAuthority.any_instance.stubs(:generate_ca_certificate)
end
- describe "a new certificate authority" do
- before do
- Puppet.settings.stubs(:use)
- Puppet.settings.stubs(:value).with(:certname).returns "whatever"
- end
+ it "should always set its name to the value of :certname" do
+ Puppet.settings.expects(:value).with(:certname).returns "whatever"
- it "should create and store a password at :capass" do
- Puppet.settings.expects(:value).with(:capass).returns "/path/to/pass"
+ Puppet::SSL::CertificateAuthority.new.name.should == "whatever"
+ end
- FileTest.expects(:exist?).with("/path/to/pass").returns false
+ it "should create an SSL::Host instance whose name is the 'ca_name'" do
+ Puppet::SSL::Host.expects(:ca_name).returns "caname"
- fh = mock 'filehandle'
- Puppet.settings.expects(:write).with(:capass).yields fh
+ host = stub 'host', :password_file= => nil
+ Puppet::SSL::Host.expects(:new).with("caname").returns host
- fh.expects(:print).with { |s| s.length > 18 }
+ Puppet::SSL::CertificateAuthority.new
+ end
- [:read_key, :generate_key, :read_certificate, :generate_certificate].each do |method|
- Puppet::SSL::CertificateAuthority.any_instance.stubs(method)
- end
+ it "should set the Host instance's password file to the :capass setting" do
+ Puppet.settings.stubs(:value).with(:capass).returns "/ca/pass"
- Puppet::SSL::CertificateAuthority.new
- end
+ host = mock 'host'
+ Puppet::SSL::Host.expects(:new).returns host
- it "should create and store a key encrypted with the password at :cakey" do
- Puppet.settings.stubs(:value).with(:capass).returns "/path/to/pass"
- Puppet.settings.stubs(:value).with(:cakey).returns "/path/to/key"
+ host.expects(:password_file=).with "/ca/pass"
- FileTest.expects(:exist?).with("/path/to/key").returns false
+ Puppet::SSL::CertificateAuthority.new
+ end
- key = mock 'key'
+ it "should use the :main, :ca, and :ssl settings sections" do
+ Puppet.settings.expects(:use).with(:main, :ssl, :ca)
+ Puppet::SSL::CertificateAuthority.new
+ end
+ end
- Puppet::SSL::Key.expects(:new).with("whatever").returns key
- key.expects(:password_file=).with("/path/to/pass")
- key.expects(:generate)
+ it "should generate a self-signed certificate if its Host instance has no certificate"
- key.expects(:to_s).returns "my key"
+ describe "when generating a self-signed CA certificate" do
+ before do
+ Puppet.settings.stubs(:use)
+ Puppet.settings.stubs(:value).returns "whatever"
- fh = mock 'filehandle'
- Puppet.settings.expects(:write).with(:cakey).yields fh
- fh.expects(:print).with("my key")
+ @ca = Puppet::SSL::CertificateAuthority.new
- [:generate_password, :read_certificate, :generate_certificate].each do |method|
- Puppet::SSL::CertificateAuthority.any_instance.stubs(method)
- end
- Puppet::SSL::CertificateAuthority.any_instance.stubs(:password?).returns true
+ @host = stub 'host', :key => mock("key"), :name => "hostname"
- Puppet::SSL::CertificateAuthority.new
- end
+ Puppet::SSL::CertificateRequest.any_instance.stubs(:generate)
- it "should create, sign, and store a self-signed cert at :cacert" do
- Puppet.settings.stubs(:value).with(:cacert).returns "/path/to/cert"
+ @ca.stubs(:host).returns @host
+ end
- FileTest.expects(:exist?).with("/path/to/cert").returns false
+ it "should create and store a password at :capass" do
+ Puppet.settings.expects(:value).with(:capass).returns "/path/to/pass"
- request = mock 'request'
- Puppet::SSL::CertificateRequest.expects(:new).with("whatever").returns request
- request.expects(:generate)
+ FileTest.expects(:exist?).with("/path/to/pass").returns false
- cert = mock 'cert'
- cert.expects(:to_s).returns "my cert"
- Puppet::SSL::CertificateAuthority.any_instance.expects(:sign).with("whatever", :ca, request).returns cert
+ fh = mock 'filehandle'
+ Puppet.settings.expects(:write).with(:capass).yields fh
- fh = mock 'filehandle'
- Puppet.settings.expects(:write).with(:cacert).yields fh
- fh.expects(:print).with("my cert")
+ fh.expects(:print).with { |s| s.length > 18 }
- [:password?, :generate_password, :read_key, :generate_key].each do |method|
- Puppet::SSL::CertificateAuthority.any_instance.stubs(method)
- end
+ @ca.stubs(:sign)
- Puppet::SSL::CertificateAuthority.new
- end
+ @ca.generate_ca_certificate
end
- describe "an existing certificate authority" do
- it "should read and decrypt the key at :cakey using the password at :capass and it should read the cert at :cacert" do
- Puppet.settings.stubs(:value).with(:certname).returns "whatever"
- Puppet.settings.stubs(:use)
+ it "should create and sign a self-signed cert" do
+ request = mock 'request'
+ Puppet::SSL::CertificateRequest.expects(:new).with(@ca.host.name).returns request
+ request.expects(:generate).with(@ca.host.key)
- paths = {}
- [:capass, :cakey, :cacert].each do |value|
- paths[value] = "/path/to/#{value.to_s}"
- Puppet.settings.stubs(:value).with(value).returns paths[value]
- FileTest.stubs(:exist?).with(paths[value]).returns true
- end
+ @ca.expects(:sign).with(@ca.name, :ca, request)
- key = mock 'key'
- Puppet::SSL::Key.expects(:new).with("whatever").returns key
- key.expects(:password_file=).returns paths[:capass]
- key.expects(:read).returns paths[:cakey]
- key.stubs(:content).returns "mykey"
+ @ca.stubs :generate_password
- cert = mock 'cert'
- Puppet::SSL::Certificate.expects(:new).with("whatever").returns cert
- cert.expects(:read).returns paths[:cacert]
- cert.stubs(:content).returns "mycert"
-
- Puppet::SSL::CertificateAuthority.new
- end
+ @ca.generate_ca_certificate
end
end
describe "when signing" do
before do
- Puppet.settings.stubs(:value).with(:certname).returns "whatever"
Puppet.settings.stubs(:use)
Puppet::SSL::CertificateAuthority.any_instance.stubs(:password?).returns true
@@ -146,6 +111,7 @@ describe Puppet::SSL::CertificateAuthority do
Puppet::SSL::Certificate.stubs(:new).returns @cert
@cert.stubs(:content=)
+ @cert.stubs(:save)
@factory = stub 'factory', :result => "my real cert"
Puppet::SSL::CertificateFactory.stubs(:new).returns @factory
@@ -226,8 +192,10 @@ describe Puppet::SSL::CertificateAuthority do
@ca.sign(@name, :ca, @request)
end
- it "should not save the resulting certificate" do
- @cert.expects(:save).never
+ it "should save the resulting certificate" do
+ @cert.expects(:save)
+
+ @ca.sign(@name, :ca, @request)
end
end
@@ -293,8 +261,8 @@ describe Puppet::SSL::CertificateAuthority do
@ca.sign(@name)
end
- it "should save the resulting certificate in the :ca_file terminus" do
- @cert.expects(:save).with(:in => :ca_file)
+ it "should save the resulting certificate" do
+ @cert.expects(:save)
@ca.sign(@name)
end
end
@@ -322,7 +290,6 @@ describe Puppet::SSL::CertificateAuthority do
describe "when managing certificate clients" do
before do
- Puppet.settings.stubs(:value).with(:certname).returns "whatever"
Puppet.settings.stubs(:use)
Puppet::SSL::CertificateAuthority.any_instance.stubs(:password?).returns true