Skip to content

Commit 13c3546

Browse files
committed
int-test: Add integration test with separated networks
Signed-off-by: Andrea Panattoni <apanatto@redhat.com>
1 parent 737247e commit 13c3546

File tree

3 files changed

+308
-3
lines changed

3 files changed

+308
-3
lines changed

pkg/nftables/enforce.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func (n *NFTables) enforcePolicy(ctx context.Context, pod *corev1.Pod, interface
4141
// Find the interfaces on the pod that belong to the networks of the policy (Policy-for annotation)
4242
matchedInterfaces := getMatchedInterfaces(interfaces, policy.Networks)
4343
if len(matchedInterfaces) == 0 {
44-
logger.Info("No matched interfaces found, skipping")
44+
logger.Info("No matched interfaces found, skipping", "policyNetworks", policy.Networks, "interfaces", interfaces)
4545
return nil
4646
}
4747

pkg/nftables/nftables_integration_test.go

Lines changed: 185 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/containernetworking/plugins/pkg/ns"
1212
"github.com/containernetworking/plugins/pkg/testutils"
1313
"github.com/go-logr/logr"
14+
"github.com/go-logr/logr/funcr"
1415
multiv1beta1 "github.com/k8snetworkplumbingwg/multi-networkpolicy/pkg/apis/k8s.cni.cncf.io/v1beta1"
1516
. "github.com/onsi/ginkgo/v2"
1617
. "github.com/onsi/gomega"
@@ -24,10 +25,17 @@ import (
2425
"github.com/k8snetworkplumbingwg/multi-network-policy-nftables/pkg/datastore"
2526
)
2627

28+
var logger logr.Logger = funcr.New(func(prefix, args string) {
29+
// if prefix == "" {
30+
// GinkgoWriter.Printf("%s\n", args)
31+
// } else {
32+
GinkgoWriter.Printf("%s %s\n", prefix, args)
33+
// }
34+
}, funcr.Options{Verbosity: 6})
35+
2736
var _ = Describe("NFTables Simple Integration Tests", func() {
2837
var (
2938
ctx context.Context
30-
logger logr.Logger
3139
targetPod *corev1.Pod
3240
matchedInterfaces []Interface
3341

@@ -44,7 +52,6 @@ var _ = Describe("NFTables Simple Integration Tests", func() {
4452

4553
BeforeEach(func() {
4654
ctx = context.Background()
47-
logger = logr.Discard()
4855

4956
// Create target pod (the one policies apply to)
5057
targetPod = &corev1.Pod{
@@ -280,6 +287,182 @@ var _ = Describe("NFTables Simple Integration Tests", func() {
280287
})
281288
})
282289

290+
var _ = FDescribe("Multiple NetworkAttachmentDefinitions Integration Tests", func() {
291+
/*
292+
┌─────────────┐ ┌─────────────┐
293+
│ << NAD >> │ │ << NAD >> │
294+
│ RedNetwork │ │ BlueNetwork │
295+
│ │ │ │
296+
└─────────────┘ └─────────────┘
297+
298+
┌────────────┐ ┌─────────────┐ ┌─────────────┐ ┌────────────┐
299+
│ │ │ │ │ │ │ │
300+
│ red-pod-a ├──┐ │ << MNP >> │ │ << MNP >> │ ┌──┼ blue-pod-a │
301+
│ │ │ │ RedPolicy │ │ BluePolicy │ │ │ │
302+
└────────────┘ │ │ │ │ │ │ └────────────┘
303+
│ └─────────────┘ └─────────────┘ │
304+
┌────────────┐ │ │ ┌────────────┐
305+
│ │ │ 10.0.1.0/24 10.0.2.0/24 │ │ │
306+
│ red-pod-b ├──┴───────────┐ ┌──────────┴──┤ blue-pod-b │
307+
│ │ ┌──┬──┴─────┬──────┬──────┴──┬──┐ │ │
308+
└────────────┘ │ │ ethred │ │ ethblue │ │ └────────────┘
309+
│ └────────┘ └─────────┘ │
310+
│ │
311+
│ TargetPod │
312+
│ │
313+
└───────────────────────────────┘
314+
*/
315+
var (
316+
targetPod *corev1.Pod
317+
redPodA *corev1.Pod
318+
redPodB *corev1.Pod
319+
bluePodA *corev1.Pod
320+
bluePodB *corev1.Pod
321+
redInterfaces []Interface
322+
blueInterfaces []Interface
323+
)
324+
325+
BeforeEach(func() {
326+
// Create target pod (the one policies apply to)
327+
targetPod = &corev1.Pod{
328+
ObjectMeta: metav1.ObjectMeta{
329+
Name: "target-pod",
330+
Namespace: "test-ns",
331+
Labels: map[string]string{"app": "target-pod"},
332+
Annotations: map[string]string{
333+
"k8s.v1.cni.cncf.io/networks": "red-net,blue-net",
334+
"k8s.v1.cni.cncf.io/network-status": `[{"name":"test-ns/red-net","interface":"ethred","ips":["10.0.1.1","2001:db8:1::1"],"dns":{}},{"name":"test-ns/blue-net","interface":"ethblue","ips":["10.0.2.1","2001:db8:2::1"],"dns":{}}]`,
335+
},
336+
},
337+
Spec: corev1.PodSpec{HostNetwork: false},
338+
Status: corev1.PodStatus{Phase: corev1.PodRunning},
339+
}
340+
341+
redInterfaces = []Interface{{Name: "ethred", Network: "test-ns/red-net", IPs: []string{"10.0.1.1", "2001:db8:1::1"}}}
342+
blueInterfaces = []Interface{{Name: "ethblue", Network: "test-ns/blue-net", IPs: []string{"10.0.2.1", "2001:db8:2::1"}}}
343+
344+
// Create test pods for comprehensive test
345+
redPodA = createPodSingleInterface("red-pod-a", "test-ns/red-net",
346+
map[string]string{"app": "red-pod-a"},
347+
"10.0.1.10", "2001:db8:1::10")
348+
349+
redPodB = createPodSingleInterface("red-pod-b", "test-ns/red-net",
350+
map[string]string{"app": "red-pod-b"},
351+
"10.0.1.11", "2001:db8:1::11")
352+
353+
bluePodA = createPodSingleInterface("blue-pod-a", "test-ns/blue-net",
354+
map[string]string{"app": "blue-pod-a"},
355+
"10.0.2.10", "2001:db8:2::10")
356+
357+
bluePodB = createPodSingleInterface("blue-pod-b", "test-ns/blue-net",
358+
map[string]string{"app": "blue-pod-b"},
359+
"10.0.2.11", "2001:db8:2::11")
360+
})
361+
362+
It("should handle policies on different networks", func(ctx context.Context) {
363+
defer GinkgoRecover()
364+
365+
netNS, err := testutils.NewNS()
366+
Expect(err).NotTo(HaveOccurred())
367+
defer netNS.Close()
368+
369+
err = netNS.Do(func(_ ns.NetNS) error {
370+
runtime.LockOSThread()
371+
defer runtime.UnlockOSThread()
372+
373+
nftablesWithPods := &NFTables{
374+
Client: createFakeClient([]*corev1.Pod{targetPod, redPodA, redPodB, bluePodA, bluePodB}),
375+
}
376+
377+
redPolicy := &datastore.Policy{
378+
Name: "red-policy",
379+
Namespace: "test-ns",
380+
Networks: []string{"test-ns/red-net"},
381+
Spec: multiv1beta1.MultiNetworkPolicySpec{
382+
PodSelector: metav1.LabelSelector{
383+
MatchLabels: map[string]string{"app": "target-pod"},
384+
},
385+
PolicyTypes: []multiv1beta1.MultiPolicyType{
386+
multiv1beta1.PolicyTypeIngress,
387+
multiv1beta1.PolicyTypeEgress,
388+
},
389+
Ingress: []multiv1beta1.MultiNetworkPolicyIngressRule{{
390+
From: []multiv1beta1.MultiNetworkPolicyPeer{createPolicyPeer(map[string]string{"app": "red-pod-a"})},
391+
}},
392+
Egress: []multiv1beta1.MultiNetworkPolicyEgressRule{{
393+
To: []multiv1beta1.MultiNetworkPolicyPeer{createPolicyPeer(map[string]string{"app": "red-pod-b"})},
394+
}},
395+
},
396+
}
397+
398+
bluePolicy := &datastore.Policy{
399+
Name: "blue-policy",
400+
Namespace: "test-ns",
401+
Networks: []string{"test-ns/blue-net"},
402+
Spec: multiv1beta1.MultiNetworkPolicySpec{
403+
PodSelector: metav1.LabelSelector{
404+
MatchLabels: map[string]string{"app": "target-pod"},
405+
},
406+
PolicyTypes: []multiv1beta1.MultiPolicyType{
407+
multiv1beta1.PolicyTypeIngress,
408+
multiv1beta1.PolicyTypeEgress,
409+
},
410+
Ingress: []multiv1beta1.MultiNetworkPolicyIngressRule{{
411+
From: []multiv1beta1.MultiNetworkPolicyPeer{createPolicyPeer(map[string]string{"app": "blue-pod-a"})},
412+
}},
413+
Egress: []multiv1beta1.MultiNetworkPolicyEgressRule{{
414+
To: []multiv1beta1.MultiNetworkPolicyPeer{createPolicyPeer(map[string]string{"app": "blue-pod-b"})},
415+
}},
416+
},
417+
}
418+
419+
err = nftablesWithPods.enforcePolicy(ctx, targetPod, redInterfaces, redPolicy, logger)
420+
if err != nil {
421+
return err
422+
}
423+
424+
err = nftablesWithPods.enforcePolicy(ctx, targetPod, blueInterfaces, bluePolicy, logger)
425+
if err != nil {
426+
return err
427+
}
428+
429+
err = verifyNFTablesGoldenFile("multiple-networks-policy.nft")
430+
if err != nil {
431+
return err
432+
}
433+
434+
return nil
435+
})
436+
Expect(err).NotTo(HaveOccurred())
437+
})
438+
})
439+
440+
func createPolicyPeer(matchLabels map[string]string) multiv1beta1.MultiNetworkPolicyPeer {
441+
return multiv1beta1.MultiNetworkPolicyPeer{
442+
PodSelector: &metav1.LabelSelector{
443+
MatchLabels: matchLabels,
444+
},
445+
}
446+
}
447+
448+
func createPodSingleInterface(name, network string, labels map[string]string, ipv4Net, ipv6Net string) *corev1.Pod {
449+
networkStatus := fmt.Sprintf(`[{"name":"%s","interface":"eth1","ips":["%s","%s"],"dns":{}}]`, network, ipv4Net, ipv6Net)
450+
451+
return &corev1.Pod{
452+
ObjectMeta: metav1.ObjectMeta{
453+
Name: name,
454+
Namespace: "test-ns",
455+
Labels: labels,
456+
Annotations: map[string]string{
457+
"k8s.v1.cni.cncf.io/networks": network,
458+
"k8s.v1.cni.cncf.io/network-status": networkStatus,
459+
},
460+
},
461+
Spec: corev1.PodSpec{HostNetwork: false},
462+
Status: corev1.PodStatus{Phase: corev1.PodRunning},
463+
}
464+
}
465+
283466
// Helper function to create a dual-stack pod
284467
func createDualStackPod(name, namespace string, labels map[string]string, ipv4Net1, ipv4Net2, ipv6Net1, ipv6Net2 string) *corev1.Pod {
285468
// We assume that the network attachment definition is common. There is no restriction per namespace
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
table inet multi_networkpolicy {
2+
comment "MultiNetworkPolicy"
3+
set smi-7cef63aba7df2a3e78ee4cae8eef6bfe {
4+
type ifname
5+
comment "Managed interfaces set for test-ns/red-policy"
6+
elements = { "ethred" }
7+
}
8+
9+
set snp-7cef63aba7df2a3e78ee4cae8eef6bfe_ingress_ipv4_ethred_0 {
10+
type ipv4_addr
11+
comment "Addresses for test-ns/red-policy"
12+
elements = { 10.0.1.10 }
13+
}
14+
15+
set snp-7cef63aba7df2a3e78ee4cae8eef6bfe_ingress_ipv6_ethred_0 {
16+
type ipv6_addr
17+
comment "Addresses for test-ns/red-policy"
18+
elements = { 2001:db8:1::10 }
19+
}
20+
21+
set snp-7cef63aba7df2a3e78ee4cae8eef6bfe_egress_ipv4_ethred_0 {
22+
type ipv4_addr
23+
comment "Addresses for test-ns/red-policy"
24+
elements = { 10.0.1.11 }
25+
}
26+
27+
set snp-7cef63aba7df2a3e78ee4cae8eef6bfe_egress_ipv6_ethred_0 {
28+
type ipv6_addr
29+
comment "Addresses for test-ns/red-policy"
30+
elements = { 2001:db8:1::11 }
31+
}
32+
33+
set smi-b458cc915046bc2c60158623677c6364 {
34+
type ifname
35+
comment "Managed interfaces set for test-ns/blue-policy"
36+
elements = { "ethblue" }
37+
}
38+
39+
set snp-b458cc915046bc2c60158623677c6364_ingress_ipv4_ethblue_0 {
40+
type ipv4_addr
41+
comment "Addresses for test-ns/blue-policy"
42+
elements = { 10.0.2.10 }
43+
}
44+
45+
set snp-b458cc915046bc2c60158623677c6364_ingress_ipv6_ethblue_0 {
46+
type ipv6_addr
47+
comment "Addresses for test-ns/blue-policy"
48+
elements = { 2001:db8:2::10 }
49+
}
50+
51+
set snp-b458cc915046bc2c60158623677c6364_egress_ipv4_ethblue_0 {
52+
type ipv4_addr
53+
comment "Addresses for test-ns/blue-policy"
54+
elements = { 10.0.2.11 }
55+
}
56+
57+
set snp-b458cc915046bc2c60158623677c6364_egress_ipv6_ethblue_0 {
58+
type ipv6_addr
59+
comment "Addresses for test-ns/blue-policy"
60+
elements = { 2001:db8:2::11 }
61+
}
62+
63+
chain input {
64+
comment "Input Dispatcher"
65+
type filter hook input priority filter; policy accept;
66+
iifname @smi-7cef63aba7df2a3e78ee4cae8eef6bfe jump ingress comment "test-ns/red-policy"
67+
iifname @smi-b458cc915046bc2c60158623677c6364 jump ingress comment "test-ns/blue-policy"
68+
}
69+
70+
chain output {
71+
comment "Output Dispatcher"
72+
type filter hook output priority filter; policy accept;
73+
oifname @smi-7cef63aba7df2a3e78ee4cae8eef6bfe jump egress comment "test-ns/red-policy"
74+
oifname @smi-b458cc915046bc2c60158623677c6364 jump egress comment "test-ns/blue-policy"
75+
}
76+
77+
chain ingress {
78+
comment "Ingress Policies"
79+
ct state established,related accept comment "Connection tracking"
80+
jump common-ingress comment "Jump to common"
81+
jump cnp-7cef63aba7df2a3e78ee4cae8eef6bfe comment "test-ns/red-policy"
82+
jump cnp-b458cc915046bc2c60158623677c6364 comment "test-ns/blue-policy"
83+
drop comment "Drop rule"
84+
}
85+
86+
chain common-ingress {
87+
comment "Common Policies"
88+
}
89+
90+
chain egress {
91+
comment "Egress Policies"
92+
ct state established,related accept comment "Connection tracking"
93+
jump common-egress comment "Jump to common"
94+
jump cnp-7cef63aba7df2a3e78ee4cae8eef6bfe comment "test-ns/red-policy"
95+
jump cnp-b458cc915046bc2c60158623677c6364 comment "test-ns/blue-policy"
96+
drop comment "Drop rule"
97+
}
98+
99+
chain common-egress {
100+
comment "Common Policies"
101+
}
102+
103+
chain cnp-7cef63aba7df2a3e78ee4cae8eef6bfe {
104+
comment "MultiNetworkPolicy test-ns/red-policy"
105+
iifname "ethred" ip saddr 10.0.1.1 accept
106+
iifname "ethred" ip6 saddr 2001:db8:1::1 accept
107+
iifname "ethred" ip saddr @snp-7cef63aba7df2a3e78ee4cae8eef6bfe_ingress_ipv4_ethred_0 accept
108+
iifname "ethred" ip6 saddr @snp-7cef63aba7df2a3e78ee4cae8eef6bfe_ingress_ipv6_ethred_0 accept
109+
oifname "ethred" ip daddr @snp-7cef63aba7df2a3e78ee4cae8eef6bfe_egress_ipv4_ethred_0 accept
110+
oifname "ethred" ip6 daddr @snp-7cef63aba7df2a3e78ee4cae8eef6bfe_egress_ipv6_ethred_0 accept
111+
}
112+
113+
chain cnp-b458cc915046bc2c60158623677c6364 {
114+
comment "MultiNetworkPolicy test-ns/blue-policy"
115+
iifname "ethblue" ip saddr 10.0.2.1 accept
116+
iifname "ethblue" ip6 saddr 2001:db8:2::1 accept
117+
iifname "ethblue" ip saddr @snp-b458cc915046bc2c60158623677c6364_ingress_ipv4_ethblue_0 accept
118+
iifname "ethblue" ip6 saddr @snp-b458cc915046bc2c60158623677c6364_ingress_ipv6_ethblue_0 accept
119+
oifname "ethblue" ip daddr @snp-b458cc915046bc2c60158623677c6364_egress_ipv4_ethblue_0 accept
120+
oifname "ethblue" ip6 daddr @snp-b458cc915046bc2c60158623677c6364_egress_ipv6_ethblue_0 accept
121+
}
122+
}

0 commit comments

Comments
 (0)