summaryrefslogtreecommitdiffstats
path: root/lib/puppet/network/server.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/puppet/network/server.rb')
-rw-r--r--lib/puppet/network/server.rb207
1 files changed, 207 insertions, 0 deletions
diff --git a/lib/puppet/network/server.rb b/lib/puppet/network/server.rb
new file mode 100644
index 000000000..e9205d48b
--- /dev/null
+++ b/lib/puppet/network/server.rb
@@ -0,0 +1,207 @@
+# the server
+#
+# allow things to connect to us and communicate, and stuff
+
+require 'puppet'
+require 'puppet/daemon'
+require 'webrick'
+require 'webrick/https'
+require 'cgi'
+require 'xmlrpc/server'
+require 'xmlrpc/client'
+
+module Puppet
+ class ServerError < RuntimeError; end
+ module Network
+ class Server < WEBrick::HTTPServer
+ include Puppet::Daemon
+
+ Puppet.config.setdefaults(:puppetd,
+ :listen => [false, "Whether puppetd should listen for
+ connections. If this is true, then by default only the
+ ``runner`` server is started, which allows remote authorized
+ and authenticated nodes to connect and trigger ``puppetd``
+ runs."]
+ )
+
+ # Create our config object if necessary. This works even if
+ # there's no configuration file.
+ def authconfig
+ unless defined? @authconfig
+ @authconfig = Puppet::Network::AuthConfig.new()
+ end
+
+ @authconfig
+ end
+
+ # Read the CA cert and CRL and populate an OpenSSL::X509::Store
+ # with them, with flags appropriate for checking client
+ # certificates for revocation
+ def x509store
+ if Puppet[:cacrl] == 'none'
+ # No CRL, no store needed
+ return nil
+ end
+ unless File.exist?(Puppet[:cacrl])
+ raise Puppet::Error, "Could not find CRL"
+ end
+ crl = OpenSSL::X509::CRL.new(File.read(Puppet[:cacrl]))
+ store = OpenSSL::X509::Store.new
+ store.purpose = OpenSSL::X509::PURPOSE_ANY
+ store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL|OpenSSL::X509::V_FLAG_CRL_CHECK
+ store.add_file(@cacertfile)
+ store.add_crl(crl)
+ return store
+ end
+
+ def initialize(hash = {})
+ Puppet.info "Starting server for Puppet version %s" % Puppet.version
+ daemonize = nil
+ if hash.include?(:Daemonize)
+ daemonize = hash[:Daemonize]
+ end
+
+ # FIXME we should have some kind of access control here, using
+ # :RequestHandler
+ hash[:Port] ||= Puppet[:masterport]
+ hash[:Logger] ||= self.httplog
+ hash[:AccessLog] ||= [
+ [ self.httplog, WEBrick::AccessLog::COMMON_LOG_FORMAT ],
+ [ self.httplog, WEBrick::AccessLog::REFERER_LOG_FORMAT ]
+ ]
+
+ if hash.include?(:Handlers)
+ unless hash[:Handlers].is_a?(Hash)
+ raise ServerError, "Handlers must have arguments"
+ end
+
+ @handlers = hash[:Handlers].collect { |handler, args|
+ hclass = nil
+ unless hclass = Handler.handler(handler)
+ raise ServerError, "Invalid handler %s" % handler
+ end
+ hclass.new(args)
+ }
+ else
+ raise ServerError, "A server must have handlers"
+ end
+
+ # okay, i need to retrieve my cert and set it up, somehow
+ # the default case will be that i'm also the ca
+ if ca = @handlers.find { |handler| handler.is_a?(Puppet::Network::Server::CA) }
+ @driver = ca
+ @secureinit = true
+ self.fqdn
+ else
+ if hash.include?(:NoSecureInit)
+ @secureinit = false
+ else
+ @secureinit = true
+ end
+ end
+
+ unless self.readcert
+ unless self.requestcert
+ raise Puppet::Error, "Cannot start without certificates"
+ end
+ end
+
+ hash[:SSLCertificateStore] = x509store
+ hash[:SSLCertificate] = @cert
+ hash[:SSLPrivateKey] = @key
+ hash[:SSLStartImmediately] = true
+ hash[:SSLEnable] = true
+ hash[:SSLCACertificateFile] = @cacertfile
+ hash[:SSLVerifyClient] = OpenSSL::SSL::VERIFY_PEER
+ hash[:SSLCertName] = nil
+
+ super(hash)
+
+ Puppet.info "Listening on port %s" % hash[:Port]
+
+ # this creates a new servlet for every connection,
+ # but all servlets have the same list of handlers
+ # thus, the servlets can have their own state -- passing
+ # around the requests and such -- but the handlers
+ # have a global state
+
+ # mount has to be called after the server is initialized
+ self.mount("/RPC2", Puppet::Network::Server::Servlet, @handlers)
+ end
+
+ # the base class for the different handlers
+ class Handler
+ attr_accessor :server
+ class << self
+ include Puppet::Util
+ end
+
+ @subclasses = []
+
+ def self.each
+ @subclasses.each { |c| yield c }
+ end
+
+ def self.handler(name)
+ name = name.to_s.downcase
+ @subclasses.find { |h|
+ h.name.to_s.downcase == name
+ }
+ end
+
+ def self.inherited(sub)
+ @subclasses << sub
+ end
+
+ def self.interface
+ if defined? @interface
+ return @interface
+ else
+ raise Puppet::DevError, "Handler %s has no defined interface" %
+ self
+ end
+ end
+
+ def self.name
+ unless defined? @name
+ @name = self.to_s.sub(/.+::/, '').intern
+ end
+
+ return @name
+ end
+
+ def initialize(hash = {})
+ end
+ end
+
+
+ class ServerStatus < Handler
+
+ @interface = XMLRPC::Service::Interface.new("status") { |iface|
+ iface.add_method("int status()")
+ }
+
+ @name = :Status
+
+ def status(status = nil, client = nil, clientip = nil)
+ return 1
+ end
+ end
+ end
+ end
+end
+
+require 'puppet/network/server/authstore'
+require 'puppet/network/server/authconfig'
+require 'puppet/network/server/servlet'
+require 'puppet/network/server/master'
+require 'puppet/network/server/ca'
+require 'puppet/network/server/fileserver'
+require 'puppet/network/server/filebucket'
+require 'puppet/network/server/resource'
+require 'puppet/network/server/runner'
+require 'puppet/network/server/logger'
+require 'puppet/network/server/report'
+require 'puppet/network/client'
+
+# $Id$