Skip to content

Commit 01edc29

Browse files
committed
fix #456: add IPv6 catchAll entry implicitly if no egress rule and no egress isolation
1 parent 2db0a78 commit 01edc29

File tree

4 files changed

+122
-31
lines changed

4 files changed

+122
-31
lines changed

controllers/policyendpoints_controller.go

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,6 @@ import (
3939
networking "k8s.io/api/networking/v1"
4040
)
4141

42-
const (
43-
defaultLocalConntrackCacheCleanupPeriodInSeconds = 300
44-
)
45-
4642
func log() logger.Logger {
4743
return logger.Get()
4844
}
@@ -84,11 +80,12 @@ func prometheusRegister() {
8480
}
8581

8682
// NewPolicyEndpointsReconciler constructs new PolicyEndpointReconciler
87-
func NewPolicyEndpointsReconciler(k8sClient client.Client, nodeIP string, ebpfClient ebpf.BpfClient) *PolicyEndpointsReconciler {
83+
func NewPolicyEndpointsReconciler(k8sClient client.Client, nodeIP string, ebpfClient ebpf.BpfClient, enableIPv6 bool) *PolicyEndpointsReconciler {
8884
r := &PolicyEndpointsReconciler{
8985
k8sClient: k8sClient,
9086
nodeIP: nodeIP,
9187
ebpfClient: ebpfClient,
88+
enableIPv6: enableIPv6,
9289
}
9390

9491
prometheusRegister()
@@ -111,6 +108,7 @@ type PolicyEndpointsReconciler struct {
111108
networkPolicyToPodIdentifierMap sync.Map
112109
//BPF Client instance
113110
ebpfClient ebpf.BpfClient
111+
enableIPv6 bool
114112
}
115113

116114
//+kubebuilder:rbac:groups=networking.k8s.aws,resources=policyendpoints,verbs=get;list;watch
@@ -244,13 +242,13 @@ func (r *PolicyEndpointsReconciler) reconcilePolicyEndpoint(ctx context.Context,
244242
if len(ingressRules) == 0 && !isIngressIsolated {
245243
//Add allow-all entry to Ingress rule set
246244
log().Info("No Ingress rules and no ingress isolation - Appending catch all entry")
247-
r.addCatchAllEntry(ctx, &ingressRules)
245+
r.addCatchAllEntry(&ingressRules)
248246
}
249247

250248
if len(egressRules) == 0 && !isEgressIsolated {
251249
//Add allow-all entry to Egress rule set
252250
log().Info("No Egress rules and no egress isolation - Appending catch all entry")
253-
r.addCatchAllEntry(ctx, &egressRules)
251+
r.addCatchAllEntry(&egressRules)
254252
}
255253

256254
// Setup/configure eBPF probes/maps for local pods
@@ -339,14 +337,14 @@ func (r *PolicyEndpointsReconciler) cleanupPod(ctx context.Context, targetPod ty
339337
// No active ingress rules for this pod, but we only should land here
340338
// if there are active egress rules. So, we need to add an allow-all entry to ingress rule set
341339
log().Info("No Ingress rules and no ingress isolation - Appending catch all entry")
342-
r.addCatchAllEntry(ctx, &ingressRules)
340+
r.addCatchAllEntry(&ingressRules)
343341
}
344342

345343
if noActiveEgressPolicies {
346344
// No active egress rules for this pod but we only should land here
347345
// if there are active ingress rules. So, we need to add an allow-all entry to egress rule set
348346
log().Info("No Egress rules and no egress isolation - Appending catch all entry")
349-
r.addCatchAllEntry(ctx, &egressRules)
347+
r.addCatchAllEntry(&egressRules)
350348
}
351349

352350
err = r.updateeBPFMaps(ctx, podIdentifier, ingressRules, egressRules)
@@ -647,18 +645,18 @@ func (r *PolicyEndpointsReconciler) deletePolicyEndpointFromPodIdentifierMap(ctx
647645
}
648646
}
649647

650-
func (r *PolicyEndpointsReconciler) addCatchAllEntry(ctx context.Context, firewallRules *[]fwrp.EbpfFirewallRules) {
648+
func (r *PolicyEndpointsReconciler) addCatchAllEntry(firewallRules *[]fwrp.EbpfFirewallRules) {
651649
//Add allow-all entry to firewall rule set
652-
catchAllRule := policyk8sawsv1.EndpointInfo{
653-
CIDR: "0.0.0.0/0",
650+
var catchAllCIDR string
651+
if r.enableIPv6 {
652+
catchAllCIDR = "::/0"
653+
} else {
654+
catchAllCIDR = "0.0.0.0/0"
654655
}
655656
*firewallRules = append(*firewallRules,
656657
fwrp.EbpfFirewallRules{
657-
IPCidr: catchAllRule.CIDR,
658-
L4Info: catchAllRule.Ports,
658+
IPCidr: policyk8sawsv1.NetworkAddress(catchAllCIDR),
659659
})
660-
661-
return
662660
}
663661

664662
// SetupWithManager sets up the controller with the Manager.
@@ -706,14 +704,14 @@ func (r *PolicyEndpointsReconciler) DeriveFireWallRulesPerPodIdentifier(podIdent
706704
// No active ingress rules for this pod, but we only should land here
707705
// if there are active egress rules. So, we need to add an allow-all entry to ingress rule set
708706
log().Info("No Ingress rules and no ingress isolation - Appending catch all entry")
709-
r.addCatchAllEntry(context.Background(), &ingressRules)
707+
r.addCatchAllEntry(&ingressRules)
710708
}
711709

712710
if len(egressRules) == 0 && !isEgressIsolated {
713711
// No active egress rules for this pod but we only should land here
714712
// if there are active ingress rules. So, we need to add an allow-all entry to egress rule set
715713
log().Info("No Egress rules and no egress isolation - Appending catch all entry")
716-
r.addCatchAllEntry(context.Background(), &egressRules)
714+
r.addCatchAllEntry(&egressRules)
717715
}
718716

719717
return ingressRules, egressRules, nil

controllers/policyendpoints_controller_test.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func TestPolicyEndpointReconcile(t *testing.T) {
4444

4545
t.Run("Reconcile call for Create PolicyEndpoint with PodEndpoint local to Node", func(t *testing.T) {
4646
mockClient := mock_client.NewMockClient(ctrl)
47-
policyEndpointReconciler := NewPolicyEndpointsReconciler(mockClient, nodeIp, &ebpf.MockBpfClient{})
47+
policyEndpointReconciler := NewPolicyEndpointsReconciler(mockClient, nodeIp, &ebpf.MockBpfClient{}, false)
4848

4949
policyEndpoint := getPolicyEndpoint("allow-all-egress", "my-namespace", []policyendpoint.PodEndpoint{p1N1, p2N1})
5050

@@ -90,7 +90,7 @@ func TestPolicyEndpointReconcile(t *testing.T) {
9090

9191
t.Run("Reconcile for Create and Delete PE", func(t *testing.T) {
9292
mockClient := mock_client.NewMockClient(ctrl)
93-
policyEndpointReconciler := NewPolicyEndpointsReconciler(mockClient, nodeIp, &ebpf.MockBpfClient{})
93+
policyEndpointReconciler := NewPolicyEndpointsReconciler(mockClient, nodeIp, &ebpf.MockBpfClient{}, false)
9494

9595
policyEndpoint := getPolicyEndpoint("allow-all-egress", "my-namespace", []policyendpoint.PodEndpoint{p1N1, p2N1})
9696

@@ -500,7 +500,7 @@ func TestDeriveIngressAndEgressFirewallRules(t *testing.T) {
500500
defer ctrl.Finish()
501501

502502
mockClient := mock_client.NewMockClient(ctrl)
503-
policyEndpointReconciler := NewPolicyEndpointsReconciler(mockClient, "", nil)
503+
policyEndpointReconciler := NewPolicyEndpointsReconciler(mockClient, "", nil, false)
504504
var policyEndpointsList []string
505505
policyEndpointsList = append(policyEndpointsList, tt.policyEndpointName)
506506
policyEndpointReconciler.podIdentifierToPolicyEndpointMap.Store(tt.podIdentifier, policyEndpointsList)
@@ -757,8 +757,7 @@ func TestAddCatchAllEntry(t *testing.T) {
757757
}
758758

759759
t.Run(tt.name, func(t *testing.T) {
760-
policyEndpointReconciler.addCatchAllEntry(context.Background(),
761-
&tt.firewallRules)
760+
policyEndpointReconciler.addCatchAllEntry(&tt.firewallRules)
762761
assert.Equal(t, tt.want, sampleFirewallRulesWithCatchAllEntry)
763762
})
764763
}
@@ -915,7 +914,7 @@ func TestArePoliciesAvailableInLocalCache(t *testing.T) {
915914
defer ctrl.Finish()
916915

917916
mockClient := mock_client.NewMockClient(ctrl)
918-
policyEndpointReconciler := NewPolicyEndpointsReconciler(mockClient, "", nil)
917+
policyEndpointReconciler := NewPolicyEndpointsReconciler(mockClient, "", nil, false)
919918
var policyEndpointsList []string
920919
policyEndpointsList = append(policyEndpointsList, tt.policyEndpointName...)
921920
policyEndpointReconciler.podIdentifierToPolicyEndpointMap.Store(tt.podIdentifier, policyEndpointsList)
@@ -1160,7 +1159,7 @@ func TestDeriveFireWallRulesPerPodIdentifier(t *testing.T) {
11601159
defer ctrl.Finish()
11611160

11621161
mockClient := mock_client.NewMockClient(ctrl)
1163-
policyEndpointReconciler := NewPolicyEndpointsReconciler(mockClient, "", nil)
1162+
policyEndpointReconciler := NewPolicyEndpointsReconciler(mockClient, "", nil, false)
11641163
var policyEndpointsList []string
11651164
policyEndpointsList = append(policyEndpointsList, tt.policyEndpointName)
11661165
policyEndpointReconciler.podIdentifierToPolicyEndpointMap.Store(tt.podIdentifier, policyEndpointsList)

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ func main() {
111111
ctrlConfig.EnableIPv6, ctrlConfig.ConntrackCacheCleanupPeriod, ctrlConfig.ConntrackCacheTableSize, npMode, isMultiNICEnabled))
112112
ebpfClient.ReAttachEbpfProbes()
113113

114-
policyEndpointController = controllers.NewPolicyEndpointsReconciler(mgr.GetClient(), nodeIP, ebpfClient)
114+
policyEndpointController = controllers.NewPolicyEndpointsReconciler(mgr.GetClient(), nodeIP, ebpfClient, ctrlConfig.EnableIPv6)
115115

116116
if err = policyEndpointController.SetupWithManager(ctx, mgr); err != nil {
117117
log.Errorf("unable to create controller PolicyEndpoints %v", err)

pkg/fwruleprocessor/fw_rule_processor_test.go

Lines changed: 99 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,10 @@ import (
1111
corev1 "k8s.io/api/core/v1"
1212
)
1313

14-
func TestFWRuleProcessor_ComputeMapEntriesFromEndpointRules(t *testing.T) {
14+
func TestFWRuleProcessor_ComputeMapEntriesFromEndpointRules_IPv4(t *testing.T) {
1515
protocolTCP := corev1.ProtocolTCP
16-
//protocolUDP := corev1.ProtocolUDP
17-
//protocolSCTP := corev1.ProtocolSCTP
1816

1917
var testIP v1alpha1.NetworkAddress
20-
var gotKeys []string
2118

2219
nodeIP := "10.1.1.1"
2320
_, nodeIPCIDR, _ := net.ParseCIDR(nodeIP + "/32")
@@ -28,6 +25,8 @@ func TestFWRuleProcessor_ComputeMapEntriesFromEndpointRules(t *testing.T) {
2825
testIP = "10.1.1.2/32"
2926
_, testIPCIDR, _ := net.ParseCIDR(string(testIP))
3027

28+
_, catchAllCIDR, _ := net.ParseCIDR(string("0.0.0.0/0"))
29+
3130
testIPKey := utils.ComputeTrieKey(*testIPCIDR, false)
3231
type args struct {
3332
firewallRules []EbpfFirewallRules
@@ -56,11 +55,106 @@ func TestFWRuleProcessor_ComputeMapEntriesFromEndpointRules(t *testing.T) {
5655
},
5756
want: []string{string(nodeIPKey), string(testIPKey)},
5857
},
58+
{
59+
name: "CatchAll CIDR",
60+
args: args{
61+
[]EbpfFirewallRules{
62+
{
63+
IPCidr: "0.0.0.0/0",
64+
},
65+
},
66+
},
67+
want: []string{string(nodeIPKey), string(utils.ComputeTrieKey(*catchAllCIDR, false))},
68+
},
69+
}
70+
71+
for _, tt := range tests {
72+
t.Run(tt.name, func(t *testing.T) {
73+
got, err := NewFirewallRuleProcessor(nodeIP, "/32", false).ComputeMapEntriesFromEndpointRules(tt.args.firewallRules)
74+
var gotKeys []string
75+
if tt.wantErr != nil {
76+
assert.EqualError(t, err, tt.wantErr.Error())
77+
} else {
78+
for key, _ := range got {
79+
gotKeys = append(gotKeys, key)
80+
}
81+
sort.Strings(tt.want)
82+
sort.Strings(gotKeys)
83+
assert.Equal(t, tt.want, gotKeys)
84+
}
85+
})
86+
}
87+
}
88+
89+
func TestFWRuleProcessor_ComputeMapEntriesFromEndpointRules_IPv6(t *testing.T) {
90+
protocolTCP := corev1.ProtocolTCP
91+
92+
nodeIP := "2001:db8:abcd:0012::1"
93+
_, nodeIPCIDR, _ := net.ParseCIDR(nodeIP + "/128")
94+
nodeIPKey := utils.ComputeTrieKey(*nodeIPCIDR, true)
95+
96+
var testPort int32
97+
testPort = 80
98+
_, testIPCIDR, _ := net.ParseCIDR("2001:db8:abcd:0012::10/128")
99+
100+
_, catchAllCIDR, _ := net.ParseCIDR("::/0")
101+
102+
testIPKey := utils.ComputeTrieKey(*testIPCIDR, true)
103+
type args struct {
104+
firewallRules []EbpfFirewallRules
105+
}
106+
107+
tests := []struct {
108+
name string
109+
args args
110+
want []string
111+
wantErr error
112+
}{
113+
{
114+
name: "CIDR with Port and Protocol",
115+
args: args{
116+
[]EbpfFirewallRules{
117+
{
118+
IPCidr: "2001:db8:abcd:0012::10/128",
119+
L4Info: []v1alpha1.Port{
120+
{
121+
Protocol: &protocolTCP,
122+
Port: &testPort,
123+
},
124+
},
125+
},
126+
},
127+
},
128+
want: []string{string(nodeIPKey), string(testIPKey)},
129+
},
130+
{
131+
name: "CatchAll IPv4 CIDR",
132+
args: args{
133+
[]EbpfFirewallRules{
134+
{
135+
IPCidr: "::/0",
136+
},
137+
},
138+
},
139+
want: []string{string(nodeIPKey), string(utils.ComputeTrieKey(*catchAllCIDR, true))},
140+
},
141+
{
142+
name: "CatchAll CIDR IPv4 ignored in rule computation",
143+
args: args{
144+
[]EbpfFirewallRules{
145+
{
146+
IPCidr: "0.0.0.0/0",
147+
},
148+
},
149+
},
150+
want: []string{string(nodeIPKey)},
151+
},
59152
}
60153

61154
for _, tt := range tests {
62155
t.Run(tt.name, func(t *testing.T) {
63-
got, err := NewFirewallRuleProcessor("10.1.1.1", "/32", false).ComputeMapEntriesFromEndpointRules(tt.args.firewallRules)
156+
got, err := NewFirewallRuleProcessor(nodeIP, "/128", true).ComputeMapEntriesFromEndpointRules(tt.args.firewallRules)
157+
var gotKeys []string
64158
if tt.wantErr != nil {
65159
assert.EqualError(t, err, tt.wantErr.Error())
66160
} else {

0 commit comments

Comments
 (0)