1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
require 'webrick'
require 'webrick/https'
require 'puppet/network/http/webrick/rest'
require 'thread'
require 'puppet/ssl/certificate'
require 'puppet/ssl/certificate_revocation_list'
class Puppet::Network::HTTP::WEBrick
def initialize(args = {})
@listening = false
@mutex = Mutex.new
end
def self.class_for_protocol(protocol)
return Puppet::Network::HTTP::WEBrickREST if protocol.to_sym == :rest
raise "Unknown protocol [#{protocol}]."
end
def listen(args = {})
raise ArgumentError, ":handlers must be specified." if !args[:handlers] or args[:handlers].empty?
raise ArgumentError, ":protocols must be specified." if !args[:protocols] or args[:protocols].empty?
raise ArgumentError, ":address must be specified." unless args[:address]
raise ArgumentError, ":port must be specified." unless args[:port]
@protocols = args[:protocols]
@handlers = args[:handlers]
arguments = {:BindAddress => args[:address], :Port => args[:port]}
arguments.merge!(setup_logger)
arguments.merge!(setup_ssl)
@server = WEBrick::HTTPServer.new(arguments)
setup_handlers
@mutex.synchronize do
raise "WEBrick server is already listening" if @listening
@listening = true
@thread = Thread.new { @server.start }
end
end
def unlisten
@mutex.synchronize do
raise "WEBrick server is not listening" unless @listening
@server.shutdown
@thread.join
@server = nil
@listening = false
end
end
def listening?
@mutex.synchronize do
@listening
end
end
# Configure our http log file.
def setup_logger
# Make sure the settings are all ready for us.
Puppet.settings.use(:main, :ssl, Puppet[:name])
if Puppet[:name] == "puppetmasterd"
file = Puppet[:masterhttplog]
else
file = Puppet[:httplog]
end
# open the log manually to prevent file descriptor leak
file_io = ::File.open(file, "a+")
file_io.sync
file_io.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
args = [file_io]
args << WEBrick::Log::DEBUG if Puppet::Util::Log.level == :debug
logger = WEBrick::Log.new(*args)
return :Logger => logger, :AccessLog => [
[logger, WEBrick::AccessLog::COMMON_LOG_FORMAT ],
[logger, WEBrick::AccessLog::REFERER_LOG_FORMAT ]
]
end
# Add all of the ssl cert information.
def setup_ssl
results = {}
host = Puppet::SSL::Host.new
host.generate unless host.key
raise Puppet::Error, "Could not retrieve certificate for %s" % host.name unless host.certificate
results[:SSLPrivateKey] = host.key.content
results[:SSLCertificate] = host.certificate.content
results[:SSLStartImmediately] = true
results[:SSLEnable] = true
unless Puppet::SSL::Certificate.find("ca")
raise Puppet::Error, "Could not find CA certificate"
end
results[:SSLCACertificateFile] = Puppet[:localcacert]
results[:SSLVerifyClient] = OpenSSL::SSL::VERIFY_PEER
# LAK:NOTE I'm not sure why this is this way, actually.
results[:SSLCertName] = nil
results[:SSLCertificateStore] = setup_ssl_store if Puppet[:cacrl] != 'false'
results
end
# Create our Certificate revocation list
def setup_ssl_store
unless crl = Puppet::SSL::CertificateRevocationList.find("ca")
raise Puppet::Error, "Could not find CRL; set 'cacrl' to 'false' to disable CRL usage"
end
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(Puppet[:localcacert])
store.add_crl(crl.content)
return store
end
private
def setup_handlers
@protocols.each do |protocol|
klass = self.class.class_for_protocol(protocol)
@handlers.each do |handler|
@server.mount('/' + handler.to_s, klass, handler)
@server.mount('/' + handler.to_s + 's', klass, handler)
end
end
end
end
|