diff options
-rwxr-xr-x | bin/puppetca | 2 | ||||
-rw-r--r-- | lib/puppet/config.rb | 36 | ||||
-rw-r--r-- | lib/puppet/sslcertificates/ca.rb | 34 | ||||
-rwxr-xr-x | test/executables/puppetca.rb | 11 |
4 files changed, 64 insertions, 19 deletions
diff --git a/bin/puppetca b/bin/puppetca index c3aedf5fe..8bc7ac1ae 100755 --- a/bin/puppetca +++ b/bin/puppetca @@ -138,8 +138,6 @@ end Puppet.genconfig Puppet.genmanifest -Puppet::Util.chuser - begin ca = Puppet::SSLCertificates::CA.new() rescue => detail diff --git a/lib/puppet/config.rb b/lib/puppet/config.rb index 5519138fd..e7ad95dd4 100644 --- a/lib/puppet/config.rb +++ b/lib/puppet/config.rb @@ -566,6 +566,42 @@ Generated on #{Time.now}. end end + # Open a non-default file under a default dir with the appropriate user, + # group, and mode + def writesub(default, file, *args) + obj = nil + unless obj = @config[default] + raise ArgumentError, "Unknown default %s" % default + end + + unless obj.is_a? CFile + raise ArgumentError, "Default %s is not a file" % default + end + + chown = nil + if Process.uid == 0 + chown = [obj.owner, obj.group] + else + chown = [nil, nil] + end + + Puppet::Util.asuser(*chown) do + mode = obj.mode || 0640 + if args.empty? + args << "w" + end + + args << mode + + # Update the umask to make non-executable files + Puppet::Util.withumask(File.umask ^ 0111) do + File.open(file, *args) do |file| + yield file + end + end + end + end + # The base element type. class CElement attr_accessor :name, :section, :default, :parent, :setbycli diff --git a/lib/puppet/sslcertificates/ca.rb b/lib/puppet/sslcertificates/ca.rb index fa6e9e368..1d9823ed1 100644 --- a/lib/puppet/sslcertificates/ca.rb +++ b/lib/puppet/sslcertificates/ca.rb @@ -66,10 +66,6 @@ class Puppet::SSLCertificates::CA :keylength => [1024, "The bit length of keys."] ) - #@@params.each { |param| - # Puppet.setdefault(param,@@defaults[param]) - #} - def certfile @config[:cacert] end @@ -84,6 +80,7 @@ class Puppet::SSLCertificates::CA File.join(Puppet[:signeddir], [hostname, "pem"].join(".")) end + # Turn our hostname into a Name object def thing2name(thing) thing.subject.to_a.find { |ary| ary[0] == "CN" @@ -116,15 +113,11 @@ class Puppet::SSLCertificates::CA end end + # Generate a new password for the CA. def genpass pass = "" 20.times { pass += (rand(74) + 48).chr } - # FIXME It's a hack that this still needs to be here :/ - #unless FileTest.exists?(File.dirname(@config[:capass])) - # Puppet::Util.recmkdir(File.dirname(@config[:capass]), 0770) - #end - begin Puppet.config.write(:capass) { |f| f.print pass } rescue Errno::EACCES => detail @@ -133,6 +126,7 @@ class Puppet::SSLCertificates::CA return pass end + # Get the CA password. def getpass if @config[:capass] and File.readable?(@config[:capass]) return File.read(@config[:capass]) @@ -141,6 +135,7 @@ class Puppet::SSLCertificates::CA end end + # Get the CA cert. def getcert if FileTest.exists?(@config[:cacert]) @cert = OpenSSL::X509::Certificate.new( @@ -151,6 +146,7 @@ class Puppet::SSLCertificates::CA end end + # Retrieve a client's CSR. def getclientcsr(host) csrfile = host2csrfile(host) unless File.exists?(csrfile) @@ -160,6 +156,7 @@ class Puppet::SSLCertificates::CA return OpenSSL::X509::Request.new(File.read(csrfile)) end + # Retrieve a client's certificate. def getclientcert(host) certfile = host2certfile(host) unless File.exists?(certfile) @@ -169,6 +166,7 @@ class Puppet::SSLCertificates::CA return [OpenSSL::X509::Certificate.new(File.read(certfile)), @cert] end + # List certificates waiting to be signed. def list return Dir.entries(Puppet[:csrdir]).reject { |file| file =~ /^\.+$/ @@ -177,6 +175,7 @@ class Puppet::SSLCertificates::CA } end + # Create the root certificate. def mkrootcert cert = Certificate.new( :name => "CAcert", @@ -208,6 +207,7 @@ class Puppet::SSLCertificates::CA File.unlink(csrfile) end + # Take the Puppet config and store it locally. def setconfig(hash) @config = {} Puppet.config.params("ca").each { |param| @@ -234,12 +234,10 @@ class Puppet::SSLCertificates::CA unless @config[dir] raise Puppet::DevError, "%s is undefined" % dir end - unless FileTest.exists?(@config[dir]) - Puppet.recmkdir(@config[dir]) - end } end + # Sign a given certificate request. def sign(csr) unless csr.is_a?(OpenSSL::X509::Request) raise Puppet::Error, @@ -295,6 +293,9 @@ class Puppet::SSLCertificates::CA return [newcert, cacert] end + # Store the client's CSR for later signing. This is called from + # server/ca.rb, and the CSRs are deleted once the certificate is actually + # signed. def storeclientcsr(csr) host = thing2name(csr) @@ -303,11 +304,12 @@ class Puppet::SSLCertificates::CA raise Puppet::Error, "Certificate request for %s already exists" % host end - File.open(csrfile, "w", 0660) { |f| + Puppet.config.writesub(:csrdir, csrfile) do |f| f.print csr.to_pem - } + end end + # Store the certificate that we generate. def storeclientcert(cert) host = thing2name(cert) @@ -317,9 +319,9 @@ class Puppet::SSLCertificates::CA [certfile, host] end - File.open(certfile, "w", 0660) { |f| + Puppet.config.writesub(:signeddir, certfile) do |f| f.print cert.to_pem - } + end end end diff --git a/test/executables/puppetca.rb b/test/executables/puppetca.rb index 67df0a6b6..a38296a54 100755 --- a/test/executables/puppetca.rb +++ b/test/executables/puppetca.rb @@ -25,7 +25,7 @@ class TestPuppetCA < Test::Unit::TestCase end def runca(args) - return %x{puppetca --confdir=#{Puppet[:confdir]} --user #{Process.uid} --group #{Process.gid} #{args} 2>&1} + return %x{puppetca --confdir=#{Puppet[:confdir]} #{args} 2>&1} end @@ -60,8 +60,17 @@ class TestPuppetCA < Test::Unit::TestCase assert_nothing_raised { output = runca("--sign -a").chomp.split("\n") } + + assert_equal($?,0) assert_equal(["Signed host.test.com"], output) + + signedfile = File.join(Puppet[:signeddir], "host.test.com.pem") + assert(FileTest.exists?(signedfile), "cert does not exist") + assert(! FileTest.executable?(signedfile), "cert is executable") + if Process.uid == 0 + assert(! FileTest.owned?(signedfile), "cert is owned by root") + end assert_nothing_raised { output = runca("--list").chomp.split("\n") } |