Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement tap selector #330

Merged
merged 13 commits into from
Aug 1, 2022
6 changes: 6 additions & 0 deletions RFCs/2021-04-16-75-taps.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,19 @@ visor:
input_type: pcap
config:
iface: eth0
tags:
virtual: true
vhost: 1
# an sflow tap which listens on the given IP and port, referenced by the identifier "pop_switch"
pop_switch:
input_type: flow
config:
flow_type: sflow
port: 6343
bind: 192.168.1.1
tags:
virtual: false
vhost: 2
# a dnstap tap which gets its stream from the given socket, named "trex_tap"
trex_tap:
input_type: dnstap
Expand Down
8 changes: 6 additions & 2 deletions RFCs/2021-04-16-76-collection-policies.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,12 @@ visor:
description: "base chaning NET to DNS policy"
# input stream to create based on the given tap and optional filter config
input:
# this must reference a tap name, or application of the policy will fail
tap: anycast
# this must reference valid tags existent on applied taps, or application of the policy will fail
tap_selector:
# It can be either "any" or "all"
leoparente marked this conversation as resolved.
Show resolved Hide resolved
any:
virtual: true
vhost: 1
# this must match the input_type of the matching tap name, or application of the policy will fail
input_type: pcap
filter:
Expand Down
538 changes: 301 additions & 237 deletions src/Policies.cpp

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/Policies.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ class PolicyManager : public AbstractManager<Policy>
void set_default_handler_config(const YAML::Node &config_yaml);
std::vector<Policy *> load_from_str(const std::string &str);
std::vector<Policy *> load(const YAML::Node &tap_yaml);
Policy *create_policy(const YAML::Node &policy_yaml, std::string policy_name, Tap *tap = nullptr);
void remove_policy(const std::string &name);
};

Expand Down
51 changes: 51 additions & 0 deletions src/Taps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ void TapManager::load(const YAML::Node &tap_yaml, bool strict)
tap_module->config_set_yaml(it->second["config"]);
}

if (it->second["tags"]) {
if (!it->second["tags"].IsMap()) {
throw ConfigException("tap tags is not a map");
}
tap_module->tags_set_yaml(it->second["tags"]);
}

// will throw if it already exists. nothing else to clean up
module_add(std::move(tap_module));

Expand All @@ -76,4 +83,48 @@ std::unique_ptr<InputStream> Tap::instantiate(const Configurable *config, const
return module;
}

bool Tap::tags_validate_yaml(const YAML::Node &tag_yaml, bool all)
{
bool any_match = false;
for (YAML::const_iterator it = tag_yaml.begin(); it != tag_yaml.end(); ++it) {
if (!it->second.IsScalar()) {
throw PolicyException(fmt::format("tag key '{}' must have scalar value", it->first));
leoparente marked this conversation as resolved.
Show resolved Hide resolved
}

auto key = it->first.as<std::string>();
if (!_tags->config_exists(key)) {
if (all) {
return false;
} else {
continue;
}
}

// the yaml library doesn't discriminate between scalar types, so we have to do that ourselves
auto value = it->second.as<std::string>();
if (std::regex_match(value, std::regex("[0-9]+"))) {
if (_tags->config_get<uint64_t>(key) == it->second.as<uint64_t>()) {
any_match = true;
} else if (all) {
return false;
}

} else if (std::regex_match(value, std::regex("true|false", std::regex_constants::icase))) {
if (_tags->config_get<bool>(key) == it->second.as<bool>()) {
any_match = true;
} else if (all) {
return false;
}
} else {
if (_tags->config_get<std::string>(key) == value) {
any_match = true;
} else if (all) {
return false;
}
}
}

return any_match;
}

}
10 changes: 10 additions & 0 deletions src/Taps.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ class Tap : public AbstractModule
{

InputModulePlugin *_input_plugin;
std::unique_ptr<Configurable> _tags;

public:
Tap(const std::string &name, InputModulePlugin *input_plugin)
: AbstractModule(name)
, _input_plugin(input_plugin)
, _tags(std::make_unique<Configurable>())
{
assert(input_plugin);
}
Expand All @@ -32,6 +34,8 @@ class Tap : public AbstractModule

std::unique_ptr<InputStream> instantiate(const Configurable *config, const Configurable *filter, std::string input_name);

bool tags_validate_yaml(const YAML::Node &tag_yaml, bool all);
leoparente marked this conversation as resolved.
Show resolved Hide resolved

const InputModulePlugin *input_plugin() const
{
return _input_plugin;
Expand All @@ -42,6 +46,12 @@ class Tap : public AbstractModule
j["input_type"] = _input_plugin->plugin();
j["interface"] = _input_plugin->pluginInterface();
config_json(j["config"]);
_tags->config_json(j["tags"]);
}

void tags_set_yaml(const YAML::Node &tag_yaml)
{
_tags->config_set_yaml(tag_yaml);
}
};

Expand Down
Loading