diff --git a/RFCs/2021-04-16-76-collection-policies.md b/RFCs/2021-04-16-76-collection-policies.md index 441e5deaf..fe41bdc98 100644 --- a/RFCs/2021-04-16-76-collection-policies.md +++ b/RFCs/2021-04-16-76-collection-policies.md @@ -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 diff --git a/src/Policies.cpp b/src/Policies.cpp index 1258f4839..f3c09e358 100644 --- a/src/Policies.cpp +++ b/src/Policies.cpp @@ -57,7 +57,10 @@ std::vector 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 @@ -99,9 +102,13 @@ std::vector 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() != 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(), 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()); diff --git a/src/Taps.h b/src/Taps.h index 55b9d6bde..eede1ca1f 100644 --- a/src/Taps.h +++ b/src/Taps.h @@ -30,6 +30,11 @@ class Tap : public AbstractModule std::unique_ptr 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(); diff --git a/src/tests/test_policies.cpp b/src/tests/test_policies.cpp index 022d753ee..8af71299f 100644 --- a/src/tests/test_policies.cpp +++ b/src/tests/test_policies.cpp @@ -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 @@ -72,6 +73,7 @@ version: "1.0" default_view: input: tap: nonexist + input_type: mock )"; auto policies_config_bad3 = R"( @@ -87,6 +89,7 @@ version: "1.0" default_view: input: tap: anycast + input_type: mock config: bpf: badmap: "bad value" @@ -105,6 +108,7 @@ version: "1.0" default_view: input: tap: anycast + input_type: mock config: except_on_start: true handlers: @@ -112,6 +116,21 @@ version: "1.0" 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]") { @@ -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);