3
require 'webrick/https'
6
require 'puppet/sslcertificates/support'
7
require 'puppet/network/xmlrpc/webrick_servlet'
8
require 'puppet/network/http_server'
9
require 'puppet/network/client'
10
require 'puppet/network/handler'
13
class ServerError < RuntimeError; end
15
# The old-school, pure ruby webrick server, which is the default serving
17
class HTTPServer::WEBrick < WEBrick::HTTPServer
18
include Puppet::SSLCertificates::Support
20
# Read the CA cert and CRL and populate an OpenSSL::X509::Store
21
# with them, with flags appropriate for checking client
22
# certificates for revocation
24
unless File.exist?(Puppet[:cacrl])
25
# No CRL, no store needed
28
crl = OpenSSL::X509::CRL.new(File.read(Puppet[:cacrl]))
29
store = OpenSSL::X509::Store.new
30
store.purpose = OpenSSL::X509::PURPOSE_ANY
31
store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL|OpenSSL::X509::V_FLAG_CRL_CHECK if Puppet.settings[:certificate_revocation]
32
raise Puppet::Error, "Could not find CA certificate" unless self.ca_cert
34
store.add_file(Puppet[:localcacert])
39
# Set up the http log.
43
# yuck; separate http logs
45
Puppet.settings.use(:main, :ssl, Puppet[:name])
46
if Puppet.run_mode.master?
47
file = Puppet[:masterhttplog]
49
file = Puppet[:httplog]
52
# open the log manually to prevent file descriptor leak
53
file_io = open(file, "a+")
55
file_io.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
58
args << WEBrick::Log::DEBUG if Puppet[:debug]
60
log = WEBrick::Log.new(*args)
66
# Create our server, yo.
67
def initialize(hash = {})
68
Puppet.info "Starting server for Puppet version #{Puppet.version}"
70
if handlers = hash[:Handlers]
71
handler_instances = setup_handlers(handlers)
73
raise ServerError, "A server must have handlers"
77
if ca = handler_instances.find { |handler| handler.is_a?(Puppet::Network::Handler.ca) }
80
raise Puppet::Error, "No certificate and no CA; cannot get cert"
89
puts detail.backtrace if Puppet[:trace]
90
raise Puppet::Error, "Could not start WEBrick: #{detail}"
93
# make sure children don't inherit the sockets
94
listeners.each { |sock|
95
sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
98
Puppet.info "Listening on port #{hash[:Port]}"
100
# this creates a new servlet for every connection,
101
# but all servlets have the same list of handlers
102
# thus, the servlets can have their own state -- passing
103
# around the requests and such -- but the handlers
104
# have a global state
106
# mount has to be called after the server is initialized
107
servlet = Puppet::Network::XMLRPC::WEBrickServlet.new( handler_instances)
108
self.mount("/RPC2", servlet)
111
# Create a ca client to set up our cert for us.
113
client = Puppet::Network::Client.ca.new(:CA => ca)
114
raise Puppet::Error, "Could get certificate" unless client.request_cert
117
# Create all of our handler instances.
118
def setup_handlers(handlers)
119
raise ServerError, "Handlers must have arguments" unless handlers.is_a?(Hash)
121
handlers.collect { |handler, args|
123
unless hclass = Puppet::Network::Handler.handler(handler)
124
raise ServerError, "Invalid handler #{handler}"
130
# Handle all of the many webrick arguments.
131
def setup_webrick(hash)
132
hash[:Port] ||= Puppet[:masterport]
133
hash[:Logger] ||= self.httplog
134
hash[:AccessLog] ||= [
135
[ self.httplog, WEBrick::AccessLog::COMMON_LOG_FORMAT ],
136
[ self.httplog, WEBrick::AccessLog::REFERER_LOG_FORMAT ]
139
hash[:SSLCertificateStore] = x509store
140
hash[:SSLCertificate] = self.cert
141
hash[:SSLPrivateKey] = self.key
142
hash[:SSLStartImmediately] = true
143
hash[:SSLEnable] = true
144
hash[:SSLCACertificateFile] = Puppet[:localcacert]
145
hash[:SSLVerifyClient] = OpenSSL::SSL::VERIFY_PEER
146
hash[:SSLCertName] = nil
148
if addr = Puppet[:bindaddress] and addr != ""
149
hash[:BindAddress] = addr