diff options
Diffstat (limited to 'lib/puppet/network')
-rw-r--r-- | lib/puppet/network/handler/master.rb | 24 | ||||
-rw-r--r-- | lib/puppet/network/http/handler.rb | 55 | ||||
-rw-r--r-- | lib/puppet/network/http/mongrel/rest.rb | 41 | ||||
-rw-r--r-- | lib/puppet/network/http/webrick/rest.rb | 51 |
4 files changed, 97 insertions, 74 deletions
diff --git a/lib/puppet/network/handler/master.rb b/lib/puppet/network/handler/master.rb index 851ccc7b2..a050b089b 100644 --- a/lib/puppet/network/handler/master.rb +++ b/lib/puppet/network/handler/master.rb @@ -56,7 +56,8 @@ class Puppet::Network::Handler # Call our various handlers; this handler is getting deprecated. def getconfig(facts, format = "marshal", client = nil, clientip = nil) facts = decode_facts(facts) - client, clientip = clientname(client, clientip, facts) + + client ||= facts["hostname"] # Pass the facts to the fact handler Puppet::Node::Facts.new(client, facts).save unless local? @@ -66,27 +67,6 @@ class Puppet::Network::Handler return translate(catalog.extract) end - private - - # Manipulate the client name as appropriate. - def clientname(name, ip, facts) - # Always use the hostname from Facter. - client = facts["hostname"] - clientip = facts["ipaddress"] - if Puppet[:node_name] == 'cert' - if name - client = name - facts["fqdn"] = client - facts["hostname"], facts["domain"] = client.split('.', 2) - end - if ip - clientip = ip - end - end - - return client, clientip - end - # def decode_facts(facts) if @local diff --git a/lib/puppet/network/http/handler.rb b/lib/puppet/network/http/handler.rb index c05d4907f..3c14c8a40 100644 --- a/lib/puppet/network/http/handler.rb +++ b/lib/puppet/network/http/handler.rb @@ -1,30 +1,30 @@ module Puppet::Network::HTTP::Handler - + def initialize_for_puppet(args = {}) raise ArgumentError unless @server = args[:server] raise ArgumentError unless @handler = args[:handler] @model = find_model_for_handler(@handler) end - + # handle an HTTP request def process(request, response) return do_find(request, response) if get?(request) and singular?(request) return do_search(request, response) if get?(request) and plural?(request) return do_destroy(request, response) if delete?(request) and singular?(request) - return do_save(request, response) if put?(request) and singular?(request) + return do_save(request, response) if put?(request) and singular?(request) raise ArgumentError, "Did not understand HTTP #{http_method(request)} request for '#{path(request)}'" rescue Exception => e return do_exception(request, response, e) end - + private def model @model end - + def do_find(request, response) - key = request_key(request) || raise(ArgumentError, "Could not locate lookup key in request path [#{path}]") + key = request_key(request) || raise(ArgumentError, "Could not locate lookup key in request path [#{path(request)}]") args = params(request) result = model.find(key, args).to_yaml encode_result(request, response, result) @@ -37,7 +37,7 @@ module Puppet::Network::HTTP::Handler end def do_destroy(request, response) - key = request_key(request) || raise(ArgumentError, "Could not locate lookup key in request path [#{path}]") + key = request_key(request) || raise(ArgumentError, "Could not locate lookup key in request path [#{path(request)}]") args = params(request) result = model.destroy(key, args) encode_result(request, response, YAML.dump(result)) @@ -46,70 +46,73 @@ module Puppet::Network::HTTP::Handler def do_save(request, response) data = body(request).to_s raise ArgumentError, "No data to save" if !data or data.empty? - # args = params(request) + args = params(request) obj = model.from_yaml(data) - result = save_object(obj).to_yaml + result = save_object(obj, args).to_yaml encode_result(request, response, result) end - - def save_object(obj) - obj.save + + # LAK:NOTE This has to be here for testing; it's a stub-point so + # we keep infinite recursion from happening. + def save_object(object, args) + object.save(args) end - + def do_exception(request, response, exception, status=404) encode_result(request, response, exception.to_yaml, status) end - + def find_model_for_handler(handler) Puppet::Indirector::Indirection.model(handler) || raise(ArgumentError, "Cannot locate indirection [#{handler}].") end - + def get?(request) http_method(request) == 'GET' end - + def put?(request) http_method(request) == 'PUT' end - + def delete?(request) http_method(request) == 'DELETE' end - + def singular?(request) %r{/#{@handler.to_s}$}.match(path(request)) end - + def plural?(request) %r{/#{@handler.to_s}s$}.match(path(request)) end - + # methods to be overridden by the including web server class + def register_handler raise NotImplementedError end - + def http_method(request) raise NotImplementedError end - + def path(request) raise NotImplementedError end - + def request_key(request) raise NotImplementedError end - + def body(request) raise NotImplementedError end - + def params(request) raise NotImplementedError end - + def encode_result(request, response, result, status = 200) raise NotImplementedError end diff --git a/lib/puppet/network/http/mongrel/rest.rb b/lib/puppet/network/http/mongrel/rest.rb index a471a62bf..520ad67f0 100644 --- a/lib/puppet/network/http/mongrel/rest.rb +++ b/lib/puppet/network/http/mongrel/rest.rb @@ -3,45 +3,64 @@ require 'puppet/network/http/handler' class Puppet::Network::HTTP::MongrelREST < Mongrel::HttpHandler include Puppet::Network::HTTP::Handler - + def initialize(args={}) super() initialize_for_puppet(args) end + # Return the query params for this request. We had to expose this method for + # testing purposes. + def params(request) + Mongrel::HttpRequest.query_parse(request.params["QUERY_STRING"]).merge(client_info(request)) + end + private - + # which HTTP verb was used in this request def http_method(request) request.params[Mongrel::Const::REQUEST_METHOD] end - + # what path was requested? def path(request) # LAK:NOTE See http://snurl.com/21zf8 [groups_google_com] x = '/' + request.params[Mongrel::Const::REQUEST_PATH].split('/')[1] end - + # return the key included in the request path def request_key(request) # LAK:NOTE See http://snurl.com/21zf8 [groups_google_com] x = request.params[Mongrel::Const::REQUEST_PATH].split('/')[2] end - + # return the request body def body(request) request.body end - - # return the query params for this request - def params(request) - Mongrel::HttpRequest.query_parse(request.params["QUERY_STRING"]) - end - + # produce the body of the response def encode_result(request, response, result, status = 200) response.start(status) do |head, body| body.write(result) end end + + def client_info(request) + result = {} + params = request.params + result[:ip] = params["REMOTE_ADDR"] + + # JJM #906 The following dn.match regular expression is forgiving + # enough to match the two Distinguished Name string contents + # coming from Apache, Pound or other reverse SSL proxies. + if dn = params[Puppet[:ssl_client_header]] and dn_matchdata = dn.match(/^.*?CN\s*=\s*(.*)/) + result[:node] = dn_matchdata[1].to_str + result[:authenticated] = (params[Puppet[:ssl_client_verify_header]] == 'SUCCESS') + else + result[:authenticated] = false + end + + return result + end end diff --git a/lib/puppet/network/http/webrick/rest.rb b/lib/puppet/network/http/webrick/rest.rb index b43912196..a235fb4f3 100644 --- a/lib/puppet/network/http/webrick/rest.rb +++ b/lib/puppet/network/http/webrick/rest.rb @@ -1,46 +1,67 @@ require 'puppet/network/http/handler' class Puppet::Network::HTTP::WEBrickREST < WEBrick::HTTPServlet::AbstractServlet - + include Puppet::Network::HTTP::Handler - + def initialize(server, handler) - raise ArgumentError, "server is required" unless server - super(server) - initialize_for_puppet(:server => server, :handler => handler) + raise ArgumentError, "server is required" unless server + super(server) + initialize_for_puppet(:server => server, :handler => handler) + end + + # We had to expose this method for testing purposes. + def params(request) + result = request.query + result.merge(client_information(request)) end # WEBrick uses a service() method to respond to requests. Simply delegate to the handler response() method. def service(request, response) process(request, response) end - + private - + def http_method(request) request.request_method end - + def path(request) # LAK:NOTE See http://snurl.com/21zf8 [groups_google_com] x = '/' + request.path.split('/')[1] end - + def request_key(request) # LAK:NOTE See http://snurl.com/21zf8 [groups_google_com] x = request.path.split('/')[2] end - + def body(request) request.body end - - def params(request) - request.query - end - + def encode_result(request, response, result, status = 200) response.status = status response.body = result end + + # Retrieve node/cert/ip information from the request object. + def client_information(request) + result = {} + if peer = request.peeraddr and ip = peer[3] + result[:ip] = ip + end + + # If they have a certificate (which will almost always be true) + # then we get the hostname from the cert, instead of via IP + # info + result[:authenticated] = false + if cert = request.client_cert and nameary = cert.subject.to_a.find { |ary| ary[0] == "CN" } + result[:node] = nameary[1] + result[:authenticated] = true + end + + result + end end |