diff options
| author | Luke Kanies <luke@madstop.com> | 2008-03-07 15:31:15 -0700 |
|---|---|---|
| committer | Luke Kanies <luke@madstop.com> | 2008-04-15 21:34:02 -0500 |
| commit | 4ca6fd3e476dbc582ebc69f5fdf9709a8703613b (patch) | |
| tree | bf151bc9c852184b98a7a7c5f923c5063eb02421 | |
| parent | ef7d914aee89b6ea023f030350d04923a7b63fd2 (diff) | |
First stage of cert refactoring: Private
keys kind of work.
| -rw-r--r-- | lib/puppet/indirector/key/file.rb | 51 | ||||
| -rw-r--r-- | lib/puppet/ssl/key.rb | 21 | ||||
| -rwxr-xr-x | spec/unit/indirector/key/file.rb | 165 | ||||
| -rwxr-xr-x | spec/unit/indirector/ssl_rsa/file.rb | 116 | ||||
| -rwxr-xr-x | spec/unit/ssl/key.rb | 64 |
5 files changed, 301 insertions, 116 deletions
diff --git a/lib/puppet/indirector/key/file.rb b/lib/puppet/indirector/key/file.rb new file mode 100644 index 000000000..47152ee08 --- /dev/null +++ b/lib/puppet/indirector/key/file.rb @@ -0,0 +1,51 @@ +require 'puppet/indirector/file' +require 'puppet/ssl/key' + +class Puppet::SSL::Key::File < Puppet::Indirector::File + desc "Manage SSL private and public keys on disk." + + # Is this key a CA key? + def ca_key?(key) + key.name == :ca + end + + def path(name) + if name == :ca + Puppet.settings[:cakey] + else + File.join(Puppet.settings[:privatekeydir], name.to_s + ".pem") + end + end + + def public_key_path(name) + if name == :ca + Puppet.settings[:capub] + else + File.join(Puppet.settings[:publickeydir], name.to_s + ".pem") + end + end + + def save(key) + return save_ca_key(key) if ca_key?(key) + + # Save the private key + File.open(path(key.name), "w") { |f| f.print key.to_pem } + + # Now save the public key + File.open(public_key_path(name), "w") { |f| f.print key.to_pem } + end + + def find(name) + return find_ca_key(key) if ca_key?(key) + + return nil unless FileTest.exist?(path(name)) + OpenSSL::PKey::RSA.new(File.read(path(name))) + end + + def destroy(name) + return find_ca_key(key) if ca_key?(key) + + return nil unless FileTest.exist?(path(name)) + File.unlink(path(name)) and true + end +end diff --git a/lib/puppet/ssl/key.rb b/lib/puppet/ssl/key.rb new file mode 100644 index 000000000..69a09f1a8 --- /dev/null +++ b/lib/puppet/ssl/key.rb @@ -0,0 +1,21 @@ +require 'puppet/ssl' +require 'puppet/indirector' + +# Manage private and public keys as a pair. +class Puppet::SSL::Key # :nodoc: + extend Puppet::Indirector + + indirects :key #, :terminus_class => :file + + attr_accessor :name, :content + + # 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]) + end + + def initialize(name) + @name = name + end +end diff --git a/spec/unit/indirector/key/file.rb b/spec/unit/indirector/key/file.rb new file mode 100755 index 000000000..b9e9e2b11 --- /dev/null +++ b/spec/unit/indirector/key/file.rb @@ -0,0 +1,165 @@ +#!/usr/bin/env ruby +# +# Created by Luke Kanies on 2008-3-7. +# Copyright (c) 2007. All rights reserved. + +require File.dirname(__FILE__) + '/../../../spec_helper' + +require 'puppet/indirector/key/file' + +describe Puppet::SSL::Key::File do + it "should be a subclass of the File terminus class" do + Puppet::SSL::Key::File.superclass.should equal(Puppet::Indirector::File) + end + + it "should have documentation" do + Puppet::SSL::Key::File.doc.should be_instance_of(String) + end + + describe "when managing keys on disk" do + before do + @file = Puppet::SSL::Key::File.new + end + + describe "and choosing the location" do + describe "for certificate authority keys" do + before do + @private_key = "/path/to/private/ca/key" + @public_key = "/path/to/public/ca/key" + Puppet.settings.stubs(:value).with(:cakey).returns @private_key + Puppet.settings.stubs(:value).with(:capub).returns @public_key + end + + it "should use the :cakey as the private key location and :capub for the public key location" do + File.expects(:open).with(@private_key, "w") + File.expects(:open).with(@private_key, "w") + + key = stub 'key', :name => :ca + + @file.save(key) + end + end + + describe "for normal keys" do + before do + @name = "myhost" + end + + it "should save private key to the :privatekeydir with the file named after the key name plus '.pem'" + + it "should save the public key to the :publickeydir with the file named after the key name plus '.pem'" + end + end + + it "should be able to find keys saved to disk" + + it "should convert found keys to instances of OpenSSL::PKey::RSA" + + it "should be able to save keys to disk" + + it "should save keys in pem format" + + it "should save both public and private keys" + + it "should be able to remove keys stored on disk" + + it "should remove both public and private keys when the key is destroyed" + + it "should fail when attempting to remove missing keys" + end + + describe "when choosing a path for a ca key" do + + it "should use the cadir" do + pending "eh" + Puppet.settings.stubs(:value).with(:cadir).returns("/dir") + @file.path(@name).should =~ /^\/dir/ + end + + it "should use 'ca_key.pem' as the file name" do + pending "eh" + @file.path(@name).should =~ /ca_key\.pem$/ + end + end + + describe "when choosing a path for a non-ca key" do + before do + @name = :publickey + end + + it "should use the privatekeydir" do + pending "eh" + Puppet.settings.stubs(:value).with(:publickeydir).returns("/dir") + @file.path(@name).should =~ /^\/dir/ + end + + it "should use the key name with the pem file extension" do + pending "eh" + @file.path(@name).should =~ /#{@name}\.pem$/ + end + end + + describe "when saving" do + before do + Puppet.settings.stubs(:value).with(:publickeydir).returns("/dir") + @key = stub "key", :name => "foo" + end + + it "should store the private key to disk in pem format in the privatekey directory" do + pending "eh" + @key.expects(:to_pem).returns(:data) + @path = "/dir/foo.pem" + filehandle = mock "filehandle" + File.expects(:open).with(@path, "w").yields(filehandle) + filehandle.expects(:print).with(:data) + @file.save(@key) + end + + it "should store the public key to disk in pem format in the publickey directory" + end + + describe "when finding a key by name" do + before do + Puppet.settings.stubs(:value).with(:publickeydir).returns("/dir") + @name = "foo" + end + + it "should return the key as a key object on success" do + pending "eh" + @path = "/dir/foo.pem" + FileTest.stubs(:exists?).with(@path).returns(true) + File.stubs(:read).with(@path).returns(:data) + OpenSSL::PKey::RSA.expects(:new).with(:data).returns(:mykey) + @file.find(@name).should == :mykey + end + + it "should return 'nil' on failure" do + pending "eh" + @path = "/dir/foo.pem" + FileTest.stubs(:exists?).with(@path).returns(false) + @file.find(@name).should == nil + end + end + + describe "when removing a key" do + before do + Puppet.settings.stubs(:value).with(:publickeydir).returns("/dir") + @name = "foo" + end + + it "should remove the key from disk and return true" do + pending "eh" + @path = "/dir/foo.pem" + FileTest.stubs(:exists?).with(@path).returns(true) + File.stubs(:unlink).with(@path).returns(true) + @file.destroy(@name).should == true + end + + it "should return an exception on failure" do + pending "eh" + @path = "/dir/foo.pem" + FileTest.stubs(:exists?).with(@path).returns(false) + @file.destroy(@name).should == nil + end + end +end diff --git a/spec/unit/indirector/ssl_rsa/file.rb b/spec/unit/indirector/ssl_rsa/file.rb deleted file mode 100755 index 76e5e3a94..000000000 --- a/spec/unit/indirector/ssl_rsa/file.rb +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env ruby -# -# Created by Luke Kanies on 2007-9-22. -# Copyright (c) 2007. All rights reserved. - -require File.dirname(__FILE__) + '/../../../spec_helper' - -require 'puppet/sslcertificates/monkey_patch' -require 'puppet/indirector/ssl_rsa/file' - - -describe Puppet::Indirector::SslRsa::File do - - it "should be a subclass of the File terminus class" do - Puppet::Indirector::SslRsa::File.superclass.should equal(Puppet::Indirector::File) - end - - it "should have documentation" do - Puppet::Indirector::SslRsa::File.doc.should be_instance_of(String) - end -end - -describe Puppet::Indirector::SslRsa::File, " when choosing a path for a ca key" do - before do - @file = Puppet::Indirector::SslRsa::File.new - @name = :ca - end - - it "should use the cadir" do - Puppet.settings.stubs(:value).with(:cadir).returns("/dir") - @file.path(@name).should =~ /^\/dir/ - end - - it "should use 'ca_key.pem' as the file name" do - @file.path(@name).should =~ /ca_key\.pem$/ - end -end - -describe Puppet::Indirector::SslRsa::File, " when choosing a path for a non-ca key" do - before do - @file = Puppet::Indirector::SslRsa::File.new - @name = :publickey - end - - it "should use the publickeydir" do - Puppet.settings.stubs(:value).with(:publickeydir).returns("/dir") - @file.path(@name).should =~ /^\/dir/ - end - - it "should use the key name with the pem file extension" do - @file.path(@name).should =~ /#{@name}\.pem$/ - end -end - -describe Puppet::Indirector::SslRsa::File, " when saving" do - before do - @file = Puppet::Indirector::SslRsa::File.new - - Puppet.settings.stubs(:value).with(:publickeydir).returns("/dir") - @key = stub "key", :name => "foo" - end - - it "should store the rsa key to disk in pem format" do - @key.expects(:to_pem).returns(:data) - @path = "/dir/foo.pem" - filehandle = mock "filehandle" - File.expects(:open).with(@path, "w").yields(filehandle) - filehandle.expects(:print).with(:data) - @file.save(@key) - end -end - -describe Puppet::Indirector::SslRsa::File, " when finding a key by name" do - before do - @file = Puppet::Indirector::SslRsa::File.new - - Puppet.settings.stubs(:value).with(:publickeydir).returns("/dir") - @name = "foo" - end - - it "should return the key as a key object on success" do - @path = "/dir/foo.pem" - FileTest.stubs(:exists?).with(@path).returns(true) - File.stubs(:read).with(@path).returns(:data) - OpenSSL::PKey::RSA.expects(:new).with(:data).returns(:mykey) - @file.find(@name).should == :mykey - end - - it "should return 'nil' on failure" do - @path = "/dir/foo.pem" - FileTest.stubs(:exists?).with(@path).returns(false) - @file.find(@name).should == nil - end -end - -describe Puppet::Indirector::SslRsa::File, " when removing a key" do - before do - @file = Puppet::Indirector::SslRsa::File.new - - Puppet.settings.stubs(:value).with(:publickeydir).returns("/dir") - @name = "foo" - end - - it "should remove the key from disk and return true" do - @path = "/dir/foo.pem" - FileTest.stubs(:exists?).with(@path).returns(true) - File.stubs(:unlink).with(@path).returns(true) - @file.destroy(@name).should == true - end - - it "should return an exception on failure" do - @path = "/dir/foo.pem" - FileTest.stubs(:exists?).with(@path).returns(false) - @file.destroy(@name).should == nil - end -end diff --git a/spec/unit/ssl/key.rb b/spec/unit/ssl/key.rb new file mode 100755 index 000000000..f8a74dcf1 --- /dev/null +++ b/spec/unit/ssl/key.rb @@ -0,0 +1,64 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../spec_helper' + +require 'puppet/ssl/key' + +describe Puppet::SSL::Key do + before do + @class = Puppet::SSL::Key + end + it "should be extended with the Indirector module" do + @class.metaclass.should be_include(Puppet::Indirector) + end + + it "should indirect key" do + @class.indirection.name.should == :key + end + + describe "when managing instances" do + before do + @key = @class.new("myname") + end + + it "should have a name attribute" do + @key.name.should == "myname" + end + + it "should have a content attribute" do + @key.should respond_to(:content) + end + end + + describe "when generating the private key" do + before do + @instance = @class.new("test") + + @key = mock 'key' + end + + it "should create an instance of OpenSSL::PKey::RSA" do + OpenSSL::PKey::RSA.expects(:new).returns(@key) + + @instance.generate + end + + it "should create the private key with the keylength specified in the settings" do + Puppet.settings.expects(:value).with(:keylength).returns(50) + OpenSSL::PKey::RSA.expects(:new).with(50).returns(@key) + + @instance.generate + end + + it "should set the content to the generated key" do + OpenSSL::PKey::RSA.stubs(:new).returns(@key) + @instance.generate + @instance.content.should equal(@key) + end + + it "should return the generated key" do + OpenSSL::PKey::RSA.stubs(:new).returns(@key) + @instance.generate.should equal(@key) + end + end +end |
