Kea 2.7.5
ca_response_creator.cc
Go to the documentation of this file.
1// Copyright (C) 2017-2024 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_http_auth_;
32 int hook_index_http_response_;
33
35 CtrlAgentHooks() {
36 hook_index_http_auth_ = HooksManager::registerHook("http_auth");
37 hook_index_http_response_ = HooksManager::registerHook("http_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
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 "http_auth".
120 bool reset_handle = false;
121 if (HooksManager::calloutsPresent(Hooks.hook_index_http_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_http_auth_,
132 *callout_handle);
133 callout_handle->getArgument("request", request);
134 callout_handle->getArgument("response", http_response);
135
136 // Status other than continue means 'please reset the handle'.
137 if (callout_handle->getStatus() != CalloutHandle::NEXT_STEP_CONTINUE) {
138 reset_handle = true;
139 }
140 }
141
142 // The basic HTTP authentication check or a callout failed and
143 // left a response.
144 if (http_response) {
145 return (http_response);
146 }
147
148 // Reset the handle when a hook asks for.
149 if (reset_handle) {
150 request->resetCalloutHandle();
151 }
152
153 // The request is always non-null, because this is verified by the
154 // createHttpResponse method. Let's try to convert it to the
155 // PostHttpRequestJson type as this is the type generated by the
156 // createNewHttpRequest. If the conversion result is null it means that
157 // the caller did not use createNewHttpRequest method to create this
158 // instance. This is considered an error in the server logic.
159 PostHttpRequestJsonPtr request_json =
160 boost::dynamic_pointer_cast<PostHttpRequestJson>(request);
161 if (!request_json) {
162 // Notify the client that we have a problem with our server.
163 return (createStockHttpResponse(request, HttpStatusCode::INTERNAL_SERVER_ERROR));
164 }
165
166 // We have already checked that the request is finalized so the call
167 // to getBodyAsJson must not trigger an exception.
168 ConstElementPtr command = request_json->getBodyAsJson();
169
170 // Process command doesn't generate exceptions but can possibly return
171 // null response, if the handler is not implemented properly. This is
172 // again an internal server issue.
173 ConstElementPtr response = CtrlAgentCommandMgr::instance().processCommand(command);
174 if (!response) {
175 // Notify the client that we have a problem with our server.
176 return (createStockHttpResponse(request, HttpStatusCode::INTERNAL_SERVER_ERROR));
177 }
178 // The response is ok, so let's create new HTTP response with the status OK.
179 http_response = boost::dynamic_pointer_cast<
180 HttpResponseJson>(createStockHttpResponseInternal(request, HttpStatusCode::OK));
181 http_response->setBodyAsJson(response);
182 http_response->finalize();
183
184 // Callout point for "http_response".
185 if (HooksManager::calloutsPresent(Hooks.hook_index_http_response_)) {
186 // Get callout handle.
187 CalloutHandlePtr callout_handle = request->getCalloutHandle();
188 ScopedCalloutHandleState callout_handle_state(callout_handle);
189
190 // Pass arguments.
191 callout_handle->setArgument("request", request);
192 callout_handle->setArgument("response", http_response);
193
194 // Call callouts.
195 HooksManager::callCallouts(Hooks.hook_index_http_response_,
196 *callout_handle);
197 callout_handle->getArgument("response", http_response);
198
199 // Ignore status as the HTTP response is used instead.
200 }
201
202 return (http_response);
203}
204
205} // end of namespace isc::agent
206} // end of namespace isc
CtrlAgentHooks Hooks
static CtrlAgentCommandMgr & instance()
Returns sole instance of the Command Manager.
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.
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.
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