Kea 2.5.8
ca_response_creator.cc
Go to the documentation of this file.
1// Copyright (C) 2017-2022 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <agent/ca_cfg_mgr.h>
11#include <agent/ca_controller.h>
12#include <agent/ca_process.h>
14#include <cc/data.h>
16#include <hooks/hooks_log.h>
17#include <hooks/hooks_manager.h>
19#include <http/response_json.h>
20#include <boost/pointer_cast.hpp>
21#include <iostream>
22
23using namespace isc::data;
24using namespace isc::hooks;
25using namespace isc::http;
26
27namespace {
28
30struct CtrlAgentHooks {
31 int hook_index_auth_;
32 int hook_index_response_;
33
35 CtrlAgentHooks() {
36 hook_index_auth_ = HooksManager::registerHook("auth");
37 hook_index_response_ = HooksManager::registerHook("response");
38 }
39};
40
41} // end of anonymous namespace.
42
43// Declare a Hooks object. As this is outside any function or method, it
44// will be instantiated (and the constructor run) when the module is loaded.
45// As a result, the hook indexes will be defined before any method in this
46// module is called.
47CtrlAgentHooks Hooks;
48
49namespace isc {
50namespace agent {
51
54 return (HttpRequestPtr(new PostHttpRequestJson()));
55}
56
60 const HttpStatusCode& status_code) const {
61 HttpResponsePtr response = createStockHttpResponseInternal(request, status_code);
62 response->finalize();
63 return (response);
64}
65
67CtrlAgentResponseCreator::
68createStockHttpResponseInternal(const HttpRequestPtr& request,
69 const HttpStatusCode& status_code) const {
70 // The request hasn't been finalized so the request object
71 // doesn't contain any information about the HTTP version number
72 // used. But, the context should have this data (assuming the
73 // HTTP version is parsed ok).
74 HttpVersion http_version(request->context()->http_version_major_,
75 request->context()->http_version_minor_);
76 // We only accept HTTP version 1.0 or 1.1. If other version number is found
77 // we fall back to HTTP/1.0.
78 if ((http_version < HttpVersion(1, 0)) || (HttpVersion(1, 1) < http_version)) {
79 http_version.major_ = 1;
80 http_version.minor_ = 0;
81 }
82 // This will generate the response holding JSON content.
83 HttpResponsePtr response(new HttpResponseJson(http_version, status_code));
84 return (response);
85}
86
88CtrlAgentResponseCreator::
89createDynamicHttpResponse(HttpRequestPtr request) {
90 // First check authentication.
91 HttpResponseJsonPtr http_response;
92
93 // Context will hold the server configuration.
95
96 // There is a hierarchy of the objects through which we need to pass to get
97 // the configuration context. We may simplify this at some point but since
98 // we're in the singleton we want to make sure that we're using most current
99 // configuration.
100 boost::shared_ptr<CtrlAgentController> controller =
101 boost::dynamic_pointer_cast<CtrlAgentController>(CtrlAgentController::instance());
102 if (controller) {
103 CtrlAgentProcessPtr process = controller->getCtrlAgentProcess();
104 if (process) {
105 CtrlAgentCfgMgrPtr cfgmgr = process->getCtrlAgentCfgMgr();
106 if (cfgmgr) {
107 ctx = cfgmgr->getCtrlAgentCfgContext();
108 if (ctx) {
109 const HttpAuthConfigPtr& auth = ctx->getAuthConfig();
110 if (auth) {
111 // Check authentication.
112 http_response = auth->checkAuth(*this, request);
113 }
114 }
115 }
116 }
117 }
118
119 // Callout point for "auth".
120 bool reset_handle = false;
121 if (HooksManager::calloutsPresent(Hooks.hook_index_auth_)) {
122 // Get callout handle.
123 CalloutHandlePtr callout_handle = request->getCalloutHandle();
124 ScopedCalloutHandleState callout_handle_state(callout_handle);
125
126 // Pass arguments.
127 callout_handle->setArgument("request", request);
128 callout_handle->setArgument("response", http_response);
129
130 // Call callouts.
131 HooksManager::callCallouts(Hooks.hook_index_auth_, *callout_handle);
132 callout_handle->getArgument("request", request);
133 callout_handle->getArgument("response", http_response);
134
135 // Status other than continue means 'please reset the handle'.
136 if (callout_handle->getStatus() != CalloutHandle::NEXT_STEP_CONTINUE) {
137 reset_handle = true;
138 }
139 }
140
141 // The basic HTTP authentication check or a callout failed and
142 // left a response.
143 if (http_response) {
144 return (http_response);
145 }
146
147 // Reset the handle when a hook asks for.
148 if (reset_handle) {
149 request->resetCalloutHandle();
150 }
151
152 // The request is always non-null, because this is verified by the
153 // createHttpResponse method. Let's try to convert it to the
154 // PostHttpRequestJson type as this is the type generated by the
155 // createNewHttpRequest. If the conversion result is null it means that
156 // the caller did not use createNewHttpRequest method to create this
157 // instance. This is considered an error in the server logic.
158 PostHttpRequestJsonPtr request_json =
159 boost::dynamic_pointer_cast<PostHttpRequestJson>(request);
160 if (!request_json) {
161 // Notify the client that we have a problem with our server.
162 return (createStockHttpResponse(request, HttpStatusCode::INTERNAL_SERVER_ERROR));
163 }
164
165 // We have already checked that the request is finalized so the call
166 // to getBodyAsJson must not trigger an exception.
167 ConstElementPtr command = request_json->getBodyAsJson();
168
169 // Process command doesn't generate exceptions but can possibly return
170 // null response, if the handler is not implemented properly. This is
171 // again an internal server issue.
173 if (!response) {
174 // Notify the client that we have a problem with our server.
175 return (createStockHttpResponse(request, HttpStatusCode::INTERNAL_SERVER_ERROR));
176 }
177 // The response is ok, so let's create new HTTP response with the status OK.
178 http_response = boost::dynamic_pointer_cast<
179 HttpResponseJson>(createStockHttpResponseInternal(request, HttpStatusCode::OK));
180 http_response->setBodyAsJson(response);
181 http_response->finalize();
182
183 // Callout point for "response".
184 if (HooksManager::calloutsPresent(Hooks.hook_index_response_)) {
185 // Get callout handle.
186 CalloutHandlePtr callout_handle = request->getCalloutHandle();
187 ScopedCalloutHandleState callout_handle_state(callout_handle);
188
189 // Pass arguments.
190 callout_handle->setArgument("request", request);
191 callout_handle->setArgument("response", http_response);
192
193 // Call callouts.
194 HooksManager::callCallouts(Hooks.hook_index_response_,
195 *callout_handle);
196 callout_handle->getArgument("response", http_response);
197
198 // Ignore status as the HTTP response is used instead.
199 }
200
201 return (http_response);
202}
203
204} // end of namespace isc::agent
205} // end of namespace isc
CtrlAgentHooks Hooks
static CtrlAgentCommandMgr & instance()
Returns sole instance of the Command Manager.
virtual isc::data::ConstElementPtr processCommand(const isc::data::ConstElementPtr &cmd)
Triggers command processing.
static process::DControllerBasePtr & instance()
Static singleton instance method.
virtual http::HttpResponsePtr createStockHttpResponse(const http::HttpRequestPtr &request, const http::HttpStatusCode &status_code) const
Creates stock HTTP response.
virtual http::HttpRequestPtr createNewHttpRequest() const
Create a new request.
@ NEXT_STEP_CONTINUE
continue normally
static int registerHook(const std::string &name)
Register Hook.
static bool calloutsPresent(int index)
Are callouts present?
static void callCallouts(int index, CalloutHandle &handle)
Calls the callouts for a given hook.
Wrapper class around callout handle which automatically resets handle's state.
Represents HTTP response with JSON content.
Definition: response_json.h:34
void setBodyAsJson(const data::ConstElementPtr &json_body)
Generates JSON content from the data structures represented as data::ConstElementPtr.
Represents HTTP POST request with JSON body.
boost::shared_ptr< CtrlAgentCfgContext > CtrlAgentCfgContextPtr
Pointer to a configuration context.
Definition: ca_cfg_mgr.h:23
boost::shared_ptr< CtrlAgentProcess > CtrlAgentProcessPtr
Defines a shared pointer to CtrlAgentProcess.
Definition: ca_process.h:150
boost::shared_ptr< CtrlAgentCfgMgr > CtrlAgentCfgMgrPtr
Defines a shared pointer to CtrlAgentCfgMgr.
Definition: ca_cfg_mgr.h:311
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:29
boost::shared_ptr< CalloutHandle > CalloutHandlePtr
A shared pointer to a CalloutHandle object.
HttpStatusCode
HTTP status codes (cf RFC 2068)
Definition: response.h:30
boost::shared_ptr< PostHttpRequestJson > PostHttpRequestJsonPtr
Pointer to PostHttpRequestJson.
boost::shared_ptr< HttpAuthConfig > HttpAuthConfigPtr
Type of shared pointers to HTTP authentication configuration.
Definition: auth_config.h:97
boost::shared_ptr< HttpResponseJson > HttpResponseJsonPtr
Pointer to the HttpResponseJson object.
Definition: response_json.h:27
boost::shared_ptr< HttpResponse > HttpResponsePtr
Pointer to the HttpResponse object.
Definition: response.h:81
boost::shared_ptr< HttpRequest > HttpRequestPtr
Pointer to the HttpRequest object.
Definition: request.h:30
Defines the logger used by the top-level component of kea-lfc.
HTTP protocol version.
Definition: http_types.h:14