Skip to content

Commit bc7394b

Browse files
LucaGuerrapoiana
authored andcommitted
new(falco): add json_include_message_property option
Signed-off-by: Luca Guerra <[email protected]>
1 parent 0f26e3c commit bc7394b

File tree

8 files changed

+99
-44
lines changed

8 files changed

+99
-44
lines changed

falco.yaml

+9
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,15 @@ json_output: false
518518
# case.
519519
json_include_output_property: true
520520

521+
# [Incubating] `json_include_message_property`
522+
#
523+
# When using JSON output in Falco, you have the option to include the formatted
524+
# rule output without timestamp or priority. For instance, if a rule specifies
525+
# an "output" property like "Opened process %proc.name" the "message" field will
526+
# only contain "Opened process bash" whereas the "output" field will contain more
527+
# information.
528+
json_include_message_property: false
529+
521530
# [Stable] `json_include_tags_property`
522531
#
523532
# When using JSON output in Falco, you have the option to include the "tags"

userspace/engine/formats.cpp

+72-18
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,14 @@ limitations under the License.
2222

2323
falco_formats::falco_formats(std::shared_ptr<const falco_engine> engine,
2424
bool json_include_output_property,
25-
bool json_include_tags_property)
25+
bool json_include_tags_property,
26+
bool json_include_message_property,
27+
bool time_format_iso_8601)
2628
: m_falco_engine(engine),
2729
m_json_include_output_property(json_include_output_property),
28-
m_json_include_tags_property(json_include_tags_property)
30+
m_json_include_tags_property(json_include_tags_property),
31+
m_json_include_message_property(json_include_message_property),
32+
m_time_format_iso_8601(time_format_iso_8601)
2933
{
3034
}
3135

@@ -37,21 +41,53 @@ std::string falco_formats::format_event(sinsp_evt *evt, const std::string &rule,
3741
const std::string &level, const std::string &format, const std::set<std::string> &tags,
3842
const std::string &hostname, const extra_output_field_t &extra_fields) const
3943
{
40-
std::string line;
44+
std::string prefix_format;
45+
std::string message_format = format;
46+
47+
if(m_time_format_iso_8601)
48+
{
49+
prefix_format = "*%evt.time.iso8601: ";
50+
}
51+
else
52+
{
53+
prefix_format = "*%evt.time: ";
54+
}
55+
prefix_format += level;
56+
57+
if(message_format[0] != '*')
58+
{
59+
message_format = "*" + message_format;
60+
}
4161

4262
std::shared_ptr<sinsp_evt_formatter> formatter;
4363

44-
formatter = m_falco_engine->create_formatter(source, format);
64+
auto prefix_formatter = m_falco_engine->create_formatter(source, prefix_format);
65+
auto message_formatter = m_falco_engine->create_formatter(source, message_format);
4566

46-
// Format the original output string, regardless of output format
47-
formatter->tostring_withformat(evt, line, sinsp_evt_formatter::OF_NORMAL);
67+
// The classic Falco output prefix with time and priority e.g. "13:53:31.726060287: Critical"
68+
std::string prefix;
69+
prefix_formatter->tostring_withformat(evt, prefix, sinsp_evt_formatter::OF_NORMAL);
70+
71+
// The formatted rule message/output
72+
std::string message;
73+
message_formatter->tostring_withformat(evt, message, sinsp_evt_formatter::OF_NORMAL);
74+
75+
// The complete Falco output, e.g. "13:53:31.726060287: Critical Some Event Description (proc_exe=bash)..."
76+
std::string output = prefix + " " + message;
4877

49-
if(formatter->get_output_format() == sinsp_evt_formatter::OF_JSON)
78+
if(message_formatter->get_output_format() == sinsp_evt_formatter::OF_NORMAL)
5079
{
51-
std::string json_fields;
80+
return output;
81+
}
82+
else if(message_formatter->get_output_format() == sinsp_evt_formatter::OF_JSON)
83+
{
84+
std::string json_fields_message;
85+
std::string json_fields_prefix;
5286

53-
// Format the event into a json object with all fields resolved
54-
formatter->tostring(evt, json_fields);
87+
// Resolve message fields
88+
message_formatter->tostring(evt, json_fields_message);
89+
// Resolve prefix (e.g. time) fields
90+
prefix_formatter->tostring(evt, json_fields_prefix);
5591

5692
// For JSON output, the formatter returned a json-as-text
5793
// object containing all the fields in the original format
@@ -78,16 +114,27 @@ std::string falco_formats::format_event(sinsp_evt *evt, const std::string &rule,
78114

79115
if(m_json_include_output_property)
80116
{
81-
// This is the filled-in output line.
82-
event["output"] = line;
117+
event["output"] = output;
83118
}
84119

85120
if(m_json_include_tags_property)
86121
{
87122
event["tags"] = tags;
88123
}
89124

90-
event["output_fields"] = nlohmann::json::parse(json_fields);
125+
if(m_json_include_message_property)
126+
{
127+
event["message"] = message;
128+
}
129+
130+
event["output_fields"] = nlohmann::json::parse(json_fields_message);
131+
132+
auto prefix_fields = nlohmann::json::parse(json_fields_prefix);
133+
if (prefix_fields.is_object()) {
134+
for (auto const& el : prefix_fields.items()) {
135+
event["output_fields"][el.key()] = el.value();
136+
}
137+
}
91138

92139
for (auto const& ef : extra_fields)
93140
{
@@ -105,8 +152,8 @@ std::string falco_formats::format_event(sinsp_evt *evt, const std::string &rule,
105152
if(ef.second.second) // raw field
106153
{
107154
std::string json_field_map;
108-
formatter = m_falco_engine->create_formatter(source, fformat);
109-
formatter->tostring_withformat(evt, json_field_map, sinsp_evt_formatter::OF_JSON);
155+
auto field_formatter = m_falco_engine->create_formatter(source, fformat);
156+
field_formatter->tostring_withformat(evt, json_field_map, sinsp_evt_formatter::OF_JSON);
110157
auto json_obj = nlohmann::json::parse(json_field_map);
111158
event["output_fields"][ef.first] = json_obj[ef.first];
112159
} else
@@ -115,10 +162,11 @@ std::string falco_formats::format_event(sinsp_evt *evt, const std::string &rule,
115162
}
116163
}
117164

118-
line = event.dump();
165+
return event.dump();
119166
}
120167

121-
return line;
168+
// should never get here until we only have OF_NORMAL and OF_JSON
169+
return "INVALID_OUTPUT_FORMAT";
122170
}
123171

124172
std::string falco_formats::format_string(sinsp_evt *evt, const std::string &format, const std::string &source) const
@@ -137,7 +185,13 @@ std::map<std::string, std::string> falco_formats::get_field_values(sinsp_evt *ev
137185
{
138186
std::shared_ptr<sinsp_evt_formatter> formatter;
139187

140-
formatter = m_falco_engine->create_formatter(source, format);
188+
std::string fformat = format;
189+
if(fformat[0] != '*')
190+
{
191+
fformat = "*" + fformat;
192+
}
193+
194+
formatter = m_falco_engine->create_formatter(source, fformat);
141195

142196
std::map<std::string, std::string> ret;
143197

userspace/engine/formats.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ class falco_formats
2626
public:
2727
falco_formats(std::shared_ptr<const falco_engine> engine,
2828
bool json_include_output_property,
29-
bool json_include_tags_property);
29+
bool json_include_tags_property,
30+
bool json_include_message_property,
31+
bool time_format_iso_8601);
3032
virtual ~falco_formats();
3133

3234
std::string format_event(sinsp_evt *evt, const std::string &rule, const std::string &source,
@@ -42,4 +44,6 @@ class falco_formats
4244
std::shared_ptr<const falco_engine> m_falco_engine;
4345
bool m_json_include_output_property;
4446
bool m_json_include_tags_property;
47+
bool m_json_include_message_property;
48+
bool m_time_format_iso_8601;
4549
};

userspace/falco/app/actions/init_outputs.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ falco::app::run_result falco::app::actions::init_outputs(falco::app::state& s)
6666
s.config->m_json_output,
6767
s.config->m_json_include_output_property,
6868
s.config->m_json_include_tags_property,
69+
s.config->m_json_include_message_property,
6970
s.config->m_output_timeout,
7071
s.config->m_buffered_outputs,
7172
s.config->m_outputs_queue_capacity,

userspace/falco/configuration.cpp

+3-1
Large diffs are not rendered by default.

userspace/falco/configuration.h

+1
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ class falco_configuration
149149
bool m_json_output;
150150
bool m_json_include_output_property;
151151
bool m_json_include_tags_property;
152+
bool m_json_include_message_property;
152153
std::string m_log_level;
153154
std::vector<falco::outputs::config> m_outputs;
154155

userspace/falco/falco_outputs.cpp

+7-24
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,16 @@ falco_outputs::falco_outputs(
4545
bool json_output,
4646
bool json_include_output_property,
4747
bool json_include_tags_property,
48+
bool json_include_message_property,
4849
uint32_t timeout,
4950
bool buffered,
5051
size_t outputs_queue_capacity,
5152
bool time_format_iso_8601,
5253
const std::string& hostname)
53-
: m_formats(std::make_unique<falco_formats>(engine, json_include_output_property, json_include_tags_property)),
54+
: m_formats(std::make_unique<falco_formats>(
55+
engine,
56+
json_include_output_property, json_include_tags_property, json_include_message_property,
57+
time_format_iso_8601)),
5458
m_buffered(buffered),
5559
m_json_output(json_output),
5660
m_time_format_iso_8601(time_format_iso_8601),
@@ -136,32 +140,11 @@ void falco_outputs::handle_event(sinsp_evt *evt, const std::string &rule, const
136140
cmsg.source = source;
137141
cmsg.rule = rule;
138142

139-
std::string sformat;
140-
if(m_time_format_iso_8601)
141-
{
142-
sformat = "*%evt.time.iso8601: ";
143-
}
144-
else
145-
{
146-
sformat = "*%evt.time: ";
147-
}
148-
sformat += falco_common::format_priority(priority);
149-
150-
// if format starts with a *, remove it, as we added our own prefix
151-
if(format[0] == '*')
152-
{
153-
sformat += " " + format.substr(1, format.length() - 1);
154-
}
155-
else
156-
{
157-
sformat += " " + format;
158-
}
159-
160143
cmsg.msg = m_formats->format_event(
161-
evt, rule, source, falco_common::format_priority(priority), sformat, tags, m_hostname, extra_fields
144+
evt, rule, source, falco_common::format_priority(priority), format, tags, m_hostname, extra_fields
162145
);
163146

164-
auto fields = m_formats->get_field_values(evt, source, sformat);
147+
auto fields = m_formats->get_field_values(evt, source, format);
165148
for (auto const& ef : extra_fields)
166149
{
167150
// when formatting for the control message we always want strings,

userspace/falco/falco_outputs.h

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class falco_outputs
4646
bool json_output,
4747
bool json_include_output_property,
4848
bool json_include_tags_property,
49+
bool json_include_message_property,
4950
uint32_t timeout,
5051
bool buffered,
5152
size_t outputs_queue_capacity,

0 commit comments

Comments
 (0)