Skip to content

Commit fecdcfc

Browse files
authored
Always serialize schemas when available (#2406)
1 parent 598b629 commit fecdcfc

File tree

15 files changed

+47
-39
lines changed

15 files changed

+47
-39
lines changed

appsec/src/extension/commands/client_init.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,21 @@ static dd_result _pack_command(
164164
mpack_start_map(w, 2);
165165

166166
dd_mpack_write_lstr(w, "enabled");
167-
mpack_write_bool(w, get_global_DD_EXPERIMENTAL_API_SECURITY_ENABLED());
168167

169-
dd_mpack_write_lstr(w, "sample_rate");
170-
mpack_write(w, get_global_DD_API_SECURITY_REQUEST_SAMPLE_RATE());
168+
#define MIN_SE_SAMPLE_RATE 0.0001
169+
170+
double se_sample_rate = get_global_DD_API_SECURITY_REQUEST_SAMPLE_RATE();
171+
if (se_sample_rate >= MIN_SE_SAMPLE_RATE) {
172+
mpack_write_bool(w, true);
173+
174+
dd_mpack_write_lstr(w, "sample_rate");
175+
mpack_write(w, se_sample_rate);
176+
} else {
177+
mpack_write_bool(w, false);
178+
179+
dd_mpack_write_lstr(w, "sample_rate");
180+
mpack_write(w, 0.0);
181+
}
171182

172183
mpack_finish_map(w);
173184

appsec/src/extension/configuration.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ extern bool runtime_config_first_init;
6262
CONFIG(CUSTOM(STRING), DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING, "safe", .parser = dd_parse_automated_user_events_tracking) \
6363
CONFIG(STRING, DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML, "") \
6464
CONFIG(STRING, DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON, "") \
65-
CONFIG(BOOL, DD_EXPERIMENTAL_API_SECURITY_ENABLED, "false") \
6665
CONFIG(DOUBLE, DD_API_SECURITY_REQUEST_SAMPLE_RATE, "0.1")
6766
// clang-format on
6867

appsec/src/helper/client.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -471,16 +471,6 @@ bool client::handle_command(network::request_shutdown::request &command)
471471

472472
response->triggers = std::move(res->events);
473473
response->force_keep = res->force_keep;
474-
for (const auto &[key, value] : res->schemas) {
475-
std::string schema = value;
476-
if (value.length() > max_plain_schema_allowed) {
477-
auto encoded = compress(schema);
478-
if (encoded) {
479-
schema = base64_encode(encoded.value(), false);
480-
}
481-
}
482-
response->meta.emplace(key, std::move(schema));
483-
}
484474

485475
DD_STDLOG(DD_STDLOG_ATTACK_DETECTED);
486476
} else {

appsec/src/helper/client.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ namespace dds {
2121
class client {
2222
public:
2323
// Below this limit the encoding+compression might result on a longer string
24-
static constexpr int max_plain_schema_allowed = 260;
2524
client(std::shared_ptr<service_manager> service_manager,
2625
network::base_broker::ptr &&broker)
2726
: service_manager_(std::move(service_manager)),

appsec/src/helper/engine.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ std::optional<engine::result> engine::context::publish(parameter &&param)
7575

7676
std::vector<std::string> event_data;
7777
std::unordered_set<std::string> event_actions;
78-
std::map<std::string, std::string> schemas;
7978

8079
for (auto &sub : common_->subscribers) {
8180
auto it = listeners_.find(sub);
@@ -89,7 +88,6 @@ std::optional<engine::result> engine::context::publish(parameter &&param)
8988
std::make_move_iterator(event->data.begin()),
9089
std::make_move_iterator(event->data.end()));
9190
event_actions.merge(event->actions);
92-
schemas.merge(event->schemas);
9391
}
9492
} catch (std::exception &e) {
9593
SPDLOG_ERROR("subscriber failed: {}", e.what());
@@ -100,8 +98,7 @@ std::optional<engine::result> engine::context::publish(parameter &&param)
10098
return std::nullopt;
10199
}
102100

103-
dds::engine::result res{
104-
action_type::record, {}, std::move(event_data), std::move(schemas)};
101+
dds::engine::result res{action_type::record, {}, std::move(event_data)};
105102
// Currently the only action the extension can perform is block
106103
if (!event_actions.empty()) {
107104
// The extension can only handle one action, so we pick the first one

appsec/src/helper/engine.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ class engine {
5050
action_type type;
5151
std::unordered_map<std::string, std::string> parameters;
5252
std::vector<std::string> events;
53-
std::map<std::string, std::string> schemas;
5453
bool force_keep;
5554
};
5655

appsec/src/helper/network/proto.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,10 +280,9 @@ struct request_shutdown {
280280

281281
std::map<std::string, std::string> meta;
282282
std::map<std::string_view, double> metrics;
283-
std::map<std::string_view, std::string> schemas;
284283

285284
MSGPACK_DEFINE(
286-
verdict, parameters, triggers, force_keep, meta, metrics, schemas);
285+
verdict, parameters, triggers, force_keep, meta, metrics);
287286
};
288287
};
289288

appsec/src/helper/subscriber/base.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ class subscriber {
2121
struct event {
2222
std::vector<std::string> data;
2323
std::unordered_set<std::string> actions;
24-
std::map<std::string, std::string> schemas;
2524
};
2625

2726
class listener {

appsec/src/helper/subscriber/waf.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
//
44
// This product includes software developed at Datadog
55
// (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
6-
#include "../std_logging.hpp"
7-
#include "ddwaf.h"
86
#include <atomic>
97
#include <chrono>
108
#include <cstdlib>
@@ -18,7 +16,11 @@
1816
#include <string_view>
1917

2018
#include "../json_helper.hpp"
19+
#include "../std_logging.hpp"
2120
#include "../tags.hpp"
21+
#include "base64.h"
22+
#include "compression.hpp"
23+
#include "ddwaf.h"
2224
#include "waf.hpp"
2325

2426
namespace dds::waf {
@@ -39,11 +41,6 @@ dds::subscriber::event format_waf_result(ddwaf_result &res)
3941
output.data.emplace_back(std::move(parameter_to_json(event)));
4042
}
4143

42-
const parameter_view schemas{res.derivatives};
43-
for (const auto &schema : schemas) {
44-
output.schemas.emplace(
45-
schema.key(), std::move(parameter_to_json(schema)));
46-
}
4744
} catch (const std::exception &e) {
4845
SPDLOG_ERROR("failed to parse WAF output: {}", e.what());
4946
}
@@ -209,6 +206,11 @@ std::optional<subscriber::event> instance::listener::call(
209206
// NOLINTNEXTLINE
210207
total_runtime_ += res.total_runtime / 1000.0;
211208

209+
const parameter_view schemas{res.derivatives};
210+
for (const auto &schema : schemas) {
211+
schemas_.emplace(schema.key(), std::move(parameter_to_json(schema)));
212+
}
213+
212214
switch (code) {
213215
case DDWAF_MATCH:
214216
return format_waf_result(res);
@@ -236,6 +238,20 @@ void instance::listener::get_meta_and_metrics(
236238
{
237239
meta[std::string(tag::event_rules_version)] = ruleset_version_;
238240
metrics[tag::waf_duration] = total_runtime_;
241+
242+
for (const auto &[key, value] : schemas_) {
243+
std::string schema = value;
244+
if (value.length() > max_plain_schema_allowed) {
245+
auto encoded = compress(schema);
246+
if (encoded) {
247+
schema = base64_encode(encoded.value(), false);
248+
}
249+
}
250+
251+
if (schema.length() <= max_schema_size) {
252+
meta.emplace(key, std::move(schema));
253+
}
254+
}
239255
}
240256

241257
instance::instance(parameter &rule, std::map<std::string, std::string> &meta,

appsec/src/helper/subscriber/waf.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ void initialise_logging(spdlog::level::level_enum level);
2323
class instance : public dds::subscriber {
2424
public:
2525
static constexpr int default_waf_timeout_us = 10000;
26-
26+
static constexpr int max_plain_schema_allowed = 260;
27+
static constexpr int max_schema_size = 25000;
2728
using ptr = std::shared_ptr<instance>;
2829
class listener : public dds::subscriber::listener {
2930
public:
@@ -46,6 +47,7 @@ class instance : public dds::subscriber {
4647
std::chrono::microseconds waf_timeout_;
4748
double total_runtime_{0.0};
4849
std::string_view ruleset_version_;
50+
std::map<std::string, std::string> schemas_;
4951
};
5052

5153
// NOLINTNEXTLINE(google-runtime-references)

0 commit comments

Comments
 (0)