Class: Puppet::Network::HTTP::API::V1

Inherits:
Object
  • Object
show all
Includes:
Authorization
Defined in:
lib/puppet/network/http/api/v1.rb

Constant Summary collapse

METHOD_MAP =

How we map http methods and the indirection name in the URI to an indirection method.

{
  "GET" => {
    :plural => :search,
    :singular => :find
  },
  "POST" => {
    :singular => :find,
  },
  "PUT" => {
    :singular => :save
  },
  "DELETE" => {
    :singular => :destroy
  },
  "HEAD" => {
    :singular => :head
  }
}

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Authorization

#authconfig, #check_authorization

Class Method Details

.routesObject



27
28
29
# File 'lib/puppet/network/http/api/v1.rb', line 27

def self.routes
  Puppet::Network::HTTP::Route.path(/.*/).any(new)
end

Instance Method Details

#call(request, response) ⇒ Object

handle an HTTP request



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
# File 'lib/puppet/network/http/api/v1.rb', line 32

def call(request, response)
  indirection_name, method, key, params = uri2indirection(request.method, request.path, request.params)
  certificate = request.client_cert

  check_authorization(method, "/#{indirection_name}/#{key}", params)

  indirection = Puppet::Indirector::Indirection.instance(indirection_name.to_sym)
  raise ArgumentError, "Could not find indirection '#{indirection_name}'" unless indirection

  if !indirection.allow_remote_requests?
    # TODO: should we tell the user we found an indirection but it doesn't
    # allow remote requests, or just pretend there's no handler at all? what
    # are the security implications for the former?
    raise Puppet::Network::HTTP::Error::HTTPNotFoundError.new("No handler for #{indirection.name}", :NO_INDIRECTION_REMOTE_REQUESTS)
  end

  trusted = Puppet::Context::TrustedInformation.remote(params[:authenticated], params[:node], certificate)
  Puppet.override(:trusted_information => trusted) do
    send("do_#{method}", indirection, key, params, request, response)
  end
rescue Puppet::Network::HTTP::Error::HTTPError => e
  return do_http_control_exception(response, e)
rescue Exception => e
  return do_exception(response, e)
end

#uri2indirection(http_method, uri, params) ⇒ Object

Raises:

  • (ArgumentError)


58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/puppet/network/http/api/v1.rb', line 58

def uri2indirection(http_method, uri, params)
  environment, indirection, key = uri.split("/", 4)[1..-1] # the first field is always nil because of the leading slash

  raise ArgumentError, "The environment must be purely alphanumeric, not '#{environment}'" unless Puppet::Node::Environment.valid_name?(environment)
  raise ArgumentError, "The indirection name must be purely alphanumeric, not '#{indirection}'" unless indirection =~ /^\w+$/

  method = indirection_method(http_method, indirection)

  configured_environment = Puppet.lookup(:environments).get(environment)
  if configured_environment.nil?
    raise Puppet::Network::HTTP::Error::HTTPNotFoundError.new("Could not find environment '#{environment}'", Puppet::Network::HTTP::Issues::ENVIRONMENT_NOT_FOUND)
  else
    configured_environment = configured_environment.override_from_commandline(Puppet.settings)
    params[:environment] = configured_environment
  end

  params.delete(:bucket_path)

  raise ArgumentError, "No request key specified in #{uri}" if key == "" or key.nil?

  key = URI.unescape(key)

  [indirection, method, key, params]
end