Files
netbird/shared/management/networkmap/decode_test.go
T

113 lines
4.2 KiB
Go

package networkmap
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
protobuf "google.golang.org/protobuf/proto"
"github.com/netbirdio/netbird/shared/management/networkmap/nmdata"
"github.com/netbirdio/netbird/shared/management/proto"
"github.com/netbirdio/netbird/shared/management/types"
)
func TestDecodePolicy(t *testing.T) {
assert.Equal(t,
nmdata.Resource{Type: "peer", ID: "valid-id"},
resourceFromProto(
&proto.ResourceCompact{Type: "peer", PeerIndexSet: true, PeerIndex: uint32(1)},
[]string{"invalid-id-0", "valid-id", "invalid-id-2"}))
// check invalid peer index returns an empty resource
assert.Equal(t,
nmdata.Resource{},
resourceFromProto(
&proto.ResourceCompact{Type: "peer", PeerIndexSet: true, PeerIndex: uint32(100)},
[]string{"invalid-id-0", "valid-id", "invalid-id-2"}))
assert.Equal(t,
nmdata.Resource{Type: "domain", ID: "domain"},
resourceFromProto(
&proto.ResourceCompact{Type: "domain", Id: "domain"}, []string{}))
assert.Equal(t,
nmdata.Resource{Type: "host", ID: "host"},
resourceFromProto(
&proto.ResourceCompact{Type: "host", Id: "host"}, []string{}))
assert.Equal(t,
nmdata.Resource{Type: "subnet", ID: "subnet"},
resourceFromProto(
&proto.ResourceCompact{Type: "subnet", Id: "subnet"}, []string{}))
// an unknown resource type return an empty resource
assert.Equal(t,
nmdata.Resource{},
resourceFromProto(
&proto.ResourceCompact{Type: "boom", Id: "boom"}, []string{}))
}
// ResourceCompact fields 1-3 are the v0.77 wire contract. Retyping any of them
// makes peers on either side of the change silently drop policy resources, so
// the encoding is pinned here as raw bytes: field 1 "peer" (bytes), field 2
// true (varint), field 3 7 (varint).
func TestResourceCompactLegacyWireFormat(t *testing.T) {
legacy := []byte{0x0a, 0x04, 'p', 'e', 'e', 'r', 0x10, 0x01, 0x18, 0x07}
var decoded proto.ResourceCompact
require.NoError(t, protobuf.Unmarshal(legacy, &decoded))
assert.Equal(t, "peer", decoded.Type)
assert.True(t, decoded.PeerIndexSet)
assert.Equal(t, uint32(7), decoded.PeerIndex)
encoded, err := protobuf.Marshal(&proto.ResourceCompact{Type: "peer", PeerIndexSet: true, PeerIndex: 7})
require.NoError(t, err)
assert.Equal(t, legacy, encoded)
}
// A management newer than this client can ship a protocol value this build has
// no case for. Mapping it to ALL would both widen the rule to every IP protocol
// and, because an ALL match short-circuits the port comparison, discard the
// port restriction the rule was written with. The rule must be dropped instead.
func TestDecodePolicyCompact_UnknownProtocolIsDropped(t *testing.T) {
const futureProtocol = proto.RuleProtocol(99)
pc := &proto.PolicyCompact{
Id: "policy-1",
Action: proto.RuleAction_ACCEPT,
Protocol: futureProtocol,
PortRanges: []*proto.PortInfo_Range{
{Start: 25900, End: 25900},
},
SourceGroupIds: []string{"g-src"},
DestinationGroupIds: []string{"g-dst"},
}
assert.Nil(t, decodePolicyCompact(pc, pc.Id, nil),
"a rule with an unrecognized protocol must not decode into an enforceable rule")
_, ok := protocolFromProto(futureProtocol)
assert.False(t, ok, "an unrecognized protocol must not resolve to a known one")
}
// Every protocol the encoder can emit must survive a round trip, so the
// drop-on-unknown rule above cannot quietly start discarding valid policies.
func TestProtocolFromProto_KnownValuesRoundTrip(t *testing.T) {
known := []proto.RuleProtocol{
proto.RuleProtocol_ALL,
proto.RuleProtocol_TCP,
proto.RuleProtocol_UDP,
proto.RuleProtocol_ICMP,
proto.RuleProtocol_NETBIRD_SSH,
proto.RuleProtocol_NETBIRD_VNC,
}
for _, p := range known {
decoded, ok := protocolFromProto(p)
require.Truef(t, ok, "protocol %s must decode", p)
assert.Equalf(t, p, GetProtoProtocol(string(decoded)), "protocol %s must round trip", p)
}
}
// An action the switch does not recognize must deny, not accept.
func TestActionFromProto_UnknownDenies(t *testing.T) {
assert.Equal(t, types.PolicyTrafficActionAccept, actionFromProto(proto.RuleAction_ACCEPT))
assert.Equal(t, types.PolicyTrafficActionDrop, actionFromProto(proto.RuleAction_DROP))
assert.Equal(t, types.PolicyTrafficActionDrop, actionFromProto(proto.RuleAction(99)))
}