Skip to content

Commit a65146e

Browse files
committed
Fix a bug where detected TCP traffic from pods short time before their deletion time could be labeled as incoming traffic from the internet
1 parent 88d4933 commit a65146e

File tree

2 files changed

+61
-5
lines changed

2 files changed

+61
-5
lines changed

src/mapper/pkg/kubefinder/kubefinder.go

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package kubefinder
33
import (
44
"context"
55
"fmt"
6+
"github.com/hashicorp/golang-lru/v2/expirable"
67
"github.com/otterize/intents-operator/src/shared/errors"
78
"github.com/otterize/intents-operator/src/shared/serviceidresolver"
89
"github.com/otterize/network-mapper/src/mapper/pkg/config"
@@ -37,22 +38,30 @@ type KubeFinder struct {
3738
mgr manager.Manager
3839
client client.Client
3940
serviceIdResolver *serviceidresolver.Resolver
41+
SeenIPsTTLCache *expirable.LRU[string, struct{}]
4042
}
4143

42-
var ErrNoPodFound = errors.NewSentinelError("no pod found")
43-
var ErrFoundMoreThanOnePod = errors.NewSentinelError("ip belongs to more than one pod")
44-
var ErrFoundMoreThanOneService = errors.NewSentinelError("ip belongs to more than one service")
45-
var ErrServiceNotFound = errors.NewSentinelError("service not found")
44+
var (
45+
ErrNoPodFound = errors.NewSentinelError("no pod found")
46+
ErrFoundMoreThanOnePod = errors.NewSentinelError("ip belongs to more than one pod")
47+
ErrFoundMoreThanOneService = errors.NewSentinelError("ip belongs to more than one service")
48+
ErrServiceNotFound = errors.NewSentinelError("service not found")
49+
)
4650

4751
func NewKubeFinder(ctx context.Context, mgr manager.Manager) (*KubeFinder, error) {
4852
indexer := &KubeFinder{client: mgr.GetClient(), mgr: mgr, serviceIdResolver: serviceidresolver.NewResolver(mgr.GetClient())}
53+
indexer.initCache()
4954
err := indexer.initIndexes(ctx)
5055
if err != nil {
5156
return nil, errors.Wrap(err)
5257
}
5358
return indexer, nil
5459
}
5560

61+
func (k *KubeFinder) initCache() {
62+
k.SeenIPsTTLCache = expirable.NewLRU[string, struct{}](2000, nil, time.Minute*10)
63+
}
64+
5665
func (k *KubeFinder) initIndexes(ctx context.Context) error {
5766
err := k.mgr.GetCache().IndexField(ctx, &corev1.Pod{}, podIPIndexField, func(object client.Object) []string {
5867
res := make([]string, 0)
@@ -80,6 +89,7 @@ func (k *KubeFinder) initIndexes(ctx context.Context) error {
8089
}
8190

8291
for _, ip := range pod.Status.PodIPs {
92+
k.SeenIPsTTLCache.Add(ip.IP, struct{}{})
8393
res = append(res, ip.IP)
8494
}
8595
return res
@@ -464,7 +474,12 @@ func (k *KubeFinder) ResolveOtterizeIdentityForService(ctx context.Context, svc
464474
}
465475

466476
func (k *KubeFinder) IsSrcIpClusterInternal(ctx context.Context, ip string) (bool, error) {
467-
// Known issue: this function is currently missing support for services/endpoints, node.PodCIDR, and pods that were deleted.
477+
// Known issue: this function is currently missing support for services/endpoints, node.PodCIDR
478+
479+
wasPodIp := k.WasPodIP(ip)
480+
if wasPodIp {
481+
return true, nil
482+
}
468483

469484
isNode, err := k.IsNodeIP(ctx, ip)
470485
if err != nil {
@@ -502,6 +517,10 @@ func (k *KubeFinder) IsPodIp(ctx context.Context, ip string) (bool, error) {
502517
return len(pods.Items) > 0, nil
503518
}
504519

520+
func (k *KubeFinder) WasPodIP(ip string) bool {
521+
return k.SeenIPsTTLCache.Contains(ip)
522+
}
523+
505524
func (k *KubeFinder) IsNodeIP(ctx context.Context, ip string) (bool, error) {
506525
var nodes corev1.NodeList
507526
err := k.client.List(ctx, &nodes, client.MatchingFields{nodeIPIndexField: ip})

src/mapper/pkg/kubefinder/kubefinder_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,43 @@ func (s *KubeFinderTestSuite) TestResolveServiceAddressToIps() {
7575
s.Require().ElementsMatch(lo.Map(pods, func(p corev1.Pod, _ int) string { return p.Status.PodIP }), lo.Map(pods4444, func(p *corev1.Pod, _ int) string { return p.Status.PodIP }))
7676
}
7777

78+
func (s *KubeFinderTestSuite) TestIsSrcIpClusterInternal() {
79+
pod := s.AddPod("test-pod", "1.1.1.1", nil, nil)
80+
s.Require().True(s.Mgr.GetCache().WaitForCacheSync(context.Background()))
81+
82+
// Check with existing pod's ip
83+
isInternal, err := s.kubeFinder.IsSrcIpClusterInternal(context.Background(), "1.1.1.1")
84+
s.Require().NoError(err)
85+
s.Require().True(isInternal)
86+
87+
// Check with non-existing pod's ip
88+
isInternal, err = s.kubeFinder.IsSrcIpClusterInternal(context.Background(), "8.8.8.8")
89+
s.Require().NoError(err)
90+
s.Require().False(isInternal)
91+
92+
err = s.Mgr.GetClient().Delete(context.Background(), pod)
93+
s.Require().NoError(err)
94+
s.Require().True(s.Mgr.GetCache().WaitForCacheSync(context.Background()))
95+
96+
// Check pod doesn't exist in the manager's cache
97+
pod, err = s.kubeFinder.ResolveIPToPod(context.Background(), "1.1.1.1")
98+
s.Require().Nil(pod)
99+
s.Require().Error(err)
100+
101+
// Check isInternal with the deleted pod's ip
102+
isInternal, err = s.kubeFinder.IsSrcIpClusterInternal(context.Background(), "1.1.1.1")
103+
s.Require().NoError(err)
104+
s.Require().True(isInternal)
105+
106+
// Reset the cache
107+
s.kubeFinder.initCache()
108+
109+
// Check isInternal with the deleted pod's ip after cache reset
110+
isInternal, err = s.kubeFinder.IsSrcIpClusterInternal(context.Background(), "1.1.1.1")
111+
s.Require().NoError(err)
112+
s.Require().False(isInternal)
113+
}
114+
78115
func TestKubeFinderTestSuite(t *testing.T) {
79116
suite.Run(t, new(KubeFinderTestSuite))
80117
}

0 commit comments

Comments
 (0)