summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/puppet.rb1
-rw-r--r--lib/puppet/client.rb137
-rwxr-xr-xlib/puppet/daemon.rb91
-rwxr-xr-xlib/puppet/sslcertificates.rb85
-rw-r--r--test/client/tc_client.rb8
5 files changed, 197 insertions, 125 deletions
diff --git a/lib/puppet.rb b/lib/puppet.rb
index 1a46cba01..a4507e09f 100644
--- a/lib/puppet.rb
+++ b/lib/puppet.rb
@@ -76,6 +76,7 @@ module Puppet
# then the files},
:manifest => [:puppetconf, "manifest.pp"],
+ :localconfig => [:puppetconf, "localconfig.ma"],
:logfile => [:logdir, "puppet.log"],
:httplogfile => [:logdir, "http.log"],
:masterlog => [:logdir, "puppetmaster.log"],
diff --git a/lib/puppet/client.rb b/lib/puppet/client.rb
index efeee68c2..81e64d66f 100644
--- a/lib/puppet/client.rb
+++ b/lib/puppet/client.rb
@@ -1,7 +1,5 @@
#!/usr/local/bin/ruby -w
-# $Id$
-
# the available clients
require 'puppet'
@@ -32,7 +30,7 @@ module Puppet
Puppet.err "Could not load client network libs: %s" % $noclientnetworking
else
class NetworkClient < XMLRPC::Client
- include Puppet::Daemon
+ #include Puppet::Daemon
@@methods = [ :getconfig, :getcert ]
@@ -40,8 +38,13 @@ module Puppet
self.send(:define_method,method) { |*args|
begin
call("puppetmaster.%s" % method.to_s,*args)
+ rescue XMLRPC::FaultException => detail
+ Puppet.err "XML Could not call %s: %s" %
+ [method, detail.faultString]
+ raise NetworkClientError.new(detail.to_s)
rescue => detail
- raise NetworkClientError.new(detail)
+ Puppet.err "Could not call %s: %s" % [method, detail.inspect]
+ raise NetworkClientError.new(detail.to_s)
end
}
}
@@ -50,15 +53,26 @@ module Puppet
hash[:Path] ||= "/RPC2"
hash[:Server] ||= "localhost"
hash[:Port] ||= Puppet[:masterport]
- super(hash[:Server],hash[:Path],hash[:Port])
+ super(
+ hash[:Server],
+ hash[:Path],
+ hash[:Port],
+ nil, # proxy_host
+ nil, # proxy_port
+ nil, # user
+ nil, # password
+ true) # use_ssl
+
+ # from here, i need to add the key, cert, and ca cert
+ # and reorgize how i start the client
end
end
end
class Client
include Puppet
+ include Puppet::Daemon
attr_accessor :local, :secureinit
- attr_reader :fqdn
def Client.facts
facts = {}
@@ -103,76 +117,12 @@ module Puppet
if hash.include?(:FQDN)
@fqdn = hash[:FQDN]
else
- hostname = Facter["hostname"].value
- domain = Facter["domain"].value
- @fqdn = [hostname, domain].join(".")
+ self.fqdn
end
@secureinit = hash[:NoSecureInit] || true
end
- def initcerts
- return unless @secureinit
- # verify we've got all of the certs set up and such
-
- # we are not going to encrypt our key, but we need at a minimum
- # a keyfile and a certfile
- certfile = File.join(Puppet[:certdir], [@fqdn, "pem"].join("."))
- keyfile = File.join(Puppet[:privatekeydir], [@fqdn, "pem"].join("."))
- publickeyfile = File.join(Puppet[:publickeydir], [@fqdn, "pem"].join("."))
-
- [Puppet[:certdir], Puppet[:privatekeydir], Puppet[:csrdir],
- Puppet[:publickeydir]].each { |dir|
- unless FileTest.exists?(dir)
- Puppet.recmkdir(dir, 0770)
- end
- }
-
- inited = false
- if File.exists?(keyfile)
- # load the key
- @key = OpenSSL::PKey::RSA.new(File.read(keyfile))
- else
- # create a new one and store it
- Puppet.info "Creating a new SSL key at %s" % keyfile
- @key = OpenSSL::PKey::RSA.new(Puppet[:keylength])
- File.open(keyfile, "w", 0660) { |f| f.print @key.to_pem }
- File.open(publickeyfile, "w", 0660) { |f|
- f.print @key.public_key.to_pem
- }
- end
-
- unless File.exists?(certfile)
- Puppet.info "Creating a new certificate request for %s" % @fqdn
- name = OpenSSL::X509::Name.new([["CN", @fqdn]])
-
- @csr = OpenSSL::X509::Request.new
- @csr.version = 0
- @csr.subject = name
- @csr.public_key = @key.public_key
- @csr.sign(@key, OpenSSL::Digest::MD5.new)
-
- Puppet.info "Requesting certificate"
-
- cert = @driver.getcert(@csr.to_pem)
-
- if cert.nil?
- raise Puppet::Error, "Failed to get certificate"
- end
- File.open(certfile, "w", 0660) { |f| f.print cert }
- begin
- @cert = OpenSSL::X509::Certificate.new(cert)
- inited = true
- rescue => detail
- raise Puppet::Error.new(
- "Invalid certificate: %s" % detail
- )
- end
- end
-
- return inited
- end
-
def getconfig
#client.loadproperty('files/sslclient.properties')
Puppet.debug("getting config")
@@ -190,7 +140,27 @@ module Puppet
objects = @driver.getconfig(facts)
else
textfacts = CGI.escape(Marshal::dump(facts))
- textobjects = CGI.unescape(@driver.getconfig(textfacts))
+ textobjects = nil
+ if textobjects = CGI.unescape(@driver.getconfig(textfacts))
+ # we store the config so that if we can't connect next time, we
+ # can just run against the most recently acquired copy
+ confdir = File.dirname(Puppet[:localconfig])
+ unless FileTest.exists?(confdir)
+ Puppet.recmkdir(confdir, 0770)
+ end
+ File.open(Puppet[:localconfig], "w", 0660) { |f|
+ f.print textobjects
+ }
+ else
+ if FileTest.exists?(Puppet[:localconfig])
+ textobjects = File.read(Puppet[:localconfig])
+ else
+ raise Puppet::Error.new(
+ "Cannot connect to server and there is no cached configuration"
+ )
+ end
+ end
+
begin
objects = Marshal::load(textobjects)
rescue => detail
@@ -257,27 +227,8 @@ module Puppet
return transaction
#self.shutdown
end
-
- private
-
- #def on_init
- # @default_namespace = 'urn:puppet-client'
- # add_method(self, 'config', 'config')
- # add_method(self, 'callfunc', 'name', 'arguments')
- #end
-
- def cert(filename)
- OpenSSL::X509::Certificate.new(File.open(File.join(@dir, filename)) { |f|
- f.read
- })
- end
-
- def key(filename)
- OpenSSL::PKey::RSA.new(File.open(File.join(@dir, filename)) { |f|
- f.read
- })
- end
-
end
#---------------------------------------------------------------
end
+
+# $Id$
diff --git a/lib/puppet/daemon.rb b/lib/puppet/daemon.rb
index 76b6cc829..e20cf4aa2 100755
--- a/lib/puppet/daemon.rb
+++ b/lib/puppet/daemon.rb
@@ -29,6 +29,15 @@ module Puppet
end
end
+ def fqdn
+ unless defined? @fqdn and @fqdn
+ hostname = Facter["hostname"].value
+ domain = Facter["domain"].value
+ @fqdn = [hostname, domain].join(".")
+ end
+ return @fqdn
+ end
+
def httplog
args = []
# yuck; separate http logs
@@ -44,6 +53,88 @@ module Puppet
return log
end
+
+ def initcerts
+ return unless @secureinit
+ # verify we've got all of the certs set up and such
+
+ # we are not going to encrypt our key, but we need at a minimum
+ # a keyfile and a certfile
+ certfile = File.join(Puppet[:certdir], [@fqdn, "pem"].join("."))
+ cacertfile = File.join(Puppet[:certdir], ["ca", "pem"].join("."))
+ keyfile = File.join(Puppet[:privatekeydir], [@fqdn, "pem"].join("."))
+ publickeyfile = File.join(Puppet[:publickeydir], [@fqdn, "pem"].join("."))
+
+ [Puppet[:certdir], Puppet[:privatekeydir], Puppet[:csrdir],
+ Puppet[:publickeydir]].each { |dir|
+ unless FileTest.exists?(dir)
+ Puppet.recmkdir(dir, 0770)
+ end
+ }
+
+ inited = false
+ if File.exists?(keyfile)
+ # load the key
+ @key = OpenSSL::PKey::RSA.new(File.read(keyfile))
+ else
+ # create a new one and store it
+ Puppet.info "Creating a new SSL key at %s" % keyfile
+ @key = OpenSSL::PKey::RSA.new(Puppet[:keylength])
+ File.open(keyfile, "w", 0660) { |f| f.print @key.to_pem }
+ File.open(publickeyfile, "w", 0660) { |f|
+ f.print @key.public_key.to_pem
+ }
+ end
+
+ if File.exists?(certfile)
+ unless File.exists?(cacertfile)
+ raise Puppet::Error, "Found cert file with no ca cert file"
+ end
+ @cert = OpenSSL::X509::Certificate.new(File.read(certfile))
+ inited = true
+ else
+ unless defined? @driver
+ Puppet.err "Cannot request a certificate without a defined target"
+ return false
+ end
+ Puppet.info "Creating a new certificate request for %s" % @fqdn
+ name = OpenSSL::X509::Name.new([["CN", @fqdn]])
+
+ @csr = OpenSSL::X509::Request.new
+ @csr.version = 0
+ @csr.subject = name
+ @csr.public_key = @key.public_key
+ @csr.sign(@key, OpenSSL::Digest::MD5.new)
+
+ Puppet.info "Requesting certificate"
+
+ begin
+ cert, cacert = @driver.getcert(@csr.to_pem)
+ rescue => detail
+ raise Puppet::Error.new("Certificate retrieval failed: %s" % detail)
+ end
+
+ if cert.nil? or cert == ""
+ return nil
+ end
+ File.open(certfile, "w", 0660) { |f| f.print cert }
+ File.open(cacertfile, "w", 0660) { |f| f.print cacert }
+ begin
+ @cert = OpenSSL::X509::Certificate.new(cert)
+ @cacert = OpenSSL::X509::Certificate.new(cacert)
+ inited = true
+ rescue => detail
+ raise Puppet::Error.new(
+ "Invalid certificate: %s" % detail
+ )
+ end
+ end
+
+ unless @cert.check_private_key(@key)
+ raise Puppet::DevError, "Received invalid certificate"
+ end
+ return inited
+ end
end
end
diff --git a/lib/puppet/sslcertificates.rb b/lib/puppet/sslcertificates.rb
index 13392dedf..1ccade1d8 100755
--- a/lib/puppet/sslcertificates.rb
+++ b/lib/puppet/sslcertificates.rb
@@ -49,7 +49,7 @@ module SSLCertificates
raise ArgumentError, "mkcert called without %s" % param
end
}
- cert = ::OpenSSL::X509::Certificate.new
+ cert = OpenSSL::X509::Certificate.new
from = Time.now
cert.subject = hash[:name]
@@ -89,13 +89,13 @@ module SSLCertificates
key_usage << %w{nonRepudiation digitalSignature keyEncipherment}
ext_key_usage << %w{clientAuth emailProtection}
else
- raise "unknonwn cert type '%s'" % hash[:type]
+ raise Puppet::Error, "unknown cert type '%s'" % hash[:type]
end
key_usage.flatten!
ext_key_usage.flatten!
- ef = ::OpenSSL::X509::ExtensionFactory.new
+ ef = OpenSSL::X509::ExtensionFactory.new
if hash[:issuer]
ef.issuer_certificate = hash[:issuer]
@@ -108,7 +108,7 @@ module SSLCertificates
ex = []
ex << ef.create_extension("basicConstraints", basic_constraint, true)
ex << ef.create_extension("nsComment",
- "Ruby/OpenSSL Generated Certificate")
+ "Puppet Ruby/OpenSSL Generated Certificate")
ex << ef.create_extension("subjectKeyIdentifier", "hash")
#ex << ef.create_extension("nsCertType", "client,email")
unless key_usage.empty? then
@@ -133,9 +133,6 @@ module SSLCertificates
#end
cert.extensions = ex
- #cmd = "#{ossl} req -nodes -new -x509 -keyout %s -out %s -config %s" %
- # [@key, certfile, Puppet::SSLCertificates.config]
-
# write the cert out
#File.open(certfile, "w") { |f| f << cert.to_pem }
@@ -193,6 +190,10 @@ module SSLCertificates
Puppet.setdefault(param,@@defaults[param])
}
+ def certfile
+ @config[:cacert]
+ end
+
def host2csrfile(hostname)
File.join(Puppet[:csrdir], [hostname, "pem"].join("."))
end
@@ -215,7 +216,7 @@ module SSLCertificates
self.getcert
unless FileTest.exists?(@config[:serial])
File.open(@config[:serial], "w") { |f|
- f << "%04X" % 0
+ f << "%04X" % 1
}
end
@@ -258,10 +259,10 @@ module SSLCertificates
def getclientcert(host)
certfile = host2certfile(host)
unless File.exists?(certfile)
- return nil
+ return [nil, nil]
end
- return OpenSSL::X509::Certificate.new(File.read(certfile))
+ return [OpenSSL::X509::Certificate.new(File.read(certfile)), @cert]
end
def list
@@ -341,24 +342,36 @@ module SSLCertificates
def sign(csr)
unless csr.is_a?(OpenSSL::X509::Request)
- raise "CA#sign only accepts OpenSSL::X509::Request objects, not %s" %
+ raise Puppet::Error,
+ "CA#sign only accepts OpenSSL::X509::Request objects, not %s" %
csr.class
end
unless csr.verify(csr.public_key)
- raise "CSR sign verification failed"
+ raise Puppet::Error, "CSR sign verification failed"
end
# i should probably check key length...
# read the ca cert in
- cacert = ::OpenSSL::X509::Certificate.new(
+ cacert = OpenSSL::X509::Certificate.new(
File.read(@config[:cacert])
)
- ca_keypair = ::OpenSSL::PKey::RSA.new(
- File.read(@config[:cakey]), @config[:password]
- )
+ cakey = nil
+ if @config[:password]
+ cakey = OpenSSL::PKey::RSA.new(
+ File.read(@config[:cakey]), @config[:password]
+ )
+ else
+ cakey = OpenSSL::PKey::RSA.new(
+ File.read(@config[:cakey])
+ )
+ end
+
+ unless cacert.check_private_key(cakey)
+ raise Puppet::Error, "CA Certificate is invalid"
+ end
serial = File.read(@config[:serial]).chomp.hex
newcert = SSLCertificates.mkcert(
@@ -367,7 +380,7 @@ module SSLCertificates
:days => @config[:ca_days],
:issuer => cacert,
:serial => serial,
- :publickey => ca_keypair.public_key
+ :publickey => csr.public_key
)
# increment the serial
@@ -375,11 +388,11 @@ module SSLCertificates
f << "%04X" % (serial + 1)
}
- newcert.sign(ca_keypair, ::OpenSSL::Digest::SHA1.new)
+ newcert.sign(cakey, OpenSSL::Digest::SHA1.new)
self.storeclientcert(newcert)
- return newcert
+ return [newcert, cacert]
end
def storeclientcsr(csr)
@@ -425,7 +438,7 @@ module SSLCertificates
}
def certname
- ::OpenSSL::X509::Name.new self.subject
+ OpenSSL::X509::Name.new self.subject
end
def delete
@@ -451,12 +464,12 @@ module SSLCertificates
self.mkkey()
end
if @password
- @key = ::OpenSSL::PKey::RSA.new(
+ @key = OpenSSL::PKey::RSA.new(
File.read(@keyfile),
@password
)
else
- @key = ::OpenSSL::PKey::RSA.new(
+ @key = OpenSSL::PKey::RSA.new(
File.read(@keyfile)
)
end
@@ -549,18 +562,22 @@ module SSLCertificates
self.getkey
end
- name = ::OpenSSL::X509::Name.new self.subject
+ name = OpenSSL::X509::Name.new self.subject
- @csr = ::OpenSSL::X509::Request.new
+ @csr = OpenSSL::X509::Request.new
@csr.version = 0
@csr.subject = name
@csr.public_key = @key.public_key
- @csr.sign(@key, ::OpenSSL::Digest::MD5.new)
+ @csr.sign(@key, OpenSSL::Digest::SHA1.new)
#File.open(@csrfile, "w") { |f|
# f << @csr.to_pem
#}
+ unless @csr.verify(@key.public_key)
+ raise Puppet::Error, "CSR sign verification failed"
+ end
+
return @csr
end
@@ -597,12 +614,24 @@ module SSLCertificates
def mkkey
# @key is the file
- @key = ::OpenSSL::PKey::RSA.new 1024
+ @key = OpenSSL::PKey::RSA.new(1024)
+# { |p,n|
+# case p
+# when 0; Puppet.info "key info: ." # BN_generate_prime
+# when 1; Puppet.info "key info: +" # BN_generate_prime
+# when 2; Puppet.info "key info: *" # searching good prime,
+# # n = #of try,
+# # but also data from BN_generate_prime
+# when 3; Puppet.info "key info: \n" # found good prime, n==0 - p, n==1 - q,
+# # but also data from BN_generate_prime
+# else; Puppet.info "key info: *" # BN_generate_prime
+# end
+# }
if @password
#passwdproc = proc { @password }
keytext = @key.export(
- ::OpenSSL::Cipher::DES.new(:EDE3, :CBC),
+ OpenSSL::Cipher::DES.new(:EDE3, :CBC),
@password
)
File.open(@keyfile, "w", 0400) { |f|
@@ -635,7 +664,7 @@ module SSLCertificates
:publickey => @key.public_key
)
- @cert.sign(@key, ::OpenSSL::Digest::SHA1.new) if @selfsign
+ @cert.sign(@key, OpenSSL::Digest::SHA1.new) if @selfsign
end
def subject(string = false)
diff --git a/test/client/tc_client.rb b/test/client/tc_client.rb
index 2ddf53c98..bbb251a6d 100644
--- a/test/client/tc_client.rb
+++ b/test/client/tc_client.rb
@@ -80,9 +80,8 @@ class TestClient < Test::Unit::TestCase
client = Puppet::Client.new(:Server => server)
}
certfile = File.join(Puppet[:certdir], [client.fqdn, "pem"].join("."))
- assert_raise(Puppet::Error) {
- client.initcerts
- }
+ cafile = File.join(Puppet[:certdir], ["ca", "pem"].join("."))
+ assert_nil(client.initcerts)
assert(! File.exists?(certfile))
ca = nil
@@ -100,8 +99,9 @@ class TestClient < Test::Unit::TestCase
cert = nil
assert_nothing_raised {
- cert = ca.sign(csr)
+ cert, cacert = ca.sign(csr)
File.open(certfile, "w") { |f| f.print cert.to_pem }
+ File.open(cafile, "w") { |f| f.print cacert.to_pem }
}
# this time it should get the cert correctly