mirror of
https://github.com/falcosecurity/falco.git
synced 2025-06-27 23:27:20 +00:00
cleanup(userspace/falco): improvements to the http output perf.
Moreover, add option to disable stdout echoing. Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
This commit is contained in:
parent
63ba15962b
commit
acaaa0b4ca
@ -365,6 +365,8 @@ http_output:
|
||||
client_cert: "/etc/ssl/certs/client.crt"
|
||||
# Path to the client key.
|
||||
client_key: "/etc/ssl/certs/client.key"
|
||||
# Whether to echo server answers to stdout
|
||||
echo: false
|
||||
|
||||
# [Stable] `program_output`
|
||||
#
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 40a98173303440ba05df11e3c607e27615429cab
|
||||
Subproject commit 3f52480618491a9232a1ec6a1f692fc04899c989
|
@ -195,6 +195,10 @@ void falco_configuration::load_yaml(const std::string& config_name, const yaml_h
|
||||
insecure = config.get_scalar<bool>("http_output.insecure", false);
|
||||
http_output.options["insecure"] = insecure? std::string("true") : std::string("false");
|
||||
|
||||
bool echo;
|
||||
echo = config.get_scalar<bool>("http_output.echo", false);
|
||||
http_output.options["echo"] = echo? std::string("true") : std::string("false");
|
||||
|
||||
std::string ca_cert;
|
||||
ca_cert = config.get_scalar<std::string>("http_output.ca_cert", "");
|
||||
http_output.options["ca_cert"] = ca_cert;
|
||||
|
@ -116,8 +116,16 @@ void falco_outputs::add_output(falco::outputs::config oc)
|
||||
throw falco_exception("Output not supported: " + oc.name);
|
||||
}
|
||||
|
||||
oo->init(oc, m_buffered, m_hostname, m_json_output);
|
||||
m_outputs.push_back(oo);
|
||||
std::string init_err;
|
||||
if (oo->init(oc, m_buffered, m_hostname, m_json_output, init_err))
|
||||
{
|
||||
m_outputs.push_back(oo);
|
||||
}
|
||||
else
|
||||
{
|
||||
falco_logger::log(LOG_ERR, "Failed to init output: " + init_err);
|
||||
delete(oo);
|
||||
}
|
||||
}
|
||||
|
||||
void falco_outputs::handle_event(gen_event *evt, std::string &rule, std::string &source,
|
||||
|
@ -62,14 +62,17 @@ struct message
|
||||
class abstract_output
|
||||
{
|
||||
public:
|
||||
virtual ~abstract_output() {}
|
||||
virtual ~abstract_output() = default;
|
||||
|
||||
void init(const config& oc, bool buffered, const std::string& hostname, bool json_output)
|
||||
virtual bool init(const config& oc, bool buffered, const std::string& hostname, bool json_output, std::string &err)
|
||||
{
|
||||
m_oc = oc;
|
||||
m_buffered = buffered;
|
||||
m_hostname = hostname;
|
||||
m_json_output = json_output;
|
||||
|
||||
err = "";
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return the output's name as per its configuration.
|
||||
|
@ -18,104 +18,105 @@ limitations under the License.
|
||||
#include "logger.h"
|
||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||
|
||||
#define CHECK_RES(fn) res = res == CURLE_OK ? fn : res
|
||||
|
||||
static size_t noop_write_callback(void *contents, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
// We don't want to echo anything. Just return size of bytes ignored
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
bool falco::outputs::output_http::init(const config& oc, bool buffered, const std::string& hostname, bool json_output, std::string &err)
|
||||
{
|
||||
falco::outputs::abstract_output::init(oc, buffered, hostname, json_output, err);
|
||||
|
||||
m_curl = nullptr;
|
||||
m_http_headers = nullptr;
|
||||
CURLcode res = CURLE_FAILED_INIT;
|
||||
|
||||
m_curl = curl_easy_init();
|
||||
if(!m_curl)
|
||||
{
|
||||
falco_logger::log(LOG_ERR, "libcurl failed to initialize the handle: " + std::string(curl_easy_strerror(res)));
|
||||
return false;
|
||||
}
|
||||
if(m_json_output)
|
||||
{
|
||||
m_http_headers = curl_slist_append(m_http_headers, "Content-Type: application/json");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_http_headers = curl_slist_append(m_http_headers, "Content-Type: text/plain");
|
||||
}
|
||||
res = curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, m_http_headers);
|
||||
|
||||
// if the URL is quoted the quotes should be removed to satisfy libcurl expected format
|
||||
std::string unquotedUrl = m_oc.options["url"];
|
||||
if (!unquotedUrl.empty() && (
|
||||
(unquotedUrl.front() == '\"' && unquotedUrl.back() == '\"') ||
|
||||
(unquotedUrl.front() == '\'' && unquotedUrl.back() == '\'')
|
||||
))
|
||||
{
|
||||
unquotedUrl = libsinsp::filter::unescape_str(unquotedUrl);
|
||||
}
|
||||
CHECK_RES(curl_easy_setopt(m_curl, CURLOPT_URL, unquotedUrl.c_str()));
|
||||
|
||||
CHECK_RES(curl_easy_setopt(m_curl, CURLOPT_USERAGENT, m_oc.options["user_agent"].c_str()));
|
||||
CHECK_RES(curl_easy_setopt(m_curl, CURLOPT_POSTFIELDSIZE, -1L));
|
||||
|
||||
if(m_oc.options["insecure"] == std::string("true"))
|
||||
{
|
||||
CHECK_RES(curl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYPEER, 0L));
|
||||
CHECK_RES(curl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYHOST, 0L));
|
||||
}
|
||||
|
||||
if(m_oc.options["mtls"] == std::string("true"))
|
||||
{
|
||||
CHECK_RES(curl_easy_setopt(m_curl, CURLOPT_SSLCERT, m_oc.options["client_cert"].c_str()));
|
||||
CHECK_RES(curl_easy_setopt(m_curl, CURLOPT_SSLKEY, m_oc.options["client_key"].c_str()));
|
||||
}
|
||||
|
||||
if (!m_oc.options["ca_cert"].empty())
|
||||
{
|
||||
CHECK_RES(curl_easy_setopt(m_curl, CURLOPT_CAINFO, m_oc.options["ca_cert"].c_str()));
|
||||
}
|
||||
else if(!m_oc.options["ca_bundle"].empty())
|
||||
{
|
||||
CHECK_RES(curl_easy_setopt(m_curl, CURLOPT_CAINFO, m_oc.options["ca_bundle"].c_str()));
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_RES(curl_easy_setopt(m_curl, CURLOPT_CAPATH, m_oc.options["ca_path"].c_str()));
|
||||
}
|
||||
|
||||
if(m_oc.options["echo"] == std::string("false"))
|
||||
{
|
||||
// If echo==true, libcurl defaults to fwrite to stdout, ie: echoing
|
||||
CHECK_RES(curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, noop_write_callback));
|
||||
}
|
||||
|
||||
if(res != CURLE_OK)
|
||||
{
|
||||
err = "libcurl error: " + std::string(curl_easy_strerror(res));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void falco::outputs::output_http::output(const message *msg)
|
||||
{
|
||||
CURL *curl = NULL;
|
||||
CURLcode res = CURLE_FAILED_INIT;
|
||||
struct curl_slist *slist1;
|
||||
slist1 = NULL;
|
||||
|
||||
curl = curl_easy_init();
|
||||
if(curl)
|
||||
CURLcode res = curl_easy_setopt(m_curl, CURLOPT_POSTFIELDS, msg->msg.c_str());
|
||||
CHECK_RES(curl_easy_perform(m_curl));
|
||||
if(res != CURLE_OK)
|
||||
{
|
||||
if (m_json_output)
|
||||
{
|
||||
slist1 = curl_slist_append(slist1, "Content-Type: application/json");
|
||||
} else {
|
||||
slist1 = curl_slist_append(slist1, "Content-Type: text/plain");
|
||||
}
|
||||
res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist1);
|
||||
|
||||
if(res == CURLE_OK)
|
||||
{
|
||||
// if the URL is quoted the quotes should be removed to satisfy libcurl expected format
|
||||
std::string unquotedUrl = m_oc.options["url"];
|
||||
if (!unquotedUrl.empty() && (
|
||||
(unquotedUrl.front() == '\"' && unquotedUrl.back() == '\"') ||
|
||||
(unquotedUrl.front() == '\'' && unquotedUrl.back() == '\'')
|
||||
))
|
||||
{
|
||||
unquotedUrl = libsinsp::filter::unescape_str(unquotedUrl);
|
||||
}
|
||||
res = curl_easy_setopt(curl, CURLOPT_URL, unquotedUrl.c_str());
|
||||
}
|
||||
|
||||
if(res == CURLE_OK)
|
||||
{
|
||||
res = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg->msg.c_str());
|
||||
}
|
||||
|
||||
if(res == CURLE_OK)
|
||||
{
|
||||
res = curl_easy_setopt(curl, CURLOPT_USERAGENT, m_oc.options["user_agent"].c_str());
|
||||
}
|
||||
|
||||
if(res == CURLE_OK)
|
||||
{
|
||||
res = curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1L);
|
||||
}
|
||||
|
||||
if(res == CURLE_OK)
|
||||
{
|
||||
if(m_oc.options["insecure"] == std::string("true"))
|
||||
{
|
||||
res = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
|
||||
if(res == CURLE_OK)
|
||||
{
|
||||
res = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(res == CURLE_OK)
|
||||
{
|
||||
if(m_oc.options["mtls"] == std::string("true"))
|
||||
{
|
||||
res = curl_easy_setopt(curl, CURLOPT_SSLCERT, m_oc.options["client_cert"].c_str());
|
||||
|
||||
if(res == CURLE_OK)
|
||||
{
|
||||
res = curl_easy_setopt(curl, CURLOPT_SSLKEY, m_oc.options["client_key"].c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(res == CURLE_OK)
|
||||
{
|
||||
if (!m_oc.options["ca_cert"].empty())
|
||||
{
|
||||
res = curl_easy_setopt(curl, CURLOPT_CAINFO, m_oc.options["ca_cert"].c_str());
|
||||
}else if(!m_oc.options["ca_bundle"].empty())
|
||||
{
|
||||
res = curl_easy_setopt(curl, CURLOPT_CAINFO, m_oc.options["ca_bundle"].c_str());
|
||||
}else{
|
||||
res = curl_easy_setopt(curl, CURLOPT_CAPATH, m_oc.options["ca_path"].c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if(res == CURLE_OK)
|
||||
{
|
||||
res = curl_easy_perform(curl);
|
||||
}
|
||||
|
||||
if(res != CURLE_OK)
|
||||
{
|
||||
falco_logger::log(LOG_ERR, "libcurl error: " + std::string(curl_easy_strerror(res)));
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
curl = NULL;
|
||||
curl_slist_free_all(slist1);
|
||||
slist1 = NULL;
|
||||
falco_logger::log(LOG_ERR, "libcurl failed to perform call: " + std::string(curl_easy_strerror(res)));
|
||||
}
|
||||
}
|
||||
|
||||
void falco::outputs::output_http::cleanup()
|
||||
{
|
||||
curl_easy_cleanup(m_curl);
|
||||
m_curl = nullptr;
|
||||
curl_slist_free_all(m_http_headers);
|
||||
m_http_headers = nullptr;
|
||||
}
|
||||
|
@ -25,7 +25,13 @@ namespace outputs
|
||||
|
||||
class output_http : public abstract_output
|
||||
{
|
||||
void output(const message *msg);
|
||||
bool init(const config& oc, bool buffered, const std::string& hostname, bool json_output, std::string &err) override;
|
||||
void output(const message *msg) override;
|
||||
void cleanup() override;
|
||||
|
||||
private:
|
||||
CURL *m_curl;
|
||||
struct curl_slist *m_http_headers;
|
||||
};
|
||||
|
||||
} // namespace outputs
|
||||
|
Loading…
Reference in New Issue
Block a user