summaryrefslogtreecommitdiffstats
path: root/lib/puppet
diff options
context:
space:
mode:
Diffstat (limited to 'lib/puppet')
-rw-r--r--lib/puppet/indirector.rb4
-rw-r--r--lib/puppet/indirector/indirection.rb11
-rw-r--r--lib/puppet/indirector/rest.rb21
-rw-r--r--lib/puppet/network/http/api/v1.rb3
-rw-r--r--lib/puppet/network/http/handler.rb11
-rw-r--r--lib/puppet/network/rest_authconfig.rb12
-rwxr-xr-xlib/puppet/network/rights.rb24
7 files changed, 73 insertions, 13 deletions
diff --git a/lib/puppet/indirector.rb b/lib/puppet/indirector.rb
index 5b737578b..e6472f4d9 100644
--- a/lib/puppet/indirector.rb
+++ b/lib/puppet/indirector.rb
@@ -50,6 +50,10 @@ module Puppet::Indirector
indirection.find(*args)
end
+ def head(*args)
+ indirection.head(*args)
+ end
+
def destroy(*args)
indirection.destroy(*args)
end
diff --git a/lib/puppet/indirector/indirection.rb b/lib/puppet/indirector/indirection.rb
index 4341f7cb2..ec147ec69 100644
--- a/lib/puppet/indirector/indirection.rb
+++ b/lib/puppet/indirector/indirection.rb
@@ -198,6 +198,17 @@ class Puppet::Indirector::Indirection
nil
end
+ # Search for an instance in the appropriate terminus, and return a
+ # boolean indicating whether the instance was found.
+ def head(key, *args)
+ request = request(:head, key, *args)
+ terminus = prepare(request)
+
+ # Look in the cache first, then in the terminus. Force the result
+ # to be a boolean.
+ !!(find_in_cache(request) || terminus.head(request))
+ end
+
def find_in_cache(request)
# See if our instance is in the cache and up to date.
return nil unless cache? and ! request.ignore_cache? and cached = cache.find(request)
diff --git a/lib/puppet/indirector/rest.rb b/lib/puppet/indirector/rest.rb
index eb41ff3b1..e50dc68ae 100644
--- a/lib/puppet/indirector/rest.rb
+++ b/lib/puppet/indirector/rest.rb
@@ -53,11 +53,15 @@ class Puppet::Indirector::REST < Puppet::Indirector::Terminus
end
else
# Raise the http error if we didn't get a 'success' of some kind.
- message = "Error #{response.code} on SERVER: #{(response.body||'').empty? ? response.message : uncompress_body(response)}"
- raise Net::HTTPError.new(message, response)
+ raise convert_to_http_error(response)
end
end
+ def convert_to_http_error(response)
+ message = "Error #{response.code} on SERVER: #{(response.body||'').empty? ? response.message : uncompress_body(response)}"
+ Net::HTTPError.new(message, response)
+ end
+
# Provide appropriate headers.
def headers
add_accept_encoding({"Accept" => model.supported_formats.join(", ")})
@@ -73,6 +77,19 @@ class Puppet::Indirector::REST < Puppet::Indirector::Terminus
result
end
+ def head(request)
+ response = network(request).head(indirection2uri(request), headers)
+ case response.code
+ when "404"
+ return false
+ when /^2/
+ return true
+ else
+ # Raise the http error if we didn't get a 'success' of some kind.
+ raise convert_to_http_error(response)
+ end
+ end
+
def search(request)
unless result = deserialize(network(request).get(indirection2uri(request), headers), true)
return []
diff --git a/lib/puppet/network/http/api/v1.rb b/lib/puppet/network/http/api/v1.rb
index dd4612a14..8aa1f0ee1 100644
--- a/lib/puppet/network/http/api/v1.rb
+++ b/lib/puppet/network/http/api/v1.rb
@@ -13,6 +13,9 @@ module Puppet::Network::HTTP::API::V1
},
"DELETE" => {
:singular => :destroy
+ },
+ "HEAD" => {
+ :singular => :head
}
}
diff --git a/lib/puppet/network/http/handler.rb b/lib/puppet/network/http/handler.rb
index f22498b70..9e9356b2f 100644
--- a/lib/puppet/network/http/handler.rb
+++ b/lib/puppet/network/http/handler.rb
@@ -116,6 +116,17 @@ module Puppet::Network::HTTP::Handler
end
end
+ # Execute our head.
+ def do_head(indirection_request, request, response)
+ unless indirection_request.model.head(indirection_request.key, indirection_request.to_hash)
+ Puppet.info("Could not find #{indirection_request.indirection_name} for '#{indirection_request.key}'")
+ return do_exception(response, "Could not find #{indirection_request.indirection_name} #{indirection_request.key}", 404)
+ end
+
+ # No need to set a response because no response is expected from a
+ # HEAD request. All we need to do is not die.
+ end
+
# Execute our search.
def do_search(indirection_request, request, response)
result = indirection_request.model.search(indirection_request.key, indirection_request.to_hash)
diff --git a/lib/puppet/network/rest_authconfig.rb b/lib/puppet/network/rest_authconfig.rb
index 1704ea0c1..7a6147a82 100644
--- a/lib/puppet/network/rest_authconfig.rb
+++ b/lib/puppet/network/rest_authconfig.rb
@@ -38,13 +38,7 @@ module Puppet
# fail_on_deny could as well be called in the XMLRPC context
# with a ClientRequest.
- if authorization_failure_exception = @rights.is_forbidden_and_why?(
- build_uri(request),
- :node => request.node,
- :ip => request.ip,
- :method => request.method,
- :environment => request.environment,
- :authenticated => request.authenticated)
+ if authorization_failure_exception = @rights.is_request_forbidden_and_why?(request)
Puppet.warning("Denying access: #{authorization_failure_exception}")
raise authorization_failure_exception
end
@@ -90,9 +84,5 @@ module Puppet
end
@rights.restrict_authenticated(acl[:acl], acl[:authenticated]) unless acl[:authenticated].nil?
end
-
- def build_uri(request)
- "/#{request.indirection_name}/#{request.key}"
- end
end
end
diff --git a/lib/puppet/network/rights.rb b/lib/puppet/network/rights.rb
index b2146494c..00ee04f8d 100755
--- a/lib/puppet/network/rights.rb
+++ b/lib/puppet/network/rights.rb
@@ -29,6 +29,30 @@ class Rights
!is_forbidden_and_why?(name, :node => args[0], :ip => args[1])
end
+ def is_request_forbidden_and_why?(request)
+ methods_to_check = if request.method == :head
+ # :head is ok if either :find or :save is ok.
+ [:find, :save]
+ else
+ [request.method]
+ end
+ authorization_failure_exceptions = methods_to_check.map do |method|
+ is_forbidden_and_why?("/#{request.indirection_name}/#{request.key}",
+ :node => request.node,
+ :ip => request.ip,
+ :method => method,
+ :environment => request.environment,
+ :authenticated => request.authenticated)
+ end
+ if authorization_failure_exceptions.include? nil
+ # One of the methods we checked is ok, therefore this request is ok.
+ nil
+ else
+ # Just need to return any of the failure exceptions.
+ authorization_failure_exceptions.first
+ end
+ end
+
def is_forbidden_and_why?(name, args = {})
res = :nomatch
right = @rights.find do |acl|