mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-23 15:19:08 +02:00
113 lines
4.2 KiB
Go
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)))
|
|
}
|