summaryrefslogtreecommitdiffstats
path: root/lib/puppet
diff options
context:
space:
mode:
Diffstat (limited to 'lib/puppet')
-rw-r--r--lib/puppet/client.rb120
-rwxr-xr-xlib/puppet/daemon.rb132
-rwxr-xr-xlib/puppet/sslcertificates.rb100
3 files changed, 229 insertions, 123 deletions
diff --git a/lib/puppet/client.rb b/lib/puppet/client.rb
index 39c3aa65b..4b2c57232 100644
--- a/lib/puppet/client.rb
+++ b/lib/puppet/client.rb
@@ -32,21 +32,40 @@ module Puppet
class NetworkClient < XMLRPC::Client
#include Puppet::Daemon
- @@methods = [ :getconfig, :getcert ]
-
- @@methods.each { |method|
- 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,
- "XMLRPC Error: %s" % detail.faultString
- rescue => detail
- Puppet.err "Could not call %s: %s" % [method, detail.inspect]
- raise NetworkClientError.new(detail.to_s)
- end
+ @@methods = {
+ "puppetmaster" => [ :getconfig ],
+ "puppetca" => [ :getcert ]
+ }
+
+ @@methods.each { |namespace, methods|
+ methods.each { |method|
+ self.send(:define_method,method) { |*args|
+ Puppet.info "peer cert is %s" % @http.peer_cert
+ #Puppet.info "cert is %s" % @http.cert
+ begin
+ call("%s.%s" % [namespace, method.to_s],*args)
+ rescue XMLRPC::FaultException => detail
+ Puppet.err "XML Could not call %s.%s: %s" %
+ [namespace, method, detail.faultString]
+ raise NetworkClientError.new,
+ "XMLRPC Error: %s" % detail.faultString
+ rescue => detail
+ Puppet.err "Could not call %s.%s: %s" %
+ [namespace, method, detail.inspect]
+ raise NetworkClientError.new(detail.to_s)
+ end
+ }
+ }
+ }
+
+ [:key, :cert, :ca_file].each { |method|
+ setmethod = method.to_s + "="
+ #self.send(:define_method, method) {
+ # @http.send(method)
+ #}
+ self.send(:define_method, setmethod) { |*args|
+ Puppet.debug "Setting %s" % method
+ @http.send(setmethod, *args)
}
}
@@ -54,6 +73,7 @@ module Puppet
hash[:Path] ||= "/RPC2"
hash[:Server] ||= "localhost"
hash[:Port] ||= Puppet[:masterport]
+
super(
hash[:Server],
hash[:Path],
@@ -62,7 +82,29 @@ module Puppet
nil, # proxy_port
nil, # user
nil, # password
- true) # use_ssl
+ true # use_ssl
+ )
+
+ if hash[:Certificate]
+ Puppet.info "adding cert to @http"
+ @http.cert = hash[:Certificate]
+ end
+
+ if hash[:Key]
+ @http.key = hash[:Key]
+ end
+
+ if hash[:CAFile]
+ @http.ca_file = hash[:CAFile]
+ store = OpenSSL::X509::Store.new
+ cacert = OpenSSL::X509::Certificate.new(
+ File.read(hash[:CAFile])
+ )
+ store.add_cert(cacert)
+ store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
+ @http.cert_store = store
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
+ end
# from here, i need to add the key, cert, and ca cert
# and reorgize how i start the client
@@ -88,6 +130,14 @@ module Puppet
# to whom do we connect?
@server = nil
@nil = nil
+ @secureinit = hash[:NoSecureInit] || true
+
+ if hash.include?(:FQDN)
+ @fqdn = hash[:FQDN]
+ else
+ self.fqdn
+ end
+
if hash.include?(:Server)
case hash[:Server]
when String:
@@ -102,6 +152,13 @@ module Puppet
args[arg] = hash[arg]
end
}
+
+ if self.readcert
+ args[:Certificate] = @cert
+ args[:Key] = @key
+ args[:CAFile] = @cacertfile
+ end
+
@driver = Puppet::NetworkClient.new(args)
@local = false
when Puppet::Master:
@@ -114,14 +171,6 @@ module Puppet
else
raise ClientError.new("Must pass :Server to client")
end
-
- if hash.include?(:FQDN)
- @fqdn = hash[:FQDN]
- else
- self.fqdn
- end
-
- @secureinit = hash[:NoSecureInit] || true
end
def getconfig
@@ -202,11 +251,11 @@ module Puppet
end
end
- container = tree.to_type
+ container = @objects.to_type
#if @local
- # container = tree.to_type
+ # container = @objects.to_type
#else
- # container = Marshal::load(tree).to_type
+ # container = Marshal::load(@objects).to_type
#end
# this is a gross hack... but i don't see a good way around it
@@ -231,6 +280,23 @@ module Puppet
return transaction
#self.shutdown
end
+
+ def initcerts
+ unless self.readcert
+ unless self.requestcert
+ return nil
+ end
+ end
+
+ unless @driver
+ return true
+ end
+
+ Puppet.info "setting cert and key and such"
+ @driver.cert = @cert
+ @driver.key = @key
+ @driver.ca_file = @cacertfile
+ end
end
#---------------------------------------------------------------
end
diff --git a/lib/puppet/daemon.rb b/lib/puppet/daemon.rb
index 8bebea832..1cbb35ce5 100755
--- a/lib/puppet/daemon.rb
+++ b/lib/puppet/daemon.rb
@@ -54,17 +54,44 @@ module Puppet
return log
end
- def initcerts
+ def readcert
return unless @secureinit
# verify we've got all of the certs set up and such
+ if defined? @cert and defined? @key and @cert and @key
+ return true
+ end
+
# 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("."))
+ @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("."))
+ if File.exists?(@keyfile)
+ # load the key
+ @key = OpenSSL::PKey::RSA.new(File.read(@keyfile))
+ else
+ return false
+ end
+
+ if File.exists?(@certfile)
+ if File.exists?(@cacertfile)
+ @cacert = OpenSSL::X509::Certificate.new(File.read(@cacertfile))
+ else
+ raise Puppet::Error, "Found cert file with no ca cert file"
+ end
+ @cert = OpenSSL::X509::Certificate.new(File.read(@certfile))
+ else
+ return false
+ end
+ return true
+ end
+
+ def requestcert
+ retrieved = false
+ # create the directories involved
[Puppet[:certdir], Puppet[:privatekeydir], Puppet[:csrdir],
Puppet[:publickeydir]].each { |dir|
unless FileTest.exists?(dir)
@@ -72,69 +99,62 @@ module Puppet
end
}
- inited = false
- if File.exists?(keyfile)
- # load the key
- @key = OpenSSL::PKey::RSA.new(File.read(keyfile))
- else
+ if self.readcert
+ Puppet.info "Certificate already exists; not requesting"
+ return true
+ end
+
+ unless defined? @key and @key
# create a new one and store it
- Puppet.info "Creating a new SSL key at %s" % keyfile
+ 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|
+ 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
+ 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]])
- 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
+ @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)
+ retrieved = true
+ rescue => detail
+ raise Puppet::Error.new(
+ "Invalid certificate: %s" % detail
+ )
end
unless @cert.check_private_key(@key)
raise Puppet::DevError, "Received invalid certificate"
end
- return inited
+ return retrieved
end
end
end
diff --git a/lib/puppet/sslcertificates.rb b/lib/puppet/sslcertificates.rb
index 1ccade1d8..b8a4d27aa 100755
--- a/lib/puppet/sslcertificates.rb
+++ b/lib/puppet/sslcertificates.rb
@@ -56,6 +56,7 @@ module SSLCertificates
if hash[:issuer]
cert.issuer = hash[:issuer].subject
else
+ # we're a self-signed cert
cert.issuer = cert.subject
end
cert.not_before = from
@@ -139,6 +140,36 @@ module SSLCertificates
return cert
end
+ def self.mkhash(dir, cert, certfile)
+ hash = "%x" % cert.issuer.hash
+ hashpath = nil
+ 10.times { |i|
+ path = File.join(dir, "%s.%s" % [hash, i])
+ if FileTest.exists?(path)
+ if FileTest.symlink?(path)
+ dest = File.readlink(path)
+ if dest == certfile
+ # the correct link already exists
+ hashpath = path
+ break
+ else
+ next
+ end
+ else
+ next
+ end
+ end
+
+ File.symlink(certfile, path)
+
+ hashpath = path
+ break
+ }
+
+ return hashpath
+ end
+
+
class CA
attr_accessor :keyfile, :file, :config, :dir, :cert
@@ -425,7 +456,7 @@ module SSLCertificates
class Certificate
attr_accessor :certfile, :keyfile, :name, :dir, :hash, :type
- attr_accessor :key, :cert, :csr
+ attr_accessor :key, :cert, :csr, :cacert
@@params2names = {
:name => "CN",
@@ -492,6 +523,8 @@ module SSLCertificates
@certfile = File.join(@dir, @name)
end
+ @cacertfile ||= File.join(Puppet[:certdir], "ca.pem")
+
unless FileTest.directory?(@dir)
Puppet::SSLCertificates.mkdir(@dir)
end
@@ -581,36 +614,6 @@ module SSLCertificates
return @csr
end
- def mkhash
- hash = "%x" % @cert.issuer.hash
- path = nil
- 10.times { |i|
- path = File.join(@dir, "%s.%s" % [hash, i])
- if FileTest.exists?(path)
- if FileTest.symlink?(path)
- dest = File.readlink(path)
- if dest == @certfile
- # the correct link already exists
- puts "hash already exists"
- @hash = path
- return
- else
- next
- end
- else
- next
- end
- end
-
- File.symlink(@certfile, path)
-
- @hash = path
- break
- }
-
- return path
- end
-
def mkkey
# @key is the file
@@ -665,6 +668,8 @@ module SSLCertificates
)
@cert.sign(@key, OpenSSL::Digest::SHA1.new) if @selfsign
+
+ return @cert
end
def subject(string = false)
@@ -683,29 +688,44 @@ module SSLCertificates
end
end
+ # verify that we can track down the cert chain or whatever
+ def verify
+ "openssl verify -verbose -CAfile /home/luke/.puppet/ssl/certs/ca.pem -purpose sslserver culain.madstop.com.pem"
+ end
+
def write
files = {
@certfile => @cert,
@keyfile => @key,
}
- #@csrfile => @csr
+ if defined? @cacert
+ files[@cacertfile] = @cacert
+ end
files.each { |file,thing|
if defined? thing and thing
if FileTest.exists?(file)
- newtext = File.open(file) { |f| f.read }
- if newtext != thing.to_pem
- raise "Cannot replace existing %s" % thing.class
- else
- next
- end
+ next
+ end
+
+ text = nil
+
+ if thing.is_a?(OpenSSL::PKey::RSA) and @password
+ text = thing.export(
+ OpenSSL::Cipher::DES.new(:EDE3, :CBC),
+ @password
+ )
+ else
+ text = thing.to_pem
end
- File.open(file, "w", 0660) { |f| f.print thing.to_pem }
+ File.open(file, "w", 0660) { |f| f.print text }
end
}
- self.mkhash
+ if defined? @cacert
+ SSLCertificates.mkhash(Puppet[:certdir], @cacert, @cacertfile)
+ end
end
end
end