summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/puppet/ssl/certificate_authority.rb26
-rw-r--r--lib/puppet/ssl/key.rb27
-rwxr-xr-xspec/unit/ssl/certificate_authority.rb95
-rwxr-xr-xspec/unit/ssl/key.rb30
4 files changed, 149 insertions, 29 deletions
diff --git a/lib/puppet/ssl/certificate_authority.rb b/lib/puppet/ssl/certificate_authority.rb
index 18f881ae3..971a9965e 100644
--- a/lib/puppet/ssl/certificate_authority.rb
+++ b/lib/puppet/ssl/certificate_authority.rb
@@ -10,7 +10,7 @@ class Puppet::SSL::CertificateAuthority < Puppet::SSL::Host
def read_key
return nil unless FileTest.exist?(Puppet[:cakey])
- key = Puppet::SSL::Key.new(:ca)
+ key = Puppet::SSL::Key.new(name)
key.password_file = Puppet[:capass]
key.read(Puppet[:cakey])
@@ -20,8 +20,9 @@ class Puppet::SSL::CertificateAuthority < Puppet::SSL::Host
# Generate and write the key out.
def generate_key
@key = Key.new(name)
+ @key.password_file = Puppet[:capass]
@key.generate
- Puppet.settings.write(:cacert) do |f|
+ Puppet.settings.write(:cakey) do |f|
f.print @key.to_s
end
true
@@ -56,7 +57,7 @@ class Puppet::SSL::CertificateAuthority < Puppet::SSL::Host
# Always name the ca after the host we're running on.
super(Puppet[:certname])
- setup_ca
+ setup_ca()
end
# Sign a given certificate request.
@@ -84,15 +85,13 @@ class Puppet::SSL::CertificateAuthority < Puppet::SSL::Host
cert.save(:in => :ca_file) unless self_signed
end
- private
-
# Do all of the initialization necessary to set up our
# ca.
def setup_ca
generate_key unless key
# Make sure we've got a password protecting our private key.
- generate_password unless read_password
+ generate_password unless password?
# 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,
@@ -134,17 +133,8 @@ class Puppet::SSL::CertificateAuthority < Puppet::SSL::Host
return serial
end
- # Get the CA password.
- def read_password
- unless defined?(@password) and @password
- path = Puppet[:capass]
- return nil unless FileTest.exist?(path)
-
- raise(Puppet::Error, "Could not read CA passfile %s" % path) unless FileTest.readable?(path)
-
- @password = File.read(path)
- end
-
- @password
+ # Does the password file exist?
+ def password?
+ FileTest.exist? Puppet[:capass]
end
end
diff --git a/lib/puppet/ssl/key.rb b/lib/puppet/ssl/key.rb
index b8943a776..35370ac69 100644
--- a/lib/puppet/ssl/key.rb
+++ b/lib/puppet/ssl/key.rb
@@ -8,24 +8,35 @@ class Puppet::SSL::Key < Puppet::SSL::Base
extend Puppet::Indirector
indirects :key, :terminus_class => :file
- attr_accessor :password_file
+ attr_reader :password_file
# Knows how to create keys with our system defaults.
def generate
Puppet.info "Creating a new SSL key for %s" % name
- @content = OpenSSL::PKey::RSA.new(Puppet[:keylength])
+ if pass = password
+ @content = OpenSSL::PKey::RSA.new(Puppet[:keylength], pass)
+ else
+ @content = OpenSSL::PKey::RSA.new(Puppet[:keylength])
+ end
+ end
+
+ def password
+ return nil unless password_file
+
+ ::File.read(password_file)
+ end
+
+ # Set our password file.
+ def password_file=(file)
+ raise ArgumentError, "Password file %s does not exist" % file unless FileTest.exist?(file)
+
+ @password_file = file
end
# Optionally support specifying a password file.
def read(path)
return super unless password_file
- begin
- password = ::File.read(password_file)
- rescue => detail
- raise Puppet::Error, "Could not read password for %s: %s" % [name, detail]
- end
-
@content = wrapped_class.new(::File.read(path), password)
end
end
diff --git a/spec/unit/ssl/certificate_authority.rb b/spec/unit/ssl/certificate_authority.rb
index 53fb48e5f..b1b33f8b9 100755
--- a/spec/unit/ssl/certificate_authority.rb
+++ b/spec/unit/ssl/certificate_authority.rb
@@ -15,13 +15,102 @@ describe Puppet::SSL::CertificateAuthority do
end
describe "a new certificate authority" do
- it "should create and store a password at :capass, a key encrypted with the password at :cakey, and a self-signed cert at :cacert"
+ before do
+ Puppet.settings.stubs(:value).with(:certname).returns "whatever"
+ end
+
+ it "should create and store a password at :capass" do
+ Puppet.settings.expects(:value).with(:capass).returns "/path/to/pass"
+
+ FileTest.expects(:exist?).with("/path/to/pass").returns false
+
+ fh = mock 'filehandle'
+ Puppet.settings.expects(:write).with(:capass).yields fh
+
+ fh.expects(:print).with { |s| s.length > 18 }
+
+ [:read_key, :generate_key, :read_certificate, :generate_certificate].each do |method|
+ Puppet::SSL::CertificateAuthority.any_instance.stubs(method)
+ end
+
+ Puppet::SSL::CertificateAuthority.new
+ end
+
+ 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"
+
+ FileTest.expects(:exist?).with("/path/to/key").returns false
+
+ key = mock 'key'
+
+ Puppet::SSL::Key.expects(:new).with("whatever").returns key
+ key.expects(:password_file=).with("/path/to/pass")
+ key.expects(:generate)
+
+ key.expects(:to_s).returns "my key"
+
+ fh = mock 'filehandle'
+ Puppet.settings.expects(:write).with(:cakey).yields fh
+ fh.expects(:print).with("my key")
+
+ [: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
+
+ Puppet::SSL::CertificateAuthority.new
+ end
+
+ it "should create, sign, and store a self-signed cert at :cacert" do
+ Puppet.settings.stubs(:value).with(:cacert).returns "/path/to/cert"
+
+ FileTest.expects(:exist?).with("/path/to/cert").returns false
+
+ request = mock 'request'
+ Puppet::SSL::CertificateRequest.expects(:new).with("whatever").returns request
+ request.expects(:generate)
+
+ cert = mock 'cert'
+ cert.expects(:to_s).returns "my cert"
+ Puppet::SSL::CertificateAuthority.any_instance.expects(:sign).with(request, :ca, true).returns cert
+
+ fh = mock 'filehandle'
+ Puppet.settings.expects(:write).with(:cacert).yields fh
+ fh.expects(:print).with("my cert")
+
+ [:password?, :generate_password, :read_key, :generate_key].each do |method|
+ Puppet::SSL::CertificateAuthority.any_instance.stubs(method)
+ end
+
+ Puppet::SSL::CertificateAuthority.new
+ end
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"
+ 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"
+
+ 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
+
+ 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"
+
+ cert = mock 'cert'
+ Puppet::SSL::Certificate.expects(:new).with("whatever").returns cert
+ cert.expects(:read).returns paths[:cacert]
+ cert.stubs(:content).returns "mycert"
- it "should read the cert stored at :cacert"
+ Puppet::SSL::CertificateAuthority.new
+ end
end
end
end
diff --git a/spec/unit/ssl/key.rb b/spec/unit/ssl/key.rb
index 71ef79c90..4978a591b 100755
--- a/spec/unit/ssl/key.rb
+++ b/spec/unit/ssl/key.rb
@@ -45,11 +45,13 @@ describe Puppet::SSL::Key do
end
it "should read the key with the password retrieved from the password file if one is provided" do
+ FileTest.stubs(:exist?).returns true
@key.password_file = "/path/to/password"
path = "/my/path"
File.expects(:read).with(path).returns("my key")
File.expects(:read).with("/path/to/password").returns("my password")
+
key = mock 'key'
OpenSSL::PKey::RSA.expects(:new).with("my key", "my password").returns(key)
@key.read(path).should equal(key)
@@ -87,6 +89,34 @@ describe Puppet::SSL::Key do
@instance.generate
end
+ it "should fail if a provided password file does not exist" do
+ FileTest.expects(:exist?).with("/path/to/pass").returns false
+
+ lambda { @instance.password_file = "/path/to/pass" }.should raise_error(ArgumentError)
+ end
+
+ it "should return the contents of the password file as its password" do
+ FileTest.expects(:exist?).with("/path/to/pass").returns true
+ File.expects(:read).with("/path/to/pass").returns "my password"
+
+ @instance.password_file = "/path/to/pass"
+
+ @instance.password.should == "my password"
+ end
+
+ it "should create the private key with any provided password" do
+ Puppet.settings.stubs(:value).with(:keylength).returns(50)
+
+ FileTest.expects(:exist?).with("/path/to/pass").returns true
+ File.expects(:read).with("/path/to/pass").returns "my password"
+
+ @instance.password_file = "/path/to/pass"
+
+ OpenSSL::PKey::RSA.expects(:new).with(50, "my password").returns(@key)
+
+ @instance.generate
+ end
+
it "should set the content to the generated key" do
OpenSSL::PKey::RSA.stubs(:new).returns(@key)
@instance.generate