From e83db81e6852a9a9a048d2fe32d2b53f937fb632 Mon Sep 17 00:00:00 2001 From: Shannon Weyrick Date: Tue, 14 Sep 2021 12:13:52 -0400 Subject: [PATCH] require a new key 'kind' to specify policy type, in preparation for future policy schemas --- RFCs/2021-04-16-76-collection-policies.md | 3 +++ cmd/pktvisord/main.cpp | 2 ++ src/Policies.cpp | 8 ++++++ src/tests/test_policies.cpp | 30 +++++++++++++++++++++++ 4 files changed, 43 insertions(+) diff --git a/RFCs/2021-04-16-76-collection-policies.md b/RFCs/2021-04-16-76-collection-policies.md index fe41bdc98..e4a00f57c 100644 --- a/RFCs/2021-04-16-76-collection-policies.md +++ b/RFCs/2021-04-16-76-collection-policies.md @@ -6,6 +6,8 @@ Collection policies direct pktvisor to use Taps (#75) to create an instance of a and attach handlers to it. Processing takes place, and the data is exposed for sinks to collect. These policies may be given directly to pktvisor via command line or through the Admin API if available. +Policies require a `kind` to indicate the type of policy being applied. + `collection-policy-anycast.yaml` ```yaml @@ -15,6 +17,7 @@ visor: policies: # policy name and description anycast_dns: + kind: collection description: "base anycast DNS policy" # input stream to create based on the given tap and optional filter config input: diff --git a/cmd/pktvisord/main.cpp b/cmd/pktvisord/main.cpp index 5e1290415..a4da27b50 100644 --- a/cmd/pktvisord/main.cpp +++ b/cmd/pktvisord/main.cpp @@ -161,8 +161,10 @@ version: "1.0" host_spec: "{}" policies: default: + kind: collection input: tap: default + input_type: pcap config: bpf: "{}" handlers: diff --git a/src/Policies.cpp b/src/Policies.cpp index f3c09e358..e3635dac6 100644 --- a/src/Policies.cpp +++ b/src/Policies.cpp @@ -51,6 +51,14 @@ std::vector PolicyManager::load(const YAML::Node &policy_yaml) throw PolicyException("expecting policy configuration map"); } + // Policy kind defines schema + if (!it->second["kind"] || !it->second["kind"].IsScalar()) { + throw PolicyException("missing or invalid policy kind at key 'kind'"); + } + if (it->second["kind"].as() != "collection") { + throw PolicyException(fmt::format("unknown policy kind: {}", it->second["kind"].as())); + } + // Input Section if (!it->second["input"] || !it->second["input"].IsMap()) { throw PolicyException("missing or invalid policy input stream configuration at key 'input'"); diff --git a/src/tests/test_policies.cpp b/src/tests/test_policies.cpp index 8af71299f..79b0a93c4 100644 --- a/src/tests/test_policies.cpp +++ b/src/tests/test_policies.cpp @@ -25,6 +25,7 @@ version: "1.0" policies: # policy name and description default_view: + kind: collection # description: "a mock view of anycast traffic" # input stream to create based on the given tap and optional filter config input: @@ -71,6 +72,7 @@ version: "1.0" iface: eth0 policies: default_view: + kind: collection input: tap: nonexist input_type: mock @@ -87,6 +89,7 @@ version: "1.0" iface: eth0 policies: default_view: + kind: collection input: tap: anycast input_type: mock @@ -106,6 +109,7 @@ version: "1.0" iface: eth0 policies: default_view: + kind: collection input: tap: anycast input_type: mock @@ -127,10 +131,27 @@ version: "1.0" iface: eth0 policies: default_view: + kind: collection input: tap: anycast input_type: wrong_type )"; +auto policies_config_bad6 = R"( +version: "1.0" + +visor: + taps: + anycast: + input_type: mock + config: + iface: eth0 + policies: + default_view: + kind: unknown_kind + input: + tap: anycast + input_type: mock +)"; TEST_CASE("Policies", "[policies]") { @@ -221,6 +242,15 @@ TEST_CASE("Policies", "[policies]") 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("Bad Config: bad policy kind") + { + CoreRegistry registry(nullptr); + YAML::Node config_file = YAML::Load(policies_config_bad6); + + REQUIRE_NOTHROW(registry.tap_manager()->load(config_file["visor"]["taps"], true)); + REQUIRE_THROWS_WITH(registry.policy_manager()->load(config_file["visor"]["policies"]), "unknown policy kind: unknown_kind"); + } + SECTION("Roll Back") { CoreRegistry registry(nullptr);