Class: Puppet::Network::HTTP::API::IndirectedRoutes

Inherits:
Object
  • Object
show all
Defined in:
lib/puppet/network/http/api/indirected_routes.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
  }
}
IndirectionType =
Puppet::Network::HTTP::API::IndirectionType

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.routesObject



29
30
31
# File 'lib/puppet/network/http/api/indirected_routes.rb', line 29

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

Instance Method Details

#call(request, response) ⇒ Object

Handle an HTTP request. The request has already been authenticated prior to calling this method.



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/indirected_routes.rb', line 35

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

  unless 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}") % { indirection: indirection.name }, :NO_INDIRECTION_REMOTE_REQUESTS)
  end

  overrides = {
    trusted_information: Puppet::Context::TrustedInformation.remote(params[:authenticated], params[:node], certificate),
  }
  if params[:environment]
    overrides[:current_environment] = params[:environment]
  end

  Puppet.override(overrides) do
    send("do_#{method}", indirection, key, params, request, response)
  end
end

#uri2indirection(http_method, uri, params) ⇒ Object



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

def uri2indirection(http_method, uri, params)
  # the first field is always nil because of the leading slash,
  indirection_type, version, indirection_name, key = uri.split("/", 5)[1..]
  url_prefix = "/#{indirection_type}/#{version}"
  environment = params.delete(:environment)

  if indirection_name !~ /^\w+$/
    raise Puppet::Network::HTTP::Error::HTTPBadRequestError, _("The indirection name must be purely alphanumeric, not '%{indirection_name}'") % { indirection_name: indirection_name }
  end

  # this also depluralizes the indirection_name if it is a search
  method = indirection_method(http_method, indirection_name)

  # check whether this indirection matches the prefix and version in the
  # request
  if url_prefix != IndirectionType.url_prefix_for(indirection_name)
    raise Puppet::Network::HTTP::Error::HTTPBadRequestError, _("Indirection '%{indirection_name}' does not match url prefix '%{url_prefix}'") % { indirection_name: indirection_name, url_prefix: url_prefix }
  end

  indirection = Puppet::Indirector::Indirection.instance(indirection_name.to_sym)
  unless indirection
    raise Puppet::Network::HTTP::Error::HTTPNotFoundError.new(
      _("Could not find indirection '%{indirection_name}'") % { indirection_name: indirection_name },
      Puppet::Network::HTTP::Issues::HANDLER_NOT_FOUND
    )
  end

  unless environment
    raise Puppet::Network::HTTP::Error::HTTPBadRequestError, _("An environment parameter must be specified")
  end

  unless Puppet::Node::Environment.valid_name?(environment)
    raise Puppet::Network::HTTP::Error::HTTPBadRequestError, _("The environment must be purely alphanumeric, not '%{environment}'") % { environment: environment }
  end

  configured_environment = Puppet.lookup(:environments).get(environment)
  unless configured_environment.nil?
    configured_environment = configured_environment.override_from_commandline(Puppet.settings)
    params[:environment] = configured_environment
  end

  if configured_environment.nil? && indirection.terminus.require_environment?
    raise Puppet::Network::HTTP::Error::HTTPNotFoundError, _("Could not find environment '%{environment}'") % { environment: environment }
  end

  params.delete(:bucket_path)

  if key == "" or key.nil?
    raise Puppet::Network::HTTP::Error::HTTPBadRequestError, _("No request key specified in %{uri}") % { uri: uri }
  end

  [indirection, method, key, params]
end