1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 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 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
|
/*
Copyright (C) 2021 The Falco Authors.
Falco is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
Falco is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Falco. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <set>
#include <list>
#include <map>
#include <memory>
#include <string>
#include <vector>
/*
* Operators to compare events
*/
enum cmpop {
CO_NONE = 0,
CO_EQ = 1,
CO_NE = 2,
CO_LT = 3,
CO_LE = 4,
CO_GT = 5,
CO_GE = 6,
CO_CONTAINS = 7,
CO_IN = 8,
CO_EXISTS = 9,
CO_ICONTAINS = 10,
CO_STARTSWITH = 11,
CO_GLOB = 12,
CO_PMATCH = 13,
CO_ENDSWITH = 14,
CO_INTERSECTS = 15,
};
enum boolop
{
BO_NONE = 0,
BO_NOT = 1,
BO_OR = 2,
BO_AND = 4,
// obtained by bitwise OR'ing with one of above ops
BO_ORNOT = 3,
BO_ANDNOT = 5,
};
enum evt_src
{
ESRC_NONE = 0,
ESRC_SINSP = 1,
ESRC_K8S_AUDIT = 2,
ESRC_MAX = 3,
};
class gen_event
{
public:
gen_event();
virtual ~gen_event();
/*!
\brief Set an opaque "check id", corresponding to the id of the last filtercheck that matched this event.
*/
void set_check_id(int32_t id);
/*!
\brief Get the opaque "check id" (-1 if not set).
*/
int32_t get_check_id() const;
// Every event must expose a timestamp
virtual uint64_t get_ts() const = 0;
/*!
\brief Get the source of the event.
*/
virtual uint16_t get_source() const = 0;
/*!
\brief Get the type of the event.
*/
virtual uint16_t get_type() const = 0;
private:
int32_t m_check_id = 0;
};
class gen_event_filter_check
{
public:
gen_event_filter_check();
virtual ~gen_event_filter_check();
boolop m_boolop;
cmpop m_cmpop;
virtual int32_t parse_field_name(const char* str, bool alloc_state, bool needed_for_filtering) = 0;
virtual void add_filter_value(const char* str, uint32_t len, uint32_t i = 0 ) = 0;
virtual bool compare(gen_event *evt) = 0;
virtual uint8_t* extract(gen_event *evt, uint32_t* len, bool sanitize_strings = true) = 0;
//
// Configure numeric id to be set on events that match this filter
//
void set_check_id(int32_t id);
virtual int32_t get_check_id();
// Return all event types used by this filtercheck. It's used in
// programs like falco to speed up rule evaluation.
virtual const std::set<uint16_t> &evttypes();
// Return all possible event types. Used for "not" operators
// where a set of events must be inverted.
virtual const std::set<uint16_t> &possible_evttypes();
static std::set<uint16_t> s_default_evttypes;
private:
int32_t m_check_id = 0;
};
///////////////////////////////////////////////////////////////////////////////
// Filter expression class
// A filter expression contains multiple filters connected by boolean expressions,
// e.g. "check or check", "check and check and check", "not check"
///////////////////////////////////////////////////////////////////////////////
class gen_event_filter_expression : public gen_event_filter_check
{
public:
gen_event_filter_expression();
virtual ~gen_event_filter_expression();
//
// The following methods are part of the filter check interface but are irrelevant
// for this class, because they are used only for the leaves of the filtering tree.
//
int32_t parse_field_name(const char* str, bool alloc_state, bool needed_for_filtering)
{
return 0;
}
void add_filter_value(const char* str, uint32_t len, uint32_t i = 0 )
{
return;
}
void add_check(gen_event_filter_check* chk);
bool compare(gen_event *evt);
uint8_t* extract(gen_event *evt, uint32_t* len, bool sanitize_strings = true);
//
// An expression is consistent if all its checks are of the same type (or/and).
//
// This method returns the expression operator (BO_AND/BO_OR/BO_NONE) if the
// expression is consistent. It returns -1 if the expression is not consistent.
//
int32_t get_expr_boolop();
// Return all event types used by this expression. It's used in
// programs like falco to speed up rule evaluation.
const std::set<uint16_t> &evttypes() override;
// An expression does not directly have a set of possible
// event types, but it can determine them from the m_checks
// vector.
const std::set<uint16_t> &possible_evttypes() override;
gen_event_filter_expression* m_parent;
std::vector<gen_event_filter_check*> m_checks;
private:
std::set<uint16_t> m_expr_event_types;
std::set<uint16_t> m_expr_possible_evttypes;
// Return the "inverse" of the provided set of event types, using the
// provided full possible set of event types as a hint.
std::set<uint16_t> inverse(const std::set<uint16_t> &evttypes);
// Given a boolean op and a set of event types from a
// filtercheck in the expression, update m_expr_event_types appropriately.
void combine_evttypes(boolop op, const std::set<uint16_t> &evttypes);
};
class gen_event_filter
{
public:
gen_event_filter();
virtual ~gen_event_filter();
/*!
\brief Applies the filter to the given event.
\param evt Pointer that needs to be filtered.
\return true if the event is accepted by the filter, false if it's rejected.
*/
bool run(gen_event *evt);
void push_expression(boolop op);
void pop_expression();
void add_check(gen_event_filter_check* chk);
// Return all event types used by this filter. It's used in
// programs like falco to speed up rule evaluation.
std::set<uint16_t> evttypes();
gen_event_filter_expression* m_filter;
protected:
gen_event_filter_expression* m_curexpr;
friend class sinsp_filter_compiler;
friend class sinsp_filter_optimizer;
};
class gen_event_filter_factory
{
public:
// A struct describing a single filtercheck field ("ka.user")
struct filter_field_info
{
// The name of the field
std::string name;
// A description of the field
std::string desc;
// The data type for the field
std::string data_type;
// A set of free-form tags for the field. Examples include:
// FILTER ONLY: for fields that can only be used in filters, not outputs.
// IDX_REQUIRED: for fields that can take an optional index
// EPF_TABLE_ONLY: for fields with the EPF_TABLE_ONLY (e.g. hidden) flag set
// etc
std::set<std::string> tags;
bool is_skippable();
};
// Describes a group of filtercheck fields ("ka")
class filter_fieldclass_info
{
public:
// The name of the group of fields
std::string name;
// A description for the fields
std::string desc;
// A short (< 10 words) description of the fields. Can be blank.
std::string shortdesc;
std::list<filter_field_info> fields;
// Print a terminal-friendly representation of this
// field class, including name, description, supported
// event sources, and the name and description of each field.
std::string as_string(bool verbose, const std::set<std::string>& event_sources = std::set<std::string>());
// Print a markdown representation of this
// field class, suitable for publication on the documentation
// website.
std::string as_markdown(const std::set<std::string>& event_sources = std::set<std::string>());
// How far to right-justify the name/description/etc block.
static uint32_t s_rightblock_start;
// How wide the overall output should be.
static uint32_t s_width;
private:
void wrapstring(const std::string &in, std::ostringstream &os);
};
gen_event_filter_factory() {};
virtual ~gen_event_filter_factory() {};
// Create a new filter
virtual gen_event_filter *new_filter() = 0;
// Create a new filtercheck
virtual gen_event_filter_check *new_filtercheck(const char *fldname) = 0;
// Return the set of fields supported by this factory
virtual std::list<filter_fieldclass_info> get_fields() = 0;
};
class gen_event_formatter
{
public:
enum output_format {
OF_NORMAL = 0,
OF_JSON = 1
};
gen_event_formatter();
virtual ~gen_event_formatter();
virtual void set_format(output_format of, const std::string &format) = 0;
// Format the output string with the configured format
virtual bool tostring(gen_event *evt, std::string &output) = 0;
// In some cases, it may be useful to format an output string
// with a custom format.
virtual bool tostring_withformat(gen_event *evt, std::string &output, output_format of) = 0;
// The map should map from field name, without the '%'
// (e.g. "proc.name"), to field value (e.g. "nginx")
virtual bool get_field_values(gen_event *evt, std::map<std::string, std::string> &fields) = 0;
virtual output_format get_output_format() = 0;
};
class gen_event_formatter_factory
{
public:
gen_event_formatter_factory();
virtual ~gen_event_formatter_factory();
// This should be called before any calls to
// create_formatter(), and changes the output format of new
// formatters.
virtual void set_output_format(gen_event_formatter::output_format of) = 0;
virtual std::shared_ptr<gen_event_formatter> create_formatter(const std::string &format) = 0;
};
|