From a9c93da8cbf72bb560fe739a238d38f01e0fb2c9 Mon Sep 17 00:00:00 2001 From: Nate Brown Date: Fri, 13 Dec 2019 13:45:21 -0800 Subject: [PATCH] Detect group array usage and try to be kind --- firewall.go | 16 +++++++++++++--- firewall_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/firewall.go b/firewall.go index 1a05256..763a66d 100644 --- a/firewall.go +++ b/firewall.go @@ -272,7 +272,7 @@ func AddFirewallRulesFromConfig(inbound bool, config *Config, fw FirewallInterfa for i, t := range rs { var groups []string - r, err := convertRule(t) + r, err := convertRule(t, table, i) if err != nil { return fmt.Errorf("%s rule #%v; %s", table, i, err) } @@ -664,7 +664,7 @@ type rule struct { CASha string } -func convertRule(p interface{}) (rule, error) { +func convertRule(p interface{}, table string, i int) (rule, error) { r := rule{} m, ok := p.(map[interface{}]interface{}) @@ -684,11 +684,21 @@ func convertRule(p interface{}) (rule, error) { r.Code = toString("code", m) r.Proto = toString("proto", m) r.Host = toString("host", m) - r.Group = toString("group", m) r.Cidr = toString("cidr", m) r.CAName = toString("ca_name", m) r.CASha = toString("ca_sha", m) + // Make sure group isn't an array + if v, ok := m["group"].([]interface{}); ok { + if len(v) > 1 { + return r, errors.New("group should contain a single value, an array with more than one entry was provided") + } + + l.Warnf("%s rule #%v; group was an array with a single value, converting to simple value", table, i) + m["group"] = v[0] + } + r.Group = toString("group", m) + if rg, ok := m["groups"]; ok { switch reflect.TypeOf(rg).Kind() { case reflect.Slice: diff --git a/firewall_test.go b/firewall_test.go index 7ae1c56..371bb91 100644 --- a/firewall_test.go +++ b/firewall_test.go @@ -1,6 +1,7 @@ package nebula import ( + "bytes" "encoding/binary" "errors" "math" @@ -676,6 +677,43 @@ func TestTCPRTTTracking(t *testing.T) { assert.Equal(t, uint32(0), c.Seq) } +func TestFirewall_convertRule(t *testing.T) { + ob := &bytes.Buffer{} + out := l.Out + l.SetOutput(ob) + defer l.SetOutput(out) + + // Ensure group array of 1 is converted and a warning is printed + c := map[interface{}]interface{}{ + "group": []interface{}{"group1"}, + } + + r, err := convertRule(c, "test", 1) + assert.Contains(t, ob.String(), "test rule #1; group was an array with a single value, converting to simple value") + assert.Nil(t, err) + assert.Equal(t, "group1", r.Group) + + // Ensure group array of > 1 is errord + ob.Reset() + c = map[interface{}]interface{}{ + "group": []interface{}{"group1", "group2"}, + } + + r, err = convertRule(c, "test", 1) + assert.Equal(t, "", ob.String()) + assert.Error(t, err, "group should contain a single value, an array with more than one entry was provided") + + // Make sure a well formed group is alright + ob.Reset() + c = map[interface{}]interface{}{ + "group": "group1", + } + + r, err = convertRule(c, "test", 1) + assert.Nil(t, err) + assert.Equal(t, "group1", r.Group) +} + type addRuleCall struct { incoming bool proto uint8