Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
cataphract committed Oct 4, 2024
1 parent 6ea002c commit 708dbe4
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 12 deletions.
38 changes: 38 additions & 0 deletions appsec/src/helper/remote_config/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,27 @@ ddog_RemoteConfigReader *(*ddog_remote_config_reader_for_path)(
bool (*ddog_remote_config_read)(
ddog_RemoteConfigReader *reader, ddog_CharSlice *data);
void (*ddog_remote_config_reader_drop)(struct ddog_RemoteConfigReader *);

// if before is the same as after, disconsidering elements not in products
bool has_updates(
const std::unordered_set<dds::remote_config::product> &products,
const std::set<dds::remote_config::config> &before,
const std::set<dds::remote_config::config> &after)
{
auto set_is_subset_of = [&products](auto &set1, auto &set2) {
for (auto &&elem_set_1 : set1) { // NOLINT(readability-use-anyofallof)
if (!products.contains(elem_set_1.get_product())) {
continue;
}
if (!set2.contains(elem_set_1)) {
return false;
}
}
return true;
};

return !set_is_subset_of(before, after) || !set_is_subset_of(after, before);
}
} // namespace

namespace dds::remote_config {
Expand Down Expand Up @@ -73,6 +94,7 @@ client::client(remote_config::settings settings,
std::vector<listener_base *> &vec_listeners =
listeners_per_product_[p];
vec_listeners.push_back(listener.get());
all_products_.insert(p);
}
}
}
Expand All @@ -86,6 +108,8 @@ std::unique_ptr<client> client::from_settings(

bool client::poll()
{
const std::lock_guard lock{mutex_};

SPDLOG_DEBUG("Polling remote config");

ddog_CharSlice slice{};
Expand Down Expand Up @@ -116,6 +140,20 @@ bool client::poll()
configs = configs.substr(pos_lf + 1);
}

if (!has_updates(all_products_, new_configs, last_configs_)) {
SPDLOG_DEBUG("Configuration is identical for the subscribed products. "
"Skipping update");
SPDLOG_DEBUG("BEFORE:");
for (auto &&c : last_configs_) {
SPDLOG_DEBUG("{}:{}", c.rc_path, c.shm_path);
}
SPDLOG_DEBUG("AFTER:");
for (auto &&c : last_configs_) {
SPDLOG_DEBUG("{}:{}", c.rc_path, c.shm_path);
}
return false;
}

return process_response(std::move(new_configs));
}

Expand Down
5 changes: 4 additions & 1 deletion appsec/src/helper/remote_config/client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#pragma once

#include <atomic>
#include <mutex>
#include <set>
#include <string>
#include <thread>
Expand Down Expand Up @@ -62,9 +63,11 @@ class client {

std::vector<std::shared_ptr<listener_base>> listeners_;
std::unordered_map<product, std::vector<listener_base *>>
listeners_per_product_; // non-owning index of listeners_
listeners_per_product_; // non-owning index of listeners_
std::unordered_set<product> all_products_; // keys of listeners_per_product_

std::set<config> last_configs_;
std::mutex mutex_;
};

} // namespace dds::remote_config
2 changes: 1 addition & 1 deletion appsec/src/helper/remote_config/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ namespace dds::remote_config {
}
} else if (sv.starts_with("employee/"sv)) {
sv.remove_prefix("employee/"sv.length());
auto product_end = shm_path.find('/');
auto product_end = sv.find('/');
if (product_end != std::string::npos) {
return known_products::for_name(sv.substr(0, product_end));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.datadog.appsec.php.mock_agent.rem_cfg

enum Capability {
ASM_ACTIVATION(1),
ASM_IP_BLOCKING(2),
ASM_DD_RULES(3),
ASM_EXCLUSIONS(4),
ASM_REQUEST_BLOCKING(5),
ASM_RESPONSE_BLOCKING(6),
ASM_USER_BLOCKING(7),
ASM_CUSTOM_RULES(8),
ASM_CUSTOM_BLOCKING_RESPONSE(9),
ASM_TRUSTED_IPS(10),
ASM_API_SECURITY_SAMPLE_RATE(11),
APM_TRACING_SAMPLE_RATE(12),
APM_TRACING_LOGS_INJECTION(13),
APM_TRACING_HTTP_HEADER_TAGS(14),
APM_TRACING_CUSTOM_TAGS(15),
ASM_PROCESSOR_OVERRIDES(16),
ASM_CUSTOM_DATA_SCANNERS(17),
ASM_EXCLUSION_DATA(18),
APM_TRACING_ENABLED(19),
APM_TRACING_DATA_STREAMS_ENABLED(20),
ASM_RASP_SQLI(21),
ASM_RASP_LFI(22),
ASM_RASP_SSRF(23),
ASM_RASP_SHI(24),
ASM_RASP_XXE(25),
ASM_RASP_RCE(26),
ASM_RASP_NOSQLI(27),
ASM_RASP_XSS(28),
APM_TRACING_SAMPLE_RULES(29),
CSM_ACTIVATION(30)

final int ordinal

Capability(int ordinal) {
this.ordinal = ordinal
}

static EnumSet<Capability> forByteArray(byte[] arr) {
def capabilities = EnumSet.noneOf(Capability)
def bi = new BigInteger(arr)
for (Capability c: values()) {
if (bi.testBit(c.ordinal)) {
capabilities << c
}
}
capabilities
}
}
4 changes: 2 additions & 2 deletions appsec/tests/integration/src/test/bin/enable_extensions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ if [[ -f /appsec/ddappsec.so && -d /project ]]; then
echo datadog.appsec.enabled=true
echo datadog.appsec.helper_path=/appsec/libddappsec-helper.so
echo datadog.appsec.helper_log_file=/tmp/logs/helper.log
echo datadog.appsec.helper_log_level=info
# echo datadog.appsec.helper_log_level=debug
# echo datadog.appsec.helper_log_level=info
echo datadog.appsec.helper_log_level=debug
echo datadog.appsec.rules=/etc/recommended.json
echo datadog.appsec.log_file=/tmp/logs/appsec.log
echo datadog.appsec.log_level=debug
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.datadog.appsec.php.integration

import com.datadog.appsec.php.docker.AppSecContainer
import com.datadog.appsec.php.docker.FailOnUnmatchedTraces
import com.datadog.appsec.php.mock_agent.rem_cfg.Capability
import com.datadog.appsec.php.mock_agent.rem_cfg.RemoteConfigRequest
import com.datadog.appsec.php.mock_agent.rem_cfg.RemoteConfigResponse
import com.datadog.appsec.php.mock_agent.rem_cfg.Target
Expand Down Expand Up @@ -55,7 +56,7 @@ class RemoteConfigTests {
}

@Test
void 'test remote activation'() {
void 'test remote activation and capabilities'() {
def doReq = { int expectedStatus ->
HttpRequest req = CONTAINER.buildReq('/hello.php')
.GET()
Expand All @@ -68,12 +69,27 @@ class RemoteConfigTests {

doReq.call(200)

applyRemoteConfig(INITIAL_TARGET, [
RemoteConfigRequest rcr = applyRemoteConfig(INITIAL_TARGET, [
'datadog/2/ASM_FEATURES/asm_features_activation/config': [
asm: [enabled: true]
]
])

def capSet = Capability.forByteArray(rcr.client.capabilities)

[
Capability.ASM_ACTIVATION,
Capability.ASM_IP_BLOCKING,
Capability.ASM_DD_RULES,
Capability.ASM_EXCLUSIONS,
Capability.ASM_REQUEST_BLOCKING,
Capability.ASM_RESPONSE_BLOCKING,
Capability.ASM_USER_BLOCKING,
Capability.ASM_CUSTOM_RULES,
Capability.ASM_CUSTOM_BLOCKING_RESPONSE,
Capability.ASM_TRUSTED_IPS,
].each { assert it in capSet }

doReq.call(403)

dropRemoteConfig(INITIAL_TARGET)
Expand Down Expand Up @@ -138,7 +154,7 @@ class RemoteConfigTests {

applyRemoteConfig(INITIAL_TARGET, [
'datadog/2/ASM_FEATURES/asm_features_activation/config': [asm: [enabled: true]],
'datadog/2/ASM_DD/full_cfg/config':
'employee/ASM_DD/full_cfg/config':
[
version: '2.1',
rules: [[
Expand Down
5 changes: 0 additions & 5 deletions components-rs/remote_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,6 @@ pub unsafe extern "C" fn ddog_init_remote_config(
RemoteConfigCapabilities::AsmCustomRules,
RemoteConfigCapabilities::AsmCustomBlockingResponse,
RemoteConfigCapabilities::AsmTrustedIps,
RemoteConfigCapabilities::AsmApiSecuritySampleRate,
RemoteConfigCapabilities::AsmProcessorOverrides,
RemoteConfigCapabilities::AsmCustomDataScanners,
RemoteConfigCapabilities::AsmExclusionData,
RemoteConfigCapabilities::AsmRaspSqli,
]
.iter()
.for_each(|c| DDTRACE_REMOTE_CONFIG_CAPABILITIES.push(*c));
Expand Down

0 comments on commit 708dbe4

Please sign in to comment.