Compare commits

..

1 Commits

Author SHA1 Message Date
Leonardo Grasso
0f0808dd8d build: add cmake module for spdlog
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-11-24 10:30:22 +01:00
29 changed files with 153 additions and 348 deletions

View File

@@ -94,6 +94,9 @@ set(CMD_MAKE make)
include(ExternalProject)
# spdlog
include(spdlog)
# jq
include(jq)

View File

@@ -11,8 +11,9 @@ Content in this document can be used to publically share about Falco.
### Logo
You can find the Falco logo in PNG and SVG in different colors in
the [CNCF's artwork repository](https://github.com/cncf/artwork/blob/master/examples/incubating.md#falco-logos).
There are 3 logos available for use in this directory. Use the primary logo unless required otherwise due to background issues, or printing.
The Falco logo is Apache 2 licensed and free to use in media and publication for the CNCF Falco project.
### Colors

BIN
brand/primary-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

1
brand/teal-logo.svg Normal file
View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 708.41 374.92"><defs><style>.cls-1{fill:#00b4c8;}</style></defs><title>Falco horizontal logo_teal2</title><g id="fqqZXT"><path class="cls-1" d="M204.69,154.4Q151.5,208,98,261.25a48.42,48.42,0,0,1-5.27,4.87c-2.55,1.89-5.34,2-7.65-.45s-1.51-5,.41-7.06c4.6-4.94,9.35-9.74,14.13-14.5q52.56-52.31,105.14-104.59c3.35-3.34,18.05,7.52,21.58,11.1"/><path class="cls-1" d="M215.06,171.36c-.15,2.14-1.54,3.55-2.93,4.94l-87.82,87.79c-2.75,2.74-6,5.42-9.46,1.68-3.15-3.39-.5-6.44,2.06-9q43.44-43.44,86.89-86.87c2.21-2.22,4.58-4.23,8-3A4.61,4.61,0,0,1,215.06,171.36Z"/><path class="cls-1" d="M70.93,71c2.42-.09,4.09,1.31,5.64,2.87q41.82,41.79,83.61,83.59c2.6,2.61,5,5.74,1.69,9s-6.41,1-9-1.66Q111,123,69.25,81.2c-2.09-2.1-3.72-4.39-2.45-7.53A4.34,4.34,0,0,1,70.93,71Z"/><path class="cls-1" d="M203.42,268c-5,1-8.9-1.34-12.45-5-6.35-6.61-12.87-13-19.41-19.46-3.85-3.8-4-7.41-.14-11.28,11.14-11.07,22.21-22.21,33.35-33.29,2.45-2.44,5.43-4.49,8.55-1.55,3.48,3.29,1.19,6.41-1.39,9-8.74,8.84-17.44,17.73-26.4,26.35-3.4,3.27-3.93,5.72-.19,9.06,4.22,3.78,8.13,7.91,12,12,2.54,2.68,5.35,4.25,9.18,4.11s8.28-.12,8.16,5.09c-.12,5-4.74,4.8-8.4,5.14A21,21,0,0,1,203.42,268Z"/><path class="cls-1" d="M148.7,178.36c-.75,3.49-2.68,5.6-6.43,4.36a13,13,0,0,1-4.74-3.31q-30.11-30-60.1-60a23.14,23.14,0,0,1-2.56-3c-1.72-2.42-1.88-5,.3-7.11s4.84-1.76,7,.26c3.65,3.42,7.17,7,10.71,10.53q25.65,25.64,51.28,51.3C146.12,173.37,148.49,175.13,148.7,178.36Z"/><path class="cls-1" d="M133.74,192.93a4.9,4.9,0,0,1-2.53,4.29,5.37,5.37,0,0,1-6.63-.95c-3.35-3.1-6.57-6.34-9.8-9.57q-14.34-14.3-28.61-28.63a34.27,34.27,0,0,1-4.17-5,4.57,4.57,0,0,1,.36-6,5,5,0,0,1,6-1.12,11.65,11.65,0,0,1,3.7,2.58q19.44,19.33,38.79,38.76C132.4,188.85,133.77,190.54,133.74,192.93Z"/></g><path class="cls-1" d="M413.15,190.86a25.57,25.57,0,0,0-10.35-6.63,46.78,46.78,0,0,0-16-2.37A83.35,83.35,0,0,0,372,183.12a75.16,75.16,0,0,0-10.58,2.53l2.37,15.48a53.47,53.47,0,0,1,9-2.21A72.44,72.44,0,0,1,385,198a22.61,22.61,0,0,1,8.13,1.26,13,13,0,0,1,5.22,3.56,13.23,13.23,0,0,1,2.76,5.29,24.6,24.6,0,0,1,.79,6.32v3.16a61.65,61.65,0,0,0-7.42-1.34,57.43,57.43,0,0,0-6.64-.4,61.45,61.45,0,0,0-13,1.35,32.26,32.26,0,0,0-11,4.42,22.7,22.7,0,0,0-7.51,8,24.09,24.09,0,0,0-2.76,12A28.39,28.39,0,0,0,356,254.05a21.6,21.6,0,0,0,6.79,8.22,28.56,28.56,0,0,0,10.51,4.58,60.24,60.24,0,0,0,13.58,1.42A137.25,137.25,0,0,0,407,266.93c5.94-.9,10.4-1.66,13.35-2.29V214.56a50.84,50.84,0,0,0-1.66-13.35A24.93,24.93,0,0,0,413.15,190.86Zm-11.3,61.3a71.4,71.4,0,0,1-13.43.94q-7.26,0-11.53-2.6t-4.26-9.4a10,10,0,0,1,1.57-5.77,10.67,10.67,0,0,1,4.19-3.55,20.18,20.18,0,0,1,5.85-1.74,43.43,43.43,0,0,1,6.39-.47,42.23,42.23,0,0,1,6.64.47,37,37,0,0,1,4.58,1Z"/><path class="cls-1" d="M461.38,248.44a9.27,9.27,0,0,1-2-4,26.17,26.17,0,0,1-.55-5.85V143.94l-19.12,3.16v95.1a40.74,40.74,0,0,0,1.35,11,17.57,17.57,0,0,0,4.66,8.06,21.71,21.71,0,0,0,8.92,5,52,52,0,0,0,14.14,1.89l2.69-15.8a29.78,29.78,0,0,1-6.24-1.34A8.76,8.76,0,0,1,461.38,248.44Z"/><path class="cls-1" d="M532.2,251.05a49.24,49.24,0,0,1-9.64.95q-13.11,0-18.64-7.19t-5.53-19.51q0-12.8,5.85-19.83t17.06-7a40.4,40.4,0,0,1,8.92.95,43.38,43.38,0,0,1,7.51,2.37l4.1-15.64a57.88,57.88,0,0,0-22.11-4.26,42.15,42.15,0,0,0-17.06,3.31,37.35,37.35,0,0,0-12.88,9.17,40.64,40.64,0,0,0-8.14,13.82,50.82,50.82,0,0,0-2.84,17.14,56.83,56.83,0,0,0,2.53,17.3A37.22,37.22,0,0,0,489,256.34a34.82,34.82,0,0,0,13,9,47.83,47.83,0,0,0,18.4,3.24,68.05,68.05,0,0,0,13.19-1.27,39.84,39.84,0,0,0,9.56-2.84l-2.69-15.8A45,45,0,0,1,532.2,251.05Z"/><path class="cls-1" d="M625.77,207.37a40.7,40.7,0,0,0-8.14-13.67,35.23,35.23,0,0,0-12.56-8.76,40.93,40.93,0,0,0-16-3.08,40.34,40.34,0,0,0-16,3.08,36.32,36.32,0,0,0-12.56,8.76,39.88,39.88,0,0,0-8.21,13.67,51.31,51.31,0,0,0-2.93,17.77A52,52,0,0,0,552.31,243a40.47,40.47,0,0,0,8.13,13.75,36.57,36.57,0,0,0,12.48,8.85A40.14,40.14,0,0,0,589,268.74a40.69,40.69,0,0,0,16.19-3.15,36.32,36.32,0,0,0,12.56-8.85A39.7,39.7,0,0,0,625.85,243a53.47,53.47,0,0,0,2.84-17.85A51.55,51.55,0,0,0,625.77,207.37Zm-22,37.52q-5.29,7.28-14.77,7.27t-14.77-7.27q-5.29-7.26-5.3-19.75,0-12.31,5.3-19.51T589,198.44q9.48,0,14.77,7.19t5.29,19.51Q609.1,237.62,603.81,244.89Z"/><path class="cls-1" d="M347.24,218h-47.8v50.57H279.65V150h75.89v15.88h-56.1v36.23h47.8Z"/></svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
brand/white-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,25 @@
#
# Copyright (C) 2020 The Falco Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
set(SPDLOG_PREFIX "${PROJECT_BINARY_DIR}/spdlog-prefix")
set(SPDLOG_INCLUDE_DIR "${SPDLOG_PREFIX}/src/spdlog/include")
message(STATUS "Using bundled spdlog in '${SPDLOG_INCLUDE_DIR}'")
ExternalProject_Add(
spdlog
URL "https://github.com/gabime/spdlog/archive/v1.8.1.tar.gz"
URL_HASH "SHA256=5197b3147cfcfaa67dd564db7b878e4a4b3d9f3443801722b3915cdeced656cb"
BUILD_COMMAND ""
INSTALL_COMMAND ""
)

View File

@@ -87,23 +87,6 @@ syscall_event_drops:
rate: .03333
max_burst: 10
# Falco continuously monitors outputs performance. When an output channel does not allow
# to deliver an alert within a given deadline, an error is reported indicating
# which output is blocking notifications.
# The timeout error will be reported to the log according to the above log_* settings.
# Note that the notification will not be discarded from the output queue; thus,
# output channels may indefinitely remain blocked.
# An output timeout error indeed indicate a misconfiguration issue or I/O problems
# that cannot be recovered by Falco and should be fixed by the user.
#
# The "output_timeout" value specifies the duration in milliseconds to wait before
# considering the deadline exceed.
#
# With a 2000ms default, the notification consumer can block the Falco output
# for up to 2 seconds without reaching the timeout.
output_timeout: 2000
# A throttling mechanism implemented as a token bucket limits the
# rate of falco notifications. This throttling is controlled by the following configuration
# options:

View File

@@ -3070,22 +3070,6 @@
priority: WARNING
tags: [process]
- list: run_as_root_image_list
items: []
- macro: user_known_run_as_root_container
condition: (container.image.repository in (run_as_root_image_list))
# The rule is disabled by default and should be enabled when non-root container policy has been applied.
# Note the rule will not work as expected when usernamespace is applied, e.g. userns-remap is enabled.
- rule: Container Run as Root User
desc: Detected container running as root user
condition: spawned_process and container and proc.vpid=1 and user.uid=0 and not user_known_run_as_root_container
enabled: false
output: Container launched with root user privilege (uid=%user.uid container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
priority: INFO
tags: [container, process]
# Application rules have moved to application_rules.yaml. Please look
# there if you want to enable them by adding to
# falco_rules.local.yaml.

View File

@@ -33,6 +33,7 @@ set(
"${PROJECT_SOURCE_DIR}/userspace/engine"
"${PROJECT_BINARY_DIR}/userspace/falco"
"${PROJECT_BINARY_DIR}/driver/src"
"${SPDLOG_INCLUDE_DIR}"
"${STRING_VIEW_LITE_INCLUDE}"
"${YAMLCPP_INCLUDE_DIR}"
"${CMAKE_CURRENT_BINARY_DIR}"
@@ -41,6 +42,7 @@ set(
set(
FALCO_DEPENDENCIES
spdlog
string-view-lite
libyaml
b64

View File

@@ -176,8 +176,6 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
falco_logger::set_level(m_log_level);
m_output_timeout = m_config->get_scalar<uint32_t>("output_timeout", 2000);
m_notifications_rate = m_config->get_scalar<uint32_t>("outputs", "rate", 1);
m_notifications_max_burst = m_config->get_scalar<uint32_t>("outputs", "max_burst", 1000);

View File

@@ -204,7 +204,6 @@ public:
bool m_buffered_outputs;
bool m_time_format_iso_8601;
uint32_t m_output_timeout;
bool m_grpc_enabled;
uint32_t m_grpc_threadiness;

View File

@@ -972,7 +972,6 @@ int falco_init(int argc, char **argv)
outputs->init(config.m_json_output,
config.m_json_include_output_property,
config.m_output_timeout,
config.m_notifications_rate, config.m_notifications_max_burst,
config.m_buffered_outputs,
config.m_time_format_iso_8601,

View File

@@ -24,7 +24,6 @@ limitations under the License.
#include "formats.h"
#include "logger.h"
#include "watchdog.h"
#include "outputs_file.h"
#include "outputs_program.h"
@@ -52,26 +51,18 @@ falco_outputs::~falco_outputs()
{
if(m_initialized)
{
this->stop_worker();
for(auto o : m_outputs)
for(auto it = m_outputs.cbegin(); it != m_outputs.cend(); ++it)
{
delete o;
(*it)->cleanup();
}
}
}
void falco_outputs::init(bool json_output,
bool json_include_output_property,
uint32_t timeout,
uint32_t rate, uint32_t max_burst, bool buffered,
bool time_format_iso_8601, std::string hostname)
bool json_include_output_property,
uint32_t rate, uint32_t max_burst, bool buffered,
bool time_format_iso_8601, string hostname)
{
// Cannot be initialized more than one time.
if(m_initialized)
{
throw falco_exception("falco_outputs already initialized");
}
m_json_output = json_output;
// Note that falco_formats is already initialized by the engine,
@@ -80,29 +71,17 @@ void falco_outputs::init(bool json_output,
falco_formats::s_json_output = json_output;
falco_formats::s_json_include_output_property = json_include_output_property;
m_timeout = std::chrono::milliseconds(timeout);
m_notifications_tb.init(rate, max_burst);
m_buffered = buffered;
m_time_format_iso_8601 = time_format_iso_8601;
m_hostname = hostname;
m_worker_thread = std::thread(&falco_outputs::worker, this);
m_initialized = true;
}
// This function has to be called after init() since some configuration settings
// need to be passed to the output plugins. Then, although the worker has started,
// the worker is still on hold, waiting for a message.
// Thus it is still safe to call add_output() before any message has been enqueued.
void falco_outputs::add_output(falco::outputs::config oc)
{
if(!m_initialized)
{
throw falco_exception("cannot add output: falco_outputs not initialized yet");
}
falco::outputs::abstract_output *oo;
@@ -150,12 +129,6 @@ void falco_outputs::handle_event(gen_event *evt, string &rule, string &source,
return;
}
falco_outputs::ctrl_msg cmsg = {};
cmsg.ts = evt->get_ts();
cmsg.priority = priority;
cmsg.source = source;
cmsg.rule = rule;
string sformat;
if(source == "syscall")
{
@@ -190,38 +163,35 @@ void falco_outputs::handle_event(gen_event *evt, string &rule, string &source,
sformat += " " + format;
}
cmsg.msg = falco_formats::format_event(evt, rule, source, falco_common::priority_names[priority], sformat);
cmsg.fields = falco_formats::resolve_tokens(evt, source, sformat);
string msg;
msg = falco_formats::format_event(evt, rule, source, falco_common::priority_names[priority], sformat);
cmsg.type = ctrl_msg_type::CTRL_MSG_OUTPUT;
m_queue.push(cmsg);
for(auto it = m_outputs.cbegin(); it != m_outputs.cend(); ++it)
{
(*it)->output_event(evt, rule, source, priority, sformat, msg);
}
}
void falco_outputs::handle_msg(uint64_t ts,
void falco_outputs::handle_msg(uint64_t now,
falco_common::priority_type priority,
std::string &msg,
std::string &rule,
std::map<std::string, std::string> &output_fields)
{
falco_outputs::ctrl_msg cmsg = {};
cmsg.ts = ts;
cmsg.priority = priority;
cmsg.source = "internal";
cmsg.rule = rule;
cmsg.fields = output_fields;
std::string full_msg;
if(m_json_output)
{
nlohmann::json jmsg;
// Convert the time-as-nanoseconds to a more json-friendly ISO8601.
time_t evttime = ts / 1000000000;
time_t evttime = now / 1000000000;
char time_sec[20]; // sizeof "YYYY-MM-DDTHH:MM:SS"
char time_ns[12]; // sizeof ".sssssssssZ"
string iso8601evttime;
strftime(time_sec, sizeof(time_sec), "%FT%T", gmtime(&evttime));
snprintf(time_ns, sizeof(time_ns), ".%09luZ", ts % 1000000000);
snprintf(time_ns, sizeof(time_ns), ".%09luZ", now % 1000000000);
iso8601evttime = time_sec;
iso8601evttime += time_ns;
@@ -231,15 +201,15 @@ void falco_outputs::handle_msg(uint64_t ts,
jmsg["time"] = iso8601evttime;
jmsg["output_fields"] = output_fields;
cmsg.msg = jmsg.dump();
full_msg = jmsg.dump();
}
else
{
std::string timestr;
bool first = true;
sinsp_utils::ts_to_string(ts, &timestr, false, true);
cmsg.msg = timestr + ": " + falco_common::priority_names[priority] + " " + msg + " (";
sinsp_utils::ts_to_string(now, &timestr, false, true);
full_msg = timestr + ": " + falco_common::priority_names[priority] + " " + msg + " (";
for(auto &pair : output_fields)
{
if(first)
@@ -248,95 +218,23 @@ void falco_outputs::handle_msg(uint64_t ts,
}
else
{
cmsg.msg += " ";
full_msg += " ";
}
cmsg.msg += pair.first + "=" + pair.second;
full_msg += pair.first + "=" + pair.second;
}
cmsg.msg += ")";
full_msg += ")";
}
cmsg.type = ctrl_msg_type::CTRL_MSG_OUTPUT;
m_queue.push(cmsg);
}
void falco_outputs::cleanup_outputs()
{
this->push(falco_outputs::ctrl_msg_type::CTRL_MSG_CLEANUP);
for(auto it = m_outputs.cbegin(); it != m_outputs.cend(); ++it)
{
(*it)->output_msg(priority, full_msg);
}
}
void falco_outputs::reopen_outputs()
{
this->push(falco_outputs::ctrl_msg_type::CTRL_MSG_REOPEN);
}
void falco_outputs::stop_worker()
{
watchdog<void *> wd;
wd.start([&](void *) -> void {
falco_logger::log(LOG_NOTICE, "output channels still blocked, discarding all remaining notifications\n");
m_queue.clear();
this->push(falco_outputs::ctrl_msg_type::CTRL_MSG_STOP);
});
wd.set_timeout(m_timeout, nullptr);
this->push(falco_outputs::ctrl_msg_type::CTRL_MSG_STOP);
if(m_worker_thread.joinable())
for(auto it = m_outputs.cbegin(); it != m_outputs.cend(); ++it)
{
m_worker_thread.join();
(*it)->reopen();
}
}
inline void falco_outputs::push(ctrl_msg_type cmt)
{
falco_outputs::ctrl_msg cmsg = {};
cmsg.type = cmt;
m_queue.push(cmsg);
}
// todo(leogr,leodido): this function is not supposed to throw exceptions, and with "noexcept",
// the program is terminated if that occurs. Although that's the wanted behavior,
// we still need to improve the error reporting since some inner functions can throw exceptions.
void falco_outputs::worker() noexcept
{
watchdog<std::string> wd;
wd.start([&](std::string payload) -> void {
falco_logger::log(LOG_CRIT, "\"" + payload + "\" output timeout, all output channels are blocked\n");
});
auto timeout = m_timeout;
falco_outputs::ctrl_msg cmsg;
do
{
// Block until a message becomes available.
m_queue.pop(cmsg);
for(const auto o : m_outputs)
{
wd.set_timeout(timeout, o->get_name());
try
{
switch(cmsg.type)
{
case ctrl_msg_type::CTRL_MSG_OUTPUT:
o->output(&cmsg);
break;
case ctrl_msg_type::CTRL_MSG_CLEANUP:
case ctrl_msg_type::CTRL_MSG_STOP:
o->cleanup();
break;
case ctrl_msg_type::CTRL_MSG_REOPEN:
o->reopen();
break;
default:
falco_logger::log(LOG_DEBUG, "Outputs worker received an unknown message type\n");
}
}
catch(const exception &e)
{
falco_logger::log(LOG_ERR, o->get_name() + ": " + string(e.what()) + "\n");
}
}
wd.cancel_timeout();
} while(cmsg.type != ctrl_msg_type::CTRL_MSG_STOP);
}

View File

@@ -25,7 +25,6 @@ limitations under the License.
#include "token_bucket.h"
#include "falco_engine.h"
#include "outputs.h"
#include "tbb/concurrent_queue.h"
//
// This class acts as the primary interface between a program and the
@@ -40,25 +39,25 @@ public:
void init(bool json_output,
bool json_include_output_property,
uint32_t timeout,
uint32_t rate, uint32_t max_burst, bool buffered,
bool time_format_iso_8601, std::string hostname);
void add_output(falco::outputs::config oc);
// Format then send the event to all configured outputs (`evt` is an event that has matched some rule).
//
// evt is an event that has matched some rule. Pass the event
// to all configured outputs.
//
void handle_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format);
// Format then send a generic message to all outputs. Not necessarily associated with any event.
// Send a generic message to all outputs. Not necessarily associated with any event.
void handle_msg(uint64_t now,
falco_common::priority_type priority,
std::string &msg,
std::string &rule,
std::map<std::string, std::string> &output_fields);
void cleanup_outputs();
void reopen_outputs();
private:
@@ -72,28 +71,5 @@ private:
bool m_buffered;
bool m_json_output;
bool m_time_format_iso_8601;
std::chrono::milliseconds m_timeout;
std::string m_hostname;
enum ctrl_msg_type
{
CTRL_MSG_STOP = 0,
CTRL_MSG_OUTPUT = 1,
CTRL_MSG_CLEANUP = 2,
CTRL_MSG_REOPEN = 3,
};
struct ctrl_msg : falco::outputs::message
{
ctrl_msg_type type;
};
typedef tbb::concurrent_bounded_queue<ctrl_msg> falco_outputs_cbq;
falco_outputs_cbq m_queue;
std::thread m_worker_thread;
inline void push(ctrl_msg_type cmt);
void worker() noexcept;
void stop_worker();
};

View File

@@ -37,21 +37,6 @@ struct config
std::map<std::string, std::string> options;
};
//
// The message to be outputted. It can either refer to:
// - an event that has matched some rule,
// - or a generic message (e.g., a drop alert).
//
struct message
{
uint64_t ts;
falco_common::priority_type priority;
std::string msg;
std::string rule;
std::string source;
map<std::string, std::string> fields;
};
//
// This class acts as the primary interface for implementing
// a Falco output class.
@@ -60,8 +45,6 @@ struct message
class abstract_output
{
public:
virtual ~abstract_output() {}
void init(config oc, bool buffered, std::string hostname)
{
m_oc = oc;
@@ -69,19 +52,15 @@ public:
m_hostname = hostname;
}
// Return the output's name as per its configuration.
const std::string get_name() const
{
return m_oc.name;
}
// Output an event that has matched some rule.
virtual void output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg) = 0;
// Output a message.
virtual void output(const message *msg) = 0;
// Output a generic message. Not necessarily associated with any event.
virtual void output_msg(falco_common::priority_type priority, std::string &msg) = 0;
// Possibly close the output and open it again.
virtual void reopen() {}
// Possibly flush the output.
virtual void cleanup() {}
protected:

View File

@@ -31,10 +31,16 @@ void falco::outputs::output_file::open_file()
}
}
void falco::outputs::output_file::output(const message *msg)
void falco::outputs::output_file::output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg)
{
output_msg(priority, msg);
}
void falco::outputs::output_file::output_msg(falco_common::priority_type priority, std::string &msg)
{
open_file();
m_outfile << msg->msg + "\n";
m_outfile << msg + "\n";
if(m_oc.options["keep_alive"] != "true")
{

View File

@@ -27,7 +27,10 @@ namespace outputs
class output_file : public abstract_output
{
void output(const message *msg);
void output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg);
void output_msg(falco_common::priority_type priority, std::string &msg);
void cleanup();

View File

@@ -21,41 +21,44 @@ limitations under the License.
#include "formats.h"
#include "banned.h" // This raises a compilation error when certain functions are used
void falco::outputs::output_grpc::output(const message *msg)
void falco::outputs::output_grpc::output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format,
std::string &msg)
{
falco::outputs::response grpc_res;
// time
auto timestamp = grpc_res.mutable_time();
*timestamp = google::protobuf::util::TimeUtil::NanosecondsToTimestamp(msg->ts);
*timestamp = google::protobuf::util::TimeUtil::NanosecondsToTimestamp(evt->get_ts());
// rule
auto r = grpc_res.mutable_rule();
*r = msg->rule;
*r = rule;
// source
falco::schema::source s = falco::schema::source::SYSCALL;
if(!falco::schema::source_Parse(msg->source, &s))
if(!falco::schema::source_Parse(source, &s))
{
throw falco_exception("Unknown source passed to output_grpc::output()");
throw falco_exception("Unknown source passed to output_grpc::output_event()");
}
grpc_res.set_source(s);
// priority
falco::schema::priority p = falco::schema::priority::EMERGENCY;
if(!falco::schema::priority_Parse(falco_common::priority_names[msg->priority], &p))
if(!falco::schema::priority_Parse(falco_common::priority_names[priority], &p))
{
throw falco_exception("Unknown priority passed to output_grpc::output()");
throw falco_exception("Unknown priority passed to output_grpc::output_event()");
}
grpc_res.set_priority(p);
// output
auto output = grpc_res.mutable_output();
*output = msg->msg;
*output = msg;
// output fields
auto &fields = *grpc_res.mutable_output_fields();
for(const auto &kv : msg->fields)
auto resolvedTkns = falco_formats::resolve_tokens(evt, source, format);
for(const auto &kv : resolvedTkns)
{
fields[kv.first] = kv.second;
}
@@ -65,4 +68,9 @@ void falco::outputs::output_grpc::output(const message *msg)
*host = m_hostname;
falco::grpc::queue::get().push(grpc_res);
}
void falco::outputs::output_grpc::output_msg(falco_common::priority_type priority, std::string &msg)
{
// todo(fntlnz, leodido, leogr) > gRPC does not support subscribing to dropped events yet
}

View File

@@ -25,7 +25,10 @@ namespace outputs
class output_grpc : public abstract_output
{
void output(const message *msg);
void output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg);
void output_msg(falco_common::priority_type priority, std::string &msg);
};
} // namespace outputs

View File

@@ -18,7 +18,13 @@ limitations under the License.
#include "logger.h"
#include "banned.h" // This raises a compilation error when certain functions are used
void falco::outputs::output_http::output(const message *msg)
void falco::outputs::output_http::output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg)
{
output_msg(priority, msg);
}
void falco::outputs::output_http::output_msg(falco_common::priority_type priority, std::string &msg)
{
CURL *curl = NULL;
CURLcode res = CURLE_FAILED_INIT;
@@ -31,7 +37,7 @@ void falco::outputs::output_http::output(const message *msg)
slist1 = curl_slist_append(slist1, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist1);
curl_easy_setopt(curl, CURLOPT_URL, m_oc.options["url"].c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg->msg.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1L);
res = curl_easy_perform(curl);

View File

@@ -25,7 +25,10 @@ namespace outputs
class output_http : public abstract_output
{
void output(const message *msg);
void output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg);
void output_msg(falco_common::priority_type priority, std::string &msg);
};
} // namespace outputs

View File

@@ -31,11 +31,17 @@ void falco::outputs::output_program::open_pfile()
}
}
void falco::outputs::output_program::output(const message *msg)
void falco::outputs::output_program::output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg)
{
output_msg(priority, msg);
}
void falco::outputs::output_program::output_msg(falco_common::priority_type priority, std::string &msg)
{
open_pfile();
fprintf(m_pfile, "%s\n", msg->msg.c_str());
fprintf(m_pfile, "%s\n", msg.c_str());
if(m_oc.options["keep_alive"] != "true")
{

View File

@@ -25,7 +25,10 @@ namespace outputs
class output_program : public abstract_output
{
void output(const message *msg);
void output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg);
void output_msg(falco_common::priority_type priority, std::string &msg);
void cleanup();

View File

@@ -18,10 +18,16 @@ limitations under the License.
#include <iostream>
#include "banned.h" // This raises a compilation error when certain functions are used
void falco::outputs::output_stdout::output(const message *msg)
void falco::outputs::output_stdout::output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg)
{
output_msg(priority, msg);
}
void falco::outputs::output_stdout::output_msg(falco_common::priority_type priority, std::string &msg)
{
//
// By default, the stdout stream is fully buffered or line buffered
// By default, the stdout stream is fully buffered or line buffered
// (if the stream can be determined to refer to an interactive device, e.g. in a TTY).
// Just enable automatic flushing when unbuffered output is desired.
// Note that it is set every time since other writings to the stdout can disable it.
@@ -30,7 +36,7 @@ void falco::outputs::output_stdout::output(const message *msg)
{
std::cout << std::unitbuf;
}
std::cout << msg->msg + "\n";
std::cout << msg + "\n";
}
void falco::outputs::output_stdout::cleanup()

View File

@@ -25,7 +25,10 @@ namespace outputs
class output_stdout : public abstract_output
{
void output(const message *msg);
void output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg);
void output_msg(falco_common::priority_type priority, std::string &msg);
void cleanup();
};

View File

@@ -18,8 +18,14 @@ limitations under the License.
#include <syslog.h>
#include "banned.h" // This raises a compilation error when certain functions are used
void falco::outputs::output_syslog::output(const message *msg)
void falco::outputs::output_syslog::output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg)
{
output_msg(priority, msg);
}
void falco::outputs::output_syslog::output_msg(falco_common::priority_type priority, std::string &msg)
{
// Syslog output should not have any trailing newline
::syslog(msg->priority, "%s", msg->msg.c_str());
::syslog(priority, "%s", msg.c_str());
}

View File

@@ -25,7 +25,10 @@ namespace outputs
class output_syslog : public abstract_output
{
void output(const message *msg);
void output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg);
void output_msg(falco_common::priority_type priority, std::string &msg);
};
} // namespace outputs

View File

@@ -57,7 +57,4 @@ enum source {
k8s_audit = 1;
K8s_audit = 1;
K8S_audit = 1;
INTERNAL = 2;
internal = 2;
Internal = 2;
}

View File

@@ -1,96 +0,0 @@
/*
Copyright (C) 2020 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <chrono>
#include <thread>
#include <functional>
#include <atomic>
template<typename _T>
class watchdog
{
public:
watchdog():
m_timeout(nullptr),
m_is_running(false)
{
}
~watchdog()
{
stop();
}
void start(std::function<void(_T)> cb,
std::chrono::milliseconds resolution = std::chrono::milliseconds(100))
{
stop();
m_is_running.store(true, std::memory_order_release);
m_thread = std::thread([this, cb, resolution]() {
const auto no_deadline = time_point{};
timeout_data curr;
while(m_is_running.load(std::memory_order_acquire))
{
auto t = m_timeout.exchange(nullptr, std::memory_order_release);
if(t)
{
curr = *t;
delete t;
}
if(curr.deadline != no_deadline && curr.deadline < std::chrono::steady_clock::now())
{
cb(curr.payload);
curr.deadline = no_deadline;
}
std::this_thread::sleep_for(resolution);
}
});
}
void stop()
{
if(m_is_running.load(std::memory_order_acquire))
{
m_is_running.store(false, std::memory_order_release);
if(m_thread.joinable())
{
m_thread.join();
}
delete m_timeout.exchange(nullptr, std::memory_order_release);
}
}
inline void set_timeout(std::chrono::milliseconds timeout, _T payload) noexcept
{
delete m_timeout.exchange(new timeout_data{std::chrono::steady_clock::now() + timeout, payload}, std::memory_order_release);
}
inline void cancel_timeout() noexcept
{
delete m_timeout.exchange(new timeout_data, std::memory_order_release);
}
private:
typedef std::chrono::time_point<std::chrono::steady_clock> time_point;
struct timeout_data
{
time_point deadline;
_T payload;
};
std::atomic<timeout_data *> m_timeout;
std::atomic<bool> m_is_running;
std::thread m_thread;
};