summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2008-03-07 15:31:15 -0700
committerLuke Kanies <luke@madstop.com>2008-04-15 21:34:02 -0500
commit4ca6fd3e476dbc582ebc69f5fdf9709a8703613b (patch)
treebf151bc9c852184b98a7a7c5f923c5063eb02421
parentef7d914aee89b6ea023f030350d04923a7b63fd2 (diff)
First stage of cert refactoring: Private
keys kind of work.
-rw-r--r--lib/puppet/indirector/key/file.rb51
-rw-r--r--lib/puppet/ssl/key.rb21
-rwxr-xr-xspec/unit/indirector/key/file.rb165
-rwxr-xr-xspec/unit/indirector/ssl_rsa/file.rb116
-rwxr-xr-xspec/unit/ssl/key.rb64
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