diff --git a/e2e/tests/multi-namespace-multinet.bats b/e2e/tests/multi-namespace-multinet.bats new file mode 100755 index 00000000..b5a568fb --- /dev/null +++ b/e2e/tests/multi-namespace-multinet.bats @@ -0,0 +1,116 @@ +#!/usr/bin/env bats + +# Note: +# This test case creates two namespaces, each with a different NetworkAttachmentDefinition +# and two pods per namespace. It tests that MultiNetworkPolicy works correctly across +# different namespaces with different network configurations. + +setup() { + cd $BATS_TEST_DIRNAME + load "common" + pod_a1_net1=$(get_net1_ip "test-namespace-a" "pod-1") + pod_a2_net1=$(get_net1_ip "test-namespace-a" "pod-2") + + pod_b1_net1=$(get_net1_ip "test-namespace-b" "pod-1") + pod_b2_net1=$(get_net1_ip "test-namespace-b" "pod-2") + + pod_c1_net1=$(get_net1_ip "test-namespace-c" "pod-1") + pod_c2_net1=$(get_net1_ip "test-namespace-c" "pod-2") + +} + +@test "setup multi-namespace test environments" { + # create test manifests + kubectl create -f multi-namespace-multinet.yml + + # verify all pods in namespace A are available + run kubectl -n test-namespace-a wait --all --for=condition=ready pod --timeout=${kubewait_timeout} + [ "$status" -eq "0" ] + + # verify all pods in namespace B are available + run kubectl -n test-namespace-b wait --all --for=condition=ready pod --timeout=${kubewait_timeout} + [ "$status" -eq "0" ] + + # wait for the iptables to be synced + sleep 3 +} + +@test "Allowed connectivity" { + run kubectl -n test-namespace-b exec pod-1 -- sh -c "echo x | nc -w 1 ${pod_a1_net1} 5555" + [ "$status" -eq "0" ] + + run kubectl -n test-namespace-a exec pod-1 -- sh -c "echo x | nc -w 1 ${pod_b2_net1} 5555" + [ "$status" -eq "0" ] +} + +@test "Denied connectivity" { + # a1 -> {a2,b1,c1,c2} + run kubectl -n test-namespace-a exec pod-1 -- sh -c "echo x | nc -w 1 ${pod_a2_net1} 5555" + [ "$status" -eq "1" ] + + run kubectl -n test-namespace-a exec pod-1 -- sh -c "echo x | nc -w 1 ${pod_b1_net1} 5555" + [ "$status" -eq "1" ] + + run kubectl -n test-namespace-a exec pod-1 -- sh -c "echo x | nc -w 1 ${pod_c1_net1} 5555" + [ "$status" -eq "1" ] + + run kubectl -n test-namespace-a exec pod-1 -- sh -c "echo x | nc -w 1 ${pod_c2_net1} 5555" + [ "$status" -eq "1" ] + + # {a2,b2,c1,c2} -> a1 + run kubectl -n test-namespace-a exec pod-2 -- sh -c "echo x | nc -w 1 ${pod_a1_net1} 5555" + [ "$status" -eq "1" ] + + run kubectl -n test-namespace-b exec pod-2 -- sh -c "echo x | nc -w 1 ${pod_a1_net1} 5555" + [ "$status" -eq "1" ] + + run kubectl -n test-namespace-c exec pod-1 -- sh -c "echo x | nc -w 1 ${pod_a1_net1} 5555" + [ "$status" -eq "1" ] + + run kubectl -n test-namespace-c exec pod-2 -- sh -c "echo x | nc -w 1 ${pod_a1_net1} 5555" + [ "$status" -eq "1" ] +} + +@test "Allowed by policy absence" { + # a2 -> {b1,b2,c1,c2} + run kubectl -n test-namespace-a exec pod-2 -- sh -c "echo x | nc -w 1 ${pod_b1_net1} 5555" + [ "$status" -eq "0" ] + + run kubectl -n test-namespace-a exec pod-2 -- sh -c "echo x | nc -w 1 ${pod_b2_net1} 5555" + [ "$status" -eq "0" ] + + run kubectl -n test-namespace-a exec pod-2 -- sh -c "echo x | nc -w 1 ${pod_c1_net1} 5555" + [ "$status" -eq "0" ] + + run kubectl -n test-namespace-a exec pod-2 -- sh -c "echo x | nc -w 1 ${pod_c2_net1} 5555" + [ "$status" -eq "0" ] + + # b1 -> {a2,b2,c1,c2} + run kubectl -n test-namespace-b exec pod-1 -- sh -c "echo x | nc -w 1 ${pod_a2_net1} 5555" + [ "$status" -eq "0" ] + + run kubectl -n test-namespace-b exec pod-1 -- sh -c "echo x | nc -w 1 ${pod_b2_net1} 5555" + [ "$status" -eq "0" ] + + run kubectl -n test-namespace-b exec pod-1 -- sh -c "echo x | nc -w 1 ${pod_c1_net1} 5555" + [ "$status" -eq "0" ] + + run kubectl -n test-namespace-b exec pod-1 -- sh -c "echo x | nc -w 1 ${pod_c2_net1} 5555" + [ "$status" -eq "0" ] +} + +@test "cleanup environments" { + # remove test manifests + kubectl delete -f multi-namespace-multinet.yml + run kubectl -n test-namespace-a wait --all --for=delete pod --timeout=${kubewait_timeout} + [ "$status" -eq "0" ] + run kubectl -n test-namespace-b wait --all --for=delete pod --timeout=${kubewait_timeout} + [ "$status" -eq "0" ] + + sleep 5 + # check that no iptables files in pod-iptables + pod_name=$(kubectl -n kube-system get pod -o wide | grep 'kind-worker' | grep multi-net | cut -f 1 -d ' ') + run kubectl -n kube-system exec ${pod_name} -- \ + sh -c "find /var/lib/multi-networkpolicy/iptables/ -name '*.iptables' | wc -l" + [ "$output" = "0" ] +} diff --git a/e2e/tests/multi-namespace-multinet.yml b/e2e/tests/multi-namespace-multinet.yml new file mode 100644 index 00000000..a1ba0742 --- /dev/null +++ b/e2e/tests/multi-namespace-multinet.yml @@ -0,0 +1,235 @@ +# ┌───────────┐ ┌───────────┐ ┌───────────┐ +# │namespace-a│ │namespace-b│ │namespace-c│ +# │ │ │ │ │ │ +# │ ┌───────┐ │ │ ┌───────┐ │ │ ┌───────┐ │ +# │ │ pod-1 │◀─────│ pod-1 │ │ │ │ pod-1 │ │ +# │ └───────┘────┐│ └───────┘ │ │ └───────┘ │ +# │ ┌───────┐ │ ││ ┌───────┐ │ │ ┌───────┐ │ +# │ │ pod-2 │ │ └─▶ pod-2 │ │ │ │ pod-2 │ │ +# │ └───────┘ │ │ └───────┘ │ │ └───────┘ │ +# └───────────┘ └───────────┘ └───────────┘ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: test-namespace-a + labels: + name: test-namespace-a +--- +apiVersion: v1 +kind: Namespace +metadata: + name: test-namespace-b + labels: + name: test-namespace-b +--- +apiVersion: v1 +kind: Namespace +metadata: + name: test-namespace-c + labels: + name: test-namespace-c +--- +apiVersion: "k8s.cni.cncf.io/v1" +kind: NetworkAttachmentDefinition +metadata: + namespace: test-namespace-a + name: macvlan1-namespace-a +spec: + config: '{ + "cniVersion": "0.3.1", + "name": "macvlan1-namespace-a", + "plugins": [ + { + "type": "macvlan", + "mode": "bridge", + "ipam":{ + "type":"host-local", + "subnet":"2.2.10.0/24", + "rangeStart":"2.2.10.10", + "rangeEnd":"2.2.10.19" + } + }] + }' +--- +apiVersion: "k8s.cni.cncf.io/v1" +kind: NetworkAttachmentDefinition +metadata: + namespace: test-namespace-b + name: macvlan1-namespace-b +spec: + config: '{ + "cniVersion": "0.3.1", + "name": "macvlan1-namespace-b", + "plugins": [ + { + "type": "macvlan", + "mode": "bridge", + "ipam":{ + "type":"host-local", + "subnet":"2.2.10.0/24", + "rangeStart":"2.2.10.20", + "rangeEnd":"2.2.10.29" + } + }] + }' +--- +apiVersion: "k8s.cni.cncf.io/v1" +kind: NetworkAttachmentDefinition +metadata: + namespace: test-namespace-c + name: macvlan1-namespace-c +spec: + config: '{ + "cniVersion": "0.3.1", + "name": "macvlan1-namespace-c", + "plugins": [ + { + "type": "macvlan", + "mode": "bridge", + "ipam":{ + "type":"host-local", + "subnet":"2.2.10.0/24", + "rangeStart":"2.2.10.30", + "rangeEnd":"2.2.10.39" + } + }] + }' +--- + + +# Pods in namespace A +apiVersion: v1 +kind: Pod +metadata: + name: pod-1 + namespace: test-namespace-a + annotations: + k8s.v1.cni.cncf.io/networks: macvlan1-namespace-a + labels: + name: pod-1 +spec: + containers: + - name: macvlan-worker1 + image: ghcr.io/k8snetworkplumbingwg/multi-networkpolicy-iptables:e2e-test + command: ["nc", "-klp", "5555"] + securityContext: + privileged: true +--- +apiVersion: v1 +kind: Pod +metadata: + name: pod-2 + namespace: test-namespace-a + annotations: + k8s.v1.cni.cncf.io/networks: macvlan1-namespace-a + labels: + name: pod-2 +spec: + containers: + - name: macvlan-worker1 + image: ghcr.io/k8snetworkplumbingwg/multi-networkpolicy-iptables:e2e-test + command: ["nc", "-klp", "5555"] + securityContext: + privileged: true +--- +# Pods in namespace B +apiVersion: v1 +kind: Pod +metadata: + name: pod-1 + namespace: test-namespace-b + annotations: + k8s.v1.cni.cncf.io/networks: macvlan1-namespace-b + labels: + name: pod-1 +spec: + containers: + - name: macvlan-worker1 + image: ghcr.io/k8snetworkplumbingwg/multi-networkpolicy-iptables:e2e-test + command: ["nc", "-klp", "5555"] + securityContext: + privileged: true +--- +apiVersion: v1 +kind: Pod +metadata: + name: pod-2 + namespace: test-namespace-b + annotations: + k8s.v1.cni.cncf.io/networks: macvlan1-namespace-b + labels: + name: pod-2 +spec: + containers: + - name: macvlan-worker1 + image: ghcr.io/k8snetworkplumbingwg/multi-networkpolicy-iptables:e2e-test + command: ["nc", "-klp", "5555"] + securityContext: + privileged: true +--- +# Pods in namespace C +apiVersion: v1 +kind: Pod +metadata: + name: pod-1 + namespace: test-namespace-c + annotations: + k8s.v1.cni.cncf.io/networks: macvlan1-namespace-c + labels: + name: pod-1 +spec: + containers: + - name: macvlan-worker1 + image: ghcr.io/k8snetworkplumbingwg/multi-networkpolicy-iptables:e2e-test + command: ["nc", "-klp", "5555"] + securityContext: + privileged: true +--- +apiVersion: v1 +kind: Pod +metadata: + name: pod-2 + namespace: test-namespace-c + annotations: + k8s.v1.cni.cncf.io/networks: macvlan1-namespace-c + labels: + name: pod-2 +spec: + containers: + - name: macvlan-worker1 + image: ghcr.io/k8snetworkplumbingwg/multi-networkpolicy-iptables:e2e-test + command: ["nc", "-klp", "5555"] + securityContext: + privileged: true +--- +apiVersion: k8s.cni.cncf.io/v1beta1 +kind: MultiNetworkPolicy +metadata: + name: test-multinetwork-policy-namespace-a + namespace: test-namespace-a + annotations: + k8s.v1.cni.cncf.io/policy-for: test-namespace-a/macvlan1-namespace-a,test-namespace-b/macvlan1-namespace-b,test-namespace-c/macvlan1-namespace-c +spec: + podSelector: + matchLabels: + name: pod-1 + ingress: + - from: + - podSelector: + matchLabels: + name: pod-1 + namespaceSelector: + matchLabels: + name: test-namespace-b + egress: + - to: + - podSelector: + matchLabels: + name: pod-2 + namespaceSelector: + matchLabels: + name: test-namespace-b + policyTypes: + - Ingress + - Egress