summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/puppetca2
-rw-r--r--lib/puppet/config.rb36
-rw-r--r--lib/puppet/sslcertificates/ca.rb34
-rwxr-xr-xtest/executables/puppetca.rb11
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")
}