fix: send empty PacketFilter when no rules match

This commit is contained in:
Johan Siebens
2024-01-19 09:56:28 +01:00
parent 123ca99665
commit 980ab1bc46
3 changed files with 36 additions and 16 deletions
+7 -11
View File
@@ -252,9 +252,9 @@ func (a ACLPolicy) NodeCapabilities(m *Machine) []tailcfg.NodeCapability {
}
func (a ACLPolicy) BuildFilterRules(srcs []Machine, dst *Machine) []tailcfg.FilterRule {
var rules []tailcfg.FilterRule
var rules = make([]tailcfg.FilterRule, 0)
transform := func(src []string, destPorts []tailcfg.NetPortRange, u *User) tailcfg.FilterRule {
appendRules := func(rules []tailcfg.FilterRule, src []string, destPorts []tailcfg.NetPortRange, u *User) []tailcfg.FilterRule {
var allSrcIPsSet = &StringSet{}
for _, alias := range src {
for _, src := range srcs {
@@ -266,29 +266,25 @@ func (a ACLPolicy) BuildFilterRules(srcs []Machine, dst *Machine) []tailcfg.Filt
allSrcIPs := allSrcIPsSet.Items()
if len(allSrcIPs) == 0 {
allSrcIPs = nil
return rules
}
return tailcfg.FilterRule{
return append(rules, tailcfg.FilterRule{
SrcIPs: allSrcIPs,
DstPorts: destPorts,
}
})
}
for _, acl := range a.ACLs {
selfDestPorts, allDestPorts := a.expandMachineToDstPorts(dst, acl.Dst)
if len(selfDestPorts) != 0 {
rules = append(rules, transform(acl.Src, selfDestPorts, &dst.User))
rules = appendRules(rules, acl.Src, selfDestPorts, &dst.User)
}
if len(allDestPorts) != 0 {
rules = append(rules, transform(acl.Src, allDestPorts, nil))
rules = appendRules(rules, acl.Src, allDestPorts, nil)
}
}
if len(rules) == 0 {
return []tailcfg.FilterRule{{}}
}
return rules
}
+16
View File
@@ -104,6 +104,22 @@ func TestACLPolicy_NodeAttributesWithUserAndTags(t *testing.T) {
assert.Equal(t, expectedAttrs, actualAttrs)
}
func TestACLPolicy_BuildFilterRulesEmptyACL(t *testing.T) {
p1 := createMachine("john@example.com")
p2 := createMachine("jane@example.com")
policy := ACLPolicy{
ACLs: []ACL{},
}
dst := createMachine("john@example.com")
actualRules := policy.BuildFilterRules([]Machine{*p1, *p2}, dst)
expectedRules := []tailcfg.FilterRule{}
assert.Equal(t, expectedRules, actualRules)
}
func TestACLPolicy_BuildFilterRulesWildcards(t *testing.T) {
p1 := createMachine("john@example.com")
p2 := createMachine("jane@example.com")
+13 -5
View File
@@ -11,6 +11,14 @@ import (
"time"
)
// MapResponse is a custom tailcfg.MapResponse
// for marshalling non-nil zero-length slices (meaning explicitly now empty)
// see tailcfg.MapResponse documentation
type MapResponse struct {
tailcfg.MapResponse
PacketFilter []tailcfg.FilterRule
}
func NewPollNetMapper(req *tailcfg.MapRequest, machineID uint64, repository domain.Repository, sessionManager core.PollMapSessionManager) *PollNetMapper {
return &PollNetMapper{
req: req,
@@ -34,7 +42,7 @@ type PollNetMapper struct {
sessionManager core.PollMapSessionManager
}
func (h *PollNetMapper) CreateMapResponse(ctx context.Context, delta bool) (*tailcfg.MapResponse, error) {
func (h *PollNetMapper) CreateMapResponse(ctx context.Context, delta bool) (*MapResponse, error) {
h.Lock()
defer h.Unlock()
@@ -106,10 +114,10 @@ func (h *PollNetMapper) CreateMapResponse(ctx context.Context, delta bool) (*tai
filterRules := policies.BuildFilterRules(candidatePeers, m)
controlTime := time.Now().UTC()
var mapResponse *tailcfg.MapResponse
var mapResponse tailcfg.MapResponse
if !delta {
mapResponse = &tailcfg.MapResponse{
mapResponse = tailcfg.MapResponse{
KeepAlive: false,
Node: node,
DNSConfig: ToDNSConfig(m, &m.Tailnet, &dnsConfig),
@@ -125,7 +133,7 @@ func (h *PollNetMapper) CreateMapResponse(ctx context.Context, delta bool) (*tai
},
}
} else {
mapResponse = &tailcfg.MapResponse{
mapResponse = tailcfg.MapResponse{
Node: node,
DNSConfig: ToDNSConfig(m, &m.Tailnet, &dnsConfig),
PacketFilter: filterRules,
@@ -155,7 +163,7 @@ func (h *PollNetMapper) CreateMapResponse(ctx context.Context, delta bool) (*tai
h.prevSyncedPeerIDs = syncedPeerIDs
h.prevDerpMapChecksum = derpMap.Checksum
return mapResponse, nil
return &MapResponse{MapResponse: mapResponse, PacketFilter: filterRules}, nil
}
type primaryRoutesCollector struct {