package netpol import ( "net" "strings" "testing" corev1 "k8s.io/api/core/v1" netv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" ) // These fixtures mirror the three NetworkPolicies live in the sjc001 // cluster on 2026-04-25. They serve as integration-shaped tests: the // translator + renderer must produce a sensible nft script for each. // // Source of truth (refresh by running `kubectl get netpol -A -o yaml`): // // - calico-apiserver/allow-apiserver // - remote-proxies/lodge-home-assistant-ingress // - storage/garage-admin-restrict // allowApiserverPolicy: TCP/5443 ingress to apiserver=true pods, no peer // restriction (allow-from-anywhere on that port). func allowApiserverPolicy() netv1.NetworkPolicy { tcp := corev1.ProtocolTCP port := intstr.FromInt32(5443) return netv1.NetworkPolicy{ ObjectMeta: metav1.ObjectMeta{Namespace: "calico-apiserver", Name: "allow-apiserver"}, Spec: netv1.NetworkPolicySpec{ PodSelector: metav1.LabelSelector{MatchLabels: map[string]string{"apiserver": "true"}}, PolicyTypes: []netv1.PolicyType{netv1.PolicyTypeIngress}, Ingress: []netv1.NetworkPolicyIngressRule{{ Ports: []netv1.NetworkPolicyPort{{Protocol: &tcp, Port: &port}}, }}, }, } } // lodgeHomeAssistantPolicy: TCP/8080 from any pod in the `edge` namespace // to pods labelled app=lodge-home-assistant. func lodgeHomeAssistantPolicy() netv1.NetworkPolicy { tcp := corev1.ProtocolTCP port := intstr.FromInt32(8080) return netv1.NetworkPolicy{ ObjectMeta: metav1.ObjectMeta{Namespace: "remote-proxies", Name: "lodge-home-assistant-ingress"}, Spec: netv1.NetworkPolicySpec{ PodSelector: metav1.LabelSelector{MatchLabels: map[string]string{"app": "lodge-home-assistant"}}, PolicyTypes: []netv1.PolicyType{netv1.PolicyTypeIngress}, Ingress: []netv1.NetworkPolicyIngressRule{{ From: []netv1.NetworkPolicyPeer{{ NamespaceSelector: &metav1.LabelSelector{ MatchLabels: map[string]string{"kubernetes.io/metadata.name": "edge"}, }, }}, Ports: []netv1.NetworkPolicyPort{{Protocol: &tcp, Port: &port}}, }}, }, } } // garageAdminPolicy: complex two-rule policy. // // 1. Allow TCP/{3900, 80, 3901} from anywhere. // 2. Allow TCP/3903 only from pods in `edge` or `storage`. func garageAdminPolicy() netv1.NetworkPolicy { tcp := corev1.ProtocolTCP p3900 := intstr.FromInt32(3900) p80 := intstr.FromInt32(80) p3901 := intstr.FromInt32(3901) p3903 := intstr.FromInt32(3903) return netv1.NetworkPolicy{ ObjectMeta: metav1.ObjectMeta{Namespace: "storage", Name: "garage-admin-restrict"}, Spec: netv1.NetworkPolicySpec{ PodSelector: metav1.LabelSelector{MatchLabels: map[string]string{"app": "garage"}}, PolicyTypes: []netv1.PolicyType{netv1.PolicyTypeIngress}, Ingress: []netv1.NetworkPolicyIngressRule{ { Ports: []netv1.NetworkPolicyPort{ {Protocol: &tcp, Port: &p3900}, {Protocol: &tcp, Port: &p80}, {Protocol: &tcp, Port: &p3901}, }, }, { From: []netv1.NetworkPolicyPeer{ {NamespaceSelector: &metav1.LabelSelector{ MatchLabels: map[string]string{"kubernetes.io/metadata.name": "edge"}, }}, {NamespaceSelector: &metav1.LabelSelector{ MatchLabels: map[string]string{"kubernetes.io/metadata.name": "storage"}, }}, }, Ports: []netv1.NetworkPolicyPort{{Protocol: &tcp, Port: &p3903}}, }, }, }, } } // TestClusterFixture_AllowApiserver — pod selected by the policy gets // isolated; the rendered script accepts TCP/5443 from anywhere. func TestClusterFixture_AllowApiserver(t *testing.T) { pod := Pod{ Namespace: "calico-apiserver", Name: "calico-apiserver-1", Labels: map[string]string{"apiserver": "true"}, HostIface: "flock00000001", IPs: []net.IP{mustIP("2001:db8::1")}, } out, err := Translate(Inputs{ LocalPods: []Pod{pod}, Policies: []netv1.NetworkPolicy{allowApiserverPolicy()}, }, nil) if err != nil { t.Fatal(err) } in, _ := isolationFor(out, "calico-apiserver/calico-apiserver-1") if !in { t.Fatalf("apiserver pod should be isolated for ingress") } script := Render(out) if !strings.Contains(script, "tcp dport 5443 accept") { t.Fatalf("expected TCP/5443 allow:\n%s", script) } // No peer filter — allow-all-on-port. if strings.Contains(script, "ip6 saddr {") || strings.Contains(script, "ip saddr {") { t.Fatalf("expected no peer filter for allow-from-anywhere:\n%s", script) } } // TestClusterFixture_LodgeHomeAssistant — pod isolated; only TCP/8080 // from edge namespace is allowed. func TestClusterFixture_LodgeHomeAssistant(t *testing.T) { pod := Pod{ Namespace: "remote-proxies", Name: "lodge-home-assistant-0", Labels: map[string]string{"app": "lodge-home-assistant"}, HostIface: "flock00000002", IPs: []net.IP{mustIP("2001:db8::2")}, } traefik := PeerPod{ Namespace: "edge", Name: "traefik-0", Labels: map[string]string{"app": "traefik"}, IPs: []net.IP{mustIP("2001:db8::aa")}, } stranger := PeerPod{ Namespace: "default", Name: "random", Labels: map[string]string{"app": "random"}, IPs: []net.IP{mustIP("2001:db8::bb")}, } out, err := Translate(Inputs{ LocalPods: []Pod{pod}, PeerPods: []PeerPod{traefik, stranger}, Namespaces: []Namespace{ {Name: "edge", Labels: map[string]string{"kubernetes.io/metadata.name": "edge"}}, {Name: "default", Labels: map[string]string{"kubernetes.io/metadata.name": "default"}}, {Name: "remote-proxies", Labels: map[string]string{"kubernetes.io/metadata.name": "remote-proxies"}}, }, Policies: []netv1.NetworkPolicy{lodgeHomeAssistantPolicy()}, }, nil) if err != nil { t.Fatal(err) } if len(out.Rules) != 1 { t.Fatalf("expected 1 rule, got %d", len(out.Rules)) } r := out.Rules[0] // Peer should be exactly traefik's IP, not stranger's. got := map[string]bool{} for _, c := range r.PeerCIDRs { got[c.IP.String()] = true } if !got["2001:db8::aa"] { t.Fatalf("traefik IP missing from rule: %v", got) } if got["2001:db8::bb"] { t.Fatalf("stranger IP leaked into rule") } script := Render(out) if !strings.Contains(script, "tcp dport 8080 accept") { t.Fatalf("expected TCP/8080 allow:\n%s", script) } } // TestClusterFixture_Garage — verifies the two-rule policy: // // 1. ports {3900, 80, 3901} accept from any peer // 2. port 3903 accept only from edge or storage namespaces func TestClusterFixture_Garage(t *testing.T) { pod := Pod{ Namespace: "storage", Name: "garage-0", Labels: map[string]string{"app": "garage"}, HostIface: "flock00000003", IPs: []net.IP{mustIP("2001:db8::3")}, } storagePeer := PeerPod{ Namespace: "storage", Name: "garage-1", Labels: map[string]string{"app": "garage"}, IPs: []net.IP{mustIP("2001:db8::31")}, } edgePeer := PeerPod{ Namespace: "edge", Name: "traefik-0", Labels: map[string]string{"app": "traefik"}, IPs: []net.IP{mustIP("2001:db8::41")}, } stranger := PeerPod{ Namespace: "default", Name: "random", Labels: map[string]string{"app": "random"}, IPs: []net.IP{mustIP("2001:db8::ff")}, } out, err := Translate(Inputs{ LocalPods: []Pod{pod}, PeerPods: []PeerPod{storagePeer, edgePeer, stranger}, Namespaces: []Namespace{ {Name: "edge", Labels: map[string]string{"kubernetes.io/metadata.name": "edge"}}, {Name: "storage", Labels: map[string]string{"kubernetes.io/metadata.name": "storage"}}, {Name: "default", Labels: map[string]string{"kubernetes.io/metadata.name": "default"}}, }, Policies: []netv1.NetworkPolicy{garageAdminPolicy()}, }, nil) if err != nil { t.Fatal(err) } // Two ingress rules in the source policy → two Rules out (one per // peer set, ports inline). if len(out.Rules) != 2 { t.Fatalf("expected 2 rules (one per ingress entry), got %d", len(out.Rules)) } script := Render(out) for _, want := range []string{ "tcp dport 3900 accept", "tcp dport 80 accept", "tcp dport 3901 accept", "tcp dport 3903 accept", } { if !strings.Contains(script, want) { t.Errorf("missing %q in script:\n%s", want, script) } } // The 3903 rule must carry a peer filter for both edge and storage // peer IPs but not the stranger. if !strings.Contains(script, "2001:db8::31/128") || !strings.Contains(script, "2001:db8::41/128") { t.Fatalf("expected edge+storage peer IPs in 3903 rule:\n%s", script) } if strings.Contains(script, "2001:db8::ff/128") { t.Fatalf("stranger IP must not appear:\n%s", script) } }