Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions RFCs/2021-04-16-76-collection-policies.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ visor:
input:
# this must reference a tap name, or application of the policy will fail
tap: anycast
# this must match the type of the matching tap name. or application of the policy will fail
type: pcap
# this must match the input_type of the matching tap name, or application of the policy will fail
input_type: pcap
config:
bpf: "port 53"
# stream handlers to attach to this input stream
Expand Down
11 changes: 9 additions & 2 deletions src/Policies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ std::vector<Policy *> PolicyManager::load(const YAML::Node &policy_yaml)
}
auto input_node = it->second["input"];
if (!input_node["tap"] || !input_node["tap"].IsScalar()) {
throw PolicyException("missing or invalid tap at key 'tap'");
throw PolicyException("missing or invalid tap at key 'input.tap'");
}
if (!input_node["input_type"] || !input_node["input_type"].IsScalar()) {
throw PolicyException("missing or invalid input_type at key 'input.input_type'");
}

// Tap
Expand Down Expand Up @@ -99,9 +102,13 @@ std::vector<Policy *> PolicyManager::load(const YAML::Node &policy_yaml)
try {
spdlog::get("visor")->info("policy [{}]: instantiating Tap: {}", policy_name, tap_name);
input_stream = tap->instantiate(policy.get(), &tap_filter);
// ensure tap input type matches policy input tap
if (input_node["input_type"].as<std::string>() != tap->input_plugin()->plugin()) {
throw PolicyException(fmt::format("input_type for policy specified tap '{}' doesn't match tap's defined input type: {}/{}", tap_name, input_node["input_type"].as<std::string>(), tap->input_plugin()->plugin()));
}
input_stream_module_name = input_stream->name();
} catch (std::runtime_error &e) {
throw PolicyException(fmt::format("unable to instantiate tap {}: {}", tap_name, e.what()));
throw PolicyException(fmt::format("unable to instantiate tap '{}': {}", tap_name, e.what()));
}
policy->set_input_stream(input_stream.get());

Expand Down
5 changes: 5 additions & 0 deletions src/Taps.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ class Tap : public AbstractModule

std::unique_ptr<InputStream> instantiate(Policy *policy, const Configurable *filter_config);

const InputModulePlugin *input_plugin() const
{
return _input_plugin;
}

void info_json(json &j) const override
{
j["input_type"] = _input_plugin->plugin();
Expand Down
28 changes: 28 additions & 0 deletions src/tests/test_policies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ version: "1.0"
input:
# this must reference a tap name, or application of the policy will fail
tap: anycast
input_type: mock
config:
bpf: "tcp or udp"
# stream handlers to attach to this input stream
Expand Down Expand Up @@ -72,6 +73,7 @@ version: "1.0"
default_view:
input:
tap: nonexist
input_type: mock
)";

auto policies_config_bad3 = R"(
Expand All @@ -87,6 +89,7 @@ version: "1.0"
default_view:
input:
tap: anycast
input_type: mock
config:
bpf:
badmap: "bad value"
Expand All @@ -105,13 +108,29 @@ version: "1.0"
default_view:
input:
tap: anycast
input_type: mock
config:
except_on_start: true
handlers:
modules:
default_net:
type: net
)";
auto policies_config_bad5 = R"(
version: "1.0"

visor:
taps:
anycast:
input_type: mock
config:
iface: eth0
policies:
default_view:
input:
tap: anycast
input_type: wrong_type
)";

TEST_CASE("Policies", "[policies]")
{
Expand Down Expand Up @@ -193,6 +212,15 @@ TEST_CASE("Policies", "[policies]")
REQUIRE_THROWS_WITH(registry.policy_manager()->load(config_file["visor"]["policies"]), "policy [default_view] failed to start: mock error on start");
}

SECTION("Bad Config: mis-matched input_type on tap")
{
CoreRegistry registry(nullptr);
YAML::Node config_file = YAML::Load(policies_config_bad5);

REQUIRE_NOTHROW(registry.tap_manager()->load(config_file["visor"]["taps"], true));
REQUIRE_THROWS_WITH(registry.policy_manager()->load(config_file["visor"]["policies"]), "unable to instantiate tap 'anycast': input_type for policy specified tap 'anycast' doesn't match tap's defined input type: wrong_type/mock");
}

SECTION("Roll Back")
{
CoreRegistry registry(nullptr);
Expand Down