diff --git a/README.md b/README.md index 50da1221..19b97ba0 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ MultiNetworkPolicy creates DaemonSet and it runs `multi-networkpolicy-iptables` ## TODO * Bugfixing +* IPv6 support * (TBD) ## Contact Us diff --git a/deploy.yml b/deploy.yml index fb795b3b..05a2985c 100644 --- a/deploy.yml +++ b/deploy.yml @@ -107,7 +107,7 @@ spec: securityContext: privileged: true capabilities: - add: ["SYS_ADMIN", "SYS_NET_ADMIN"] + add: ["SYS_ADMIN", "NET_ADMIN"] volumeMounts: - name: host mountPath: /host diff --git a/pkg/controllers/namespace.go b/pkg/controllers/namespace.go index 671d39e0..605b737f 100644 --- a/pkg/controllers/namespace.go +++ b/pkg/controllers/namespace.go @@ -22,7 +22,7 @@ import ( "sync" "time" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" utilruntime "k8s.io/apimachinery/pkg/util/runtime" coreinformers "k8s.io/client-go/informers/core/v1" "k8s.io/client-go/tools/cache" @@ -83,7 +83,7 @@ func (c *NamespaceConfig) Run(stopCh <-chan struct{}) { } for i := range c.eventHandlers { - klog.V(4).Infof("Calling handler.OnNamespaceSynced()") + klog.V(10).Infof("Calling handler.OnNamespaceSynced()") c.eventHandlers[i].OnNamespaceSynced() } } @@ -96,7 +96,7 @@ func (c *NamespaceConfig) handleAddNamespace(obj interface{}) { } for i := range c.eventHandlers { - klog.V(4).Infof("Calling handler.OnNamespaceAdd") + klog.V(10).Infof("Calling handler.OnNamespaceAdd") c.eventHandlers[i].OnNamespaceAdd(ns) } } @@ -113,7 +113,7 @@ func (c *NamespaceConfig) handleUpdateNamespace(oldObj, newObj interface{}) { return } for i := range c.eventHandlers { - klog.V(4).Infof("Calling handler.OnNamespaceUpdate") + klog.V(10).Infof("Calling handler.OnNamespaceUpdate") c.eventHandlers[i].OnNamespaceUpdate(oldNamespace, ns) } } @@ -131,7 +131,7 @@ func (c *NamespaceConfig) handleDeleteNamespace(obj interface{}) { } } for i := range c.eventHandlers { - klog.V(4).Infof("Calling handler.OnNamespaceDelete") + klog.V(10).Infof("Calling handler.OnNamespaceDelete") c.eventHandlers[i].OnNamespaceDelete(ns) } } diff --git a/pkg/controllers/net-attach-def.go b/pkg/controllers/net-attach-def.go index e316d1fb..073edb28 100644 --- a/pkg/controllers/net-attach-def.go +++ b/pkg/controllers/net-attach-def.go @@ -88,7 +88,7 @@ func (c *NetDefConfig) Run(stopCh <-chan struct{}) { } for i := range c.eventHandlers { - klog.V(4).Infof("Calling handler.OnPolicySynced()") + klog.V(10).Infof("Calling handler.OnNetDefSynced()") c.eventHandlers[i].OnNetDefSynced() } } @@ -101,7 +101,7 @@ func (c *NetDefConfig) handleAddNetDef(obj interface{}) { } for i := range c.eventHandlers { - klog.V(4).Infof("Calling handler.OnPolicyAdd") + klog.V(10).Infof("Calling handler.OnNetDefAdd") c.eventHandlers[i].OnNetDefAdd(netdef) } } @@ -118,7 +118,7 @@ func (c *NetDefConfig) handleUpdateNetDef(oldObj, newObj interface{}) { return } for i := range c.eventHandlers { - klog.V(4).Infof("Calling handler.OnPolicyUpdate") + klog.V(10).Infof("Calling handler.OnNetDefUpdate") c.eventHandlers[i].OnNetDefUpdate(oldNetDef, netdef) } } @@ -136,7 +136,7 @@ func (c *NetDefConfig) handleDeleteNetDef(obj interface{}) { } } for i := range c.eventHandlers { - klog.V(4).Infof("Calling handler.OnNetDefDelete") + klog.V(10).Infof("Calling handler.OnNetDefDelete") c.eventHandlers[i].OnNetDefDelete(netdef) } } diff --git a/pkg/controllers/networkpolicy.go b/pkg/controllers/networkpolicy.go index 19e20001..0a1d17c8 100644 --- a/pkg/controllers/networkpolicy.go +++ b/pkg/controllers/networkpolicy.go @@ -85,7 +85,7 @@ func (c *NetworkPolicyConfig) Run(stopCh <-chan struct{}) { } for i := range c.eventHandlers { - klog.V(4).Infof("Calling handler.OnPolicySynced()") + klog.V(10).Infof("Calling handler.OnPolicySynced()") c.eventHandlers[i].OnPolicySynced() } } @@ -98,7 +98,7 @@ func (c *NetworkPolicyConfig) handleAddPolicy(obj interface{}) { } for i := range c.eventHandlers { - klog.V(4).Infof("Calling handler.OnPolicyAdd") + klog.V(10).Infof("Calling handler.OnPolicyAdd") c.eventHandlers[i].OnPolicyAdd(policy) } } @@ -115,7 +115,7 @@ func (c *NetworkPolicyConfig) handleUpdatePolicy(oldObj, newObj interface{}) { return } for i := range c.eventHandlers { - klog.V(4).Infof("Calling handler.OnPolicyUpdate") + klog.V(10).Infof("Calling handler.OnPolicyUpdate") c.eventHandlers[i].OnPolicyUpdate(oldPolicy, policy) } } @@ -133,7 +133,7 @@ func (c *NetworkPolicyConfig) handleDeletePolicy(obj interface{}) { } } for i := range c.eventHandlers { - klog.V(4).Infof("Calling handler.OnPolicyDelete") + klog.V(10).Infof("Calling handler.OnPolicyDelete") c.eventHandlers[i].OnPolicyDelete(policy) } } diff --git a/pkg/controllers/pod.go b/pkg/controllers/pod.go index 1ec29b31..91e78629 100644 --- a/pkg/controllers/pod.go +++ b/pkg/controllers/pod.go @@ -127,7 +127,7 @@ func (c *PodConfig) Run(stopCh <-chan struct{}) { } for i := range c.eventHandlers { - klog.V(9).Infof("Calling handler.OnPodSynced()") + klog.V(10).Infof("Calling handler.OnPodSynced()") c.eventHandlers[i].OnPodSynced() } } @@ -140,7 +140,7 @@ func (c *PodConfig) handleAddPod(obj interface{}) { } for i := range c.eventHandlers { - klog.V(9).Infof("Calling handler.OnPodAdd") + klog.V(10).Infof("Calling handler.OnPodAdd") c.eventHandlers[i].OnPodAdd(pod) } } @@ -157,7 +157,7 @@ func (c *PodConfig) handleUpdatePod(oldObj, newObj interface{}) { return } for i := range c.eventHandlers { - klog.V(9).Infof("Calling handler.OnPodUpdate") + klog.V(10).Infof("Calling handler.OnPodUpdate") c.eventHandlers[i].OnPodUpdate(oldPod, pod) } } @@ -175,7 +175,7 @@ func (c *PodConfig) handleDeletePod(obj interface{}) { } } for i := range c.eventHandlers { - klog.V(9).Infof("Calling handler.OnPodDelete") + klog.V(10).Infof("Calling handler.OnPodDelete") c.eventHandlers[i].OnPodDelete(pod) } } diff --git a/pkg/server/policyrules.go b/pkg/server/policyrules.go index 21db3760..e621641d 100644 --- a/pkg/server/policyrules.go +++ b/pkg/server/policyrules.go @@ -24,8 +24,7 @@ import ( "github.com/k8snetworkplumbingwg/multi-networkpolicy-iptables/pkg/controllers" multiv1beta1 "github.com/k8snetworkplumbingwg/multi-networkpolicy/pkg/apis/k8s.cni.cncf.io/v1beta1" - - //v1 "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/klog" @@ -144,11 +143,6 @@ func (ipt *iptableBuffer) SaveRules(path string) error { } func (ipt *iptableBuffer) SyncRules(iptables utiliptables.Interface) error { - /* - fmt.Fprintf(os.Stderr, "========= filterRules\n") - fmt.Fprintf(os.Stderr, "%s", ipt.filterRules.String()) - fmt.Fprintf(os.Stderr, "=========\n") - */ return iptables.RestoreAll(ipt.filterRules.Bytes(), utiliptables.NoFlushTables, utiliptables.RestoreCounters) } @@ -171,12 +165,17 @@ func (ipt *iptableBuffer) renderIngress(s *Server, podInfo *controllers.PodInfo, ipt.CreateFilterChain(chainName) ingresses := policy.Spec.Ingress + if idx == 0 { + writeLine(ipt.policyIndex, "-A", ingressChain, "-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT") + } for _, podIntf := range podInfo.Interfaces { if podIntf.CheckPolicyNetwork(policyNetworks) { comment := fmt.Sprintf("\"policy:%s net-attach-def:%s\"", policy.Name, podIntf.NetattachName) writeLine(ipt.policyIndex, "-A", ingressChain, "-m", "comment", "--comment", comment, "-i", podIntf.InterfaceName, "-j", chainName) + writeLine(ipt.policyIndex, "-A", ingressChain, + "-m", "mark", "--mark", "0x30000/0x30000", "-j", "RETURN") } } @@ -185,10 +184,7 @@ func (ipt *iptableBuffer) renderIngress(s *Server, podInfo *controllers.PodInfo, "-j", "MARK", "--set-xmark 0x0/0x30000") ipt.renderIngressPorts(s, podInfo, idx, n, ingress.Ports, policyNetworks) ipt.renderIngressFrom(s, podInfo, idx, n, ingress.From, policyNetworks) - writeLine(ipt.policyIndex, "-A", chainName, - "-m", "mark", "--mark", "0x30000/0x30000", "-j", "RETURN") } - writeLine(ipt.policyIndex, "-A", chainName, "-j", "DROP") } func (ipt *iptableBuffer) renderIngressPorts(s *Server, podInfo *controllers.PodInfo, pIndex, iIndex int, ports []multiv1beta1.MultiNetworkPolicyPort, policyNetworks []string) { @@ -200,7 +196,8 @@ func (ipt *iptableBuffer) renderIngressPorts(s *Server, podInfo *controllers.Pod validPorts := 0 for _, port := range ports { - proto := strings.ToLower(string(*port.Protocol)) + proto := renderProtocol(port.Protocol) + for _, podIntf := range podInfo.Interfaces { if !podIntf.CheckPolicyNetwork(policyNetworks) { continue @@ -232,7 +229,7 @@ func (ipt *iptableBuffer) renderIngressFrom(s *Server, podInfo *controllers.PodI s.podMap.Update(s.podChanges) validPeers := 0 for _, peer := range from { - if peer.PodSelector != nil { + if peer.PodSelector != nil || peer.NamespaceSelector != nil { podSelectorMap, err := metav1.LabelSelectorAsMap(peer.PodSelector) if err != nil { klog.Errorf("pod selector: %v", err) @@ -285,6 +282,12 @@ func (ipt *iptableBuffer) renderIngressFrom(s *Server, podInfo *controllers.PodI "-j", "MARK", "--set-xmark", "0x20000/0x20000") validPeers++ } + // ingress should accept reverse path + for _, ip := range podIntf.IPs { + writeLine(ipt.ingressFrom, "-A", chainName, + "-i", podIntf.InterfaceName, "-s", ip, + "-j", "MARK", "--set-xmark", "0x20000/0x20000") + } } } } @@ -308,6 +311,16 @@ func (ipt *iptableBuffer) renderIngressFrom(s *Server, podInfo *controllers.PodI "-j", "MARK", "--set-xmark", "0x20000/0x20000") validPeers++ } + for _, podIntf := range podInfo.Interfaces { + if !podIntf.CheckPolicyNetwork(policyNetworks) { + continue + } + for _, ip := range podIntf.IPs { + writeLine(ipt.ingressFrom, "-A", chainName, + "-i", podIntf.InterfaceName, "-s", ip, + "-j", "MARK", "--set-xmark", "0x20000/0x20000") + } + } } else { klog.Errorf("unknown rule") } @@ -327,21 +340,24 @@ func (ipt *iptableBuffer) renderEgress(s *Server, podInfo *controllers.PodInfo, ipt.CreateFilterChain(chainName) egresses := policy.Spec.Egress + if idx == 0 { + writeLine(ipt.policyIndex, "-A", egressChain, "-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT") + } for _, podIntf := range podInfo.Interfaces { if podIntf.CheckPolicyNetwork(policyNetworks) { comment := fmt.Sprintf("\"policy:%s net-attach-def:%s\"", policy.Name, podIntf.NetattachName) writeLine(ipt.policyIndex, "-A", egressChain, "-m", "comment", "--comment", comment, "-o", podIntf.InterfaceName, "-j", chainName) + writeLine(ipt.policyIndex, "-A", egressChain, + "-m", "mark", "--mark", "0x30000/0x30000", "-j", "RETURN") } } for n, egress := range egresses { writeLine(ipt.policyIndex, "-A", chainName, "-j", "MARK", "--set-xmark 0x0/0x30000") ipt.renderEgressPorts(s, podInfo, idx, n, egress.Ports, policyNetworks) ipt.renderEgressTo(s, podInfo, idx, n, egress.To, policyNetworks) - writeLine(ipt.policyIndex, "-A", chainName, "-m", "mark", "--mark", "0x30000/0x30000", "-j", "RETURN") } - writeLine(ipt.policyIndex, "-A", chainName, "-j", "DROP") } func (ipt *iptableBuffer) renderEgressPorts(s *Server, podInfo *controllers.PodInfo, pIndex, iIndex int, ports []multiv1beta1.MultiNetworkPolicyPort, policyNetworks []string) { @@ -353,7 +369,8 @@ func (ipt *iptableBuffer) renderEgressPorts(s *Server, podInfo *controllers.PodI validPorts := 0 for _, port := range ports { - proto := strings.ToLower(string(*port.Protocol)) + proto := renderProtocol(port.Protocol) + for _, podIntf := range podInfo.Interfaces { if !podIntf.CheckPolicyNetwork(policyNetworks) { continue @@ -385,7 +402,7 @@ func (ipt *iptableBuffer) renderEgressTo(s *Server, podInfo *controllers.PodInfo s.podMap.Update(s.podChanges) validPeers := 0 for _, peer := range to { - if peer.PodSelector != nil { + if peer.PodSelector != nil || peer.NamespaceSelector != nil { podSelectorMap, err := metav1.LabelSelectorAsMap(peer.PodSelector) if err != nil { klog.Errorf("pod selector: %v", err) @@ -439,6 +456,12 @@ func (ipt *iptableBuffer) renderEgressTo(s *Server, podInfo *controllers.PodInfo "-j", "MARK", "--set-xmark", "0x20000/0x20000") validPeers++ } + // egress should accept reverse path + for _, ip := range podIntf.IPs { + writeLine(ipt.egressTo, "-A", chainName, + "-o", podIntf.InterfaceName, "-d", ip, + "-j", "MARK", "--set-xmark", "0x20000/0x20000") + } } } } @@ -462,6 +485,17 @@ func (ipt *iptableBuffer) renderEgressTo(s *Server, podInfo *controllers.PodInfo "-j", "MARK", "--set-xmark", "0x20000/0x20000") validPeers++ } + // egress should accept reverse path + for _, podIntf := range podInfo.Interfaces { + if !podIntf.CheckPolicyNetwork(policyNetworks) { + continue + } + for _, ip := range podIntf.IPs { + writeLine(ipt.egressTo, "-A", chainName, + "-o", podIntf.InterfaceName, "-d", ip, + "-j", "MARK", "--set-xmark", "0x20000/0x20000") + } + } } else { klog.Errorf("unknown rule") } @@ -493,3 +527,12 @@ func writeBytesLine(buf *bytes.Buffer, bytes []byte) { buf.Write(bytes) buf.WriteByte('\n') } + +func renderProtocol(proto *v1.Protocol) string { + p := v1.ProtocolTCP + if proto != nil { + p = *proto + } + + return strings.ToLower(string(p)) +} diff --git a/pkg/server/policyrules_test.go b/pkg/server/policyrules_test.go index 0d07185a..b25669dd 100644 --- a/pkg/server/policyrules_test.go +++ b/pkg/server/policyrules_test.go @@ -130,7 +130,9 @@ func AddNamespace(s *Server, name string) { namespace := &v1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: name, - //Labels: labels, + Labels: map[string]string{ + "nsname": name, + }, }, } Expect(s.nsChanges.Update(nil, namespace)).To(BeTrue()) @@ -268,7 +270,7 @@ var _ = Describe("policyrules testing", func() { { IPBlock: &multiv1beta1.IPBlock{ CIDR: "10.1.1.1/24", - Except: []string{"10.1.1.1"}, + Except: []string{"10.1.1.254"}, }, }, }, @@ -307,7 +309,7 @@ var _ = Describe("policyrules testing", func() { portRules := []byte("-A MULTI-0-INGRESS-0-PORTS -i net1 -m tcp -p tcp --dport 8888 -j MARK --set-xmark 0x10000/0x10000\n") Expect(buf.ingressPorts.Bytes()).To(Equal(portRules)) - fromRules := []byte("-A MULTI-0-INGRESS-0-FROM -i net1 -s 10.1.1.1 -j DROP\n-A MULTI-0-INGRESS-0-FROM -i net1 -s 10.1.1.1/24 -j MARK --set-xmark 0x20000/0x20000\n") + fromRules := []byte("-A MULTI-0-INGRESS-0-FROM -i net1 -s 10.1.1.254 -j DROP\n-A MULTI-0-INGRESS-0-FROM -i net1 -s 10.1.1.1/24 -j MARK --set-xmark 0x20000/0x20000\n-A MULTI-0-INGRESS-0-FROM -i net1 -s 10.1.1.1 -j MARK --set-xmark 0x20000/0x20000\n") Expect(buf.ingressFrom.Bytes()).To(Equal(fromRules)) buf.FinalizeRules() @@ -318,15 +320,16 @@ var _ = Describe("policyrules testing", func() { :MULTI-0-INGRESS - [0:0] :MULTI-0-INGRESS-0-PORTS - [0:0] :MULTI-0-INGRESS-0-FROM - [0:0] +-A MULTI-INGRESS -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A MULTI-INGRESS -m comment --comment "policy:ingressPolicies1 net-attach-def:testns1/net-attach1" -i net1 -j MULTI-0-INGRESS +-A MULTI-INGRESS -m mark --mark 0x30000/0x30000 -j RETURN -A MULTI-0-INGRESS -j MARK --set-xmark 0x0/0x30000 -A MULTI-0-INGRESS -j MULTI-0-INGRESS-0-PORTS -A MULTI-0-INGRESS -j MULTI-0-INGRESS-0-FROM --A MULTI-0-INGRESS -m mark --mark 0x30000/0x30000 -j RETURN --A MULTI-0-INGRESS -j DROP -A MULTI-0-INGRESS-0-PORTS -i net1 -m tcp -p tcp --dport 8888 -j MARK --set-xmark 0x10000/0x10000 --A MULTI-0-INGRESS-0-FROM -i net1 -s 10.1.1.1 -j DROP +-A MULTI-0-INGRESS-0-FROM -i net1 -s 10.1.1.254 -j DROP -A MULTI-0-INGRESS-0-FROM -i net1 -s 10.1.1.1/24 -j MARK --set-xmark 0x20000/0x20000 +-A MULTI-0-INGRESS-0-FROM -i net1 -s 10.1.1.1 -j MARK --set-xmark 0x20000/0x20000 COMMIT `) Expect(buf.filterRules.Bytes()).To(Equal(finalizedRules)) @@ -405,7 +408,7 @@ COMMIT portRules := []byte("-A MULTI-0-INGRESS-0-PORTS -i net1 -m tcp -p tcp --dport 8888 -j MARK --set-xmark 0x10000/0x10000\n") Expect(buf.ingressPorts.Bytes()).To(Equal(portRules)) - fromRules := []byte("-A MULTI-0-INGRESS-0-FROM -i net1 -s 10.1.1.2 -j MARK --set-xmark 0x20000/0x20000\n") + fromRules := []byte("-A MULTI-0-INGRESS-0-FROM -i net1 -s 10.1.1.2 -j MARK --set-xmark 0x20000/0x20000\n-A MULTI-0-INGRESS-0-FROM -i net1 -s 10.1.1.1 -j MARK --set-xmark 0x20000/0x20000\n") Expect(buf.ingressFrom.Bytes()).To(Equal(fromRules)) buf.FinalizeRules() @@ -416,19 +419,190 @@ COMMIT :MULTI-0-INGRESS - [0:0] :MULTI-0-INGRESS-0-PORTS - [0:0] :MULTI-0-INGRESS-0-FROM - [0:0] +-A MULTI-INGRESS -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A MULTI-INGRESS -m comment --comment "policy:ingressPolicies1 net-attach-def:testns1/net-attach1" -i net1 -j MULTI-0-INGRESS +-A MULTI-INGRESS -m mark --mark 0x30000/0x30000 -j RETURN -A MULTI-0-INGRESS -j MARK --set-xmark 0x0/0x30000 -A MULTI-0-INGRESS -j MULTI-0-INGRESS-0-PORTS -A MULTI-0-INGRESS -j MULTI-0-INGRESS-0-FROM --A MULTI-0-INGRESS -m mark --mark 0x30000/0x30000 -j RETURN --A MULTI-0-INGRESS -j DROP -A MULTI-0-INGRESS-0-PORTS -i net1 -m tcp -p tcp --dport 8888 -j MARK --set-xmark 0x10000/0x10000 -A MULTI-0-INGRESS-0-FROM -i net1 -s 10.1.1.2 -j MARK --set-xmark 0x20000/0x20000 +-A MULTI-0-INGRESS-0-FROM -i net1 -s 10.1.1.1 -j MARK --set-xmark 0x20000/0x20000 COMMIT `) Expect(buf.filterRules.Bytes()).To(Equal(finalizedRules)) }) + It("ingress rules namespace selector", func() { + ingressPolicies1 := &multiv1beta1.MultiNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "ingressPolicies1", + Namespace: "testns1", + }, + Spec: multiv1beta1.MultiNetworkPolicySpec{ + Ingress: []multiv1beta1.MultiNetworkPolicyIngressRule{ + { + From: []multiv1beta1.MultiNetworkPolicyPeer{ + { + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "nsname": "testns2", + }, + }, + }, + }, + }, + }, + }, + } + + ipt := fakeiptables.NewFake() + Expect(ipt).NotTo(BeNil()) + buf := newIptableBuffer() + Expect(buf).NotTo(BeNil()) + + // verify buf initialized at init + buf.Init(ipt) + s := NewFakeServer("samplehost") + Expect(s).NotTo(BeNil()) + + AddNamespace(s, "testns1") + AddNamespace(s, "testns2") + + Expect(s.netdefChanges.Update( + nil, + NewNetDef("testns1", "net-attach1", NewCNIConfig("testCNI", "multi")))).To(BeTrue()) + Expect(s.netdefChanges.GetPluginType(types.NamespacedName{Namespace: "testns1", Name: "net-attach1"})).To(Equal("multi")) + Expect(s.netdefChanges.Update( + nil, + NewNetDef("testns2", "net-attach1", NewCNIConfig("testCNI", "multi")))).To(BeTrue()) + Expect(s.netdefChanges.GetPluginType(types.NamespacedName{Namespace: "testns2", Name: "net-attach1"})).To(Equal("multi")) + + pod1 := NewFakePodWithNetAnnotation( + "testns1", + "testpod1", + "net-attach1", + NewFakeNetworkStatus("testns1", "net-attach1", "192.168.1.1", "10.1.1.1"), + nil) + AddPod(s, pod1) + podInfo1, err := s.podMap.GetPodInfo(pod1) + Expect(err).To(BeNil()) + + pod2 := NewFakePodWithNetAnnotation( + "testns2", + "testpod2", + "net-attach1", + NewFakeNetworkStatus("testns2", "net-attach1", "192.168.1.2", "10.1.1.2"), + nil) + AddPod(s, pod2) + buf.renderIngress(s, podInfo1, 0, ingressPolicies1, []string{"testns1/net-attach1", "testns2/net-attach1"}) + + buf.FinalizeRules() + finalizedRules := []byte( + `*filter +:MULTI-INGRESS - [0:0] +:MULTI-EGRESS - [0:0] +:MULTI-0-INGRESS - [0:0] +:MULTI-0-INGRESS-0-PORTS - [0:0] +:MULTI-0-INGRESS-0-FROM - [0:0] +-A MULTI-INGRESS -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A MULTI-INGRESS -m comment --comment "policy:ingressPolicies1 net-attach-def:testns1/net-attach1" -i net1 -j MULTI-0-INGRESS +-A MULTI-INGRESS -m mark --mark 0x30000/0x30000 -j RETURN +-A MULTI-0-INGRESS -j MARK --set-xmark 0x0/0x30000 +-A MULTI-0-INGRESS -j MULTI-0-INGRESS-0-PORTS +-A MULTI-0-INGRESS -j MULTI-0-INGRESS-0-FROM +-A MULTI-0-INGRESS-0-PORTS -m comment --comment "no ingress ports, skipped" -j MARK --set-xmark 0x10000/0x10000 +-A MULTI-0-INGRESS-0-FROM -i net1 -s 10.1.1.2 -j MARK --set-xmark 0x20000/0x20000 +-A MULTI-0-INGRESS-0-FROM -i net1 -s 10.1.1.1 -j MARK --set-xmark 0x20000/0x20000 +COMMIT +`) + + Expect(buf.filterRules.String()).To(Equal(string(finalizedRules))) + }) + + It("enforce policy with net-attach-def in a different namespace than pods", func() { + ingressPolicies1 := &multiv1beta1.MultiNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "ingressPolicies1", + Namespace: "testns1", + }, + Spec: multiv1beta1.MultiNetworkPolicySpec{ + Ingress: []multiv1beta1.MultiNetworkPolicyIngressRule{ + { + From: []multiv1beta1.MultiNetworkPolicyPeer{ + { + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "nsname": "testns2", + }, + }, + }, + }, + }, + }, + }, + } + + ipt := fakeiptables.NewFake() + Expect(ipt).NotTo(BeNil()) + buf := newIptableBuffer() + Expect(buf).NotTo(BeNil()) + + // verify buf initialized at init + buf.Init(ipt) + s := NewFakeServer("samplehost") + Expect(s).NotTo(BeNil()) + + AddNamespace(s, "default") + AddNamespace(s, "testns1") + AddNamespace(s, "testns2") + + Expect(s.netdefChanges.Update( + nil, + NewNetDef("default", "net-attach1", NewCNIConfig("testCNI", "multi")))).To(BeTrue()) + Expect(s.netdefChanges.GetPluginType(types.NamespacedName{Namespace: "default", Name: "net-attach1"})).To(Equal("multi")) + + pod1 := NewFakePodWithNetAnnotation( + "testns1", + "testpod1", + "default/net-attach1", + NewFakeNetworkStatus("default", "net-attach1", "192.168.1.1", "10.1.1.1"), + nil) + AddPod(s, pod1) + podInfo1, err := s.podMap.GetPodInfo(pod1) + Expect(err).To(BeNil()) + + pod2 := NewFakePodWithNetAnnotation( + "testns2", + "testpod2", + "default/net-attach1", + NewFakeNetworkStatus("default", "net-attach1", "192.168.1.2", "10.1.1.2"), + nil) + AddPod(s, pod2) + buf.renderIngress(s, podInfo1, 0, ingressPolicies1, []string{"default/net-attach1"}) + + buf.FinalizeRules() + finalizedRules := []byte( + `*filter +:MULTI-INGRESS - [0:0] +:MULTI-EGRESS - [0:0] +:MULTI-0-INGRESS - [0:0] +:MULTI-0-INGRESS-0-PORTS - [0:0] +:MULTI-0-INGRESS-0-FROM - [0:0] +-A MULTI-INGRESS -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A MULTI-INGRESS -m comment --comment "policy:ingressPolicies1 net-attach-def:default/net-attach1" -i net1 -j MULTI-0-INGRESS +-A MULTI-INGRESS -m mark --mark 0x30000/0x30000 -j RETURN +-A MULTI-0-INGRESS -j MARK --set-xmark 0x0/0x30000 +-A MULTI-0-INGRESS -j MULTI-0-INGRESS-0-PORTS +-A MULTI-0-INGRESS -j MULTI-0-INGRESS-0-FROM +-A MULTI-0-INGRESS-0-PORTS -m comment --comment "no ingress ports, skipped" -j MARK --set-xmark 0x10000/0x10000 +-A MULTI-0-INGRESS-0-FROM -i net1 -s 10.1.1.2 -j MARK --set-xmark 0x20000/0x20000 +-A MULTI-0-INGRESS-0-FROM -i net1 -s 10.1.1.1 -j MARK --set-xmark 0x20000/0x20000 +COMMIT +`) + Expect(buf.filterRules.String()).To(Equal(string(finalizedRules))) + }) + It("egress rules ipblock", func() { port := intstr.FromInt(8888) protoTCP := v1.ProtocolTCP @@ -450,7 +624,7 @@ COMMIT { IPBlock: &multiv1beta1.IPBlock{ CIDR: "10.1.1.1/24", - Except: []string{"10.1.1.1"}, + Except: []string{"10.1.1.254"}, }, }, }, @@ -489,7 +663,7 @@ COMMIT portRules := []byte("-A MULTI-0-EGRESS-0-PORTS -o net1 -m tcp -p tcp --dport 8888 -j MARK --set-xmark 0x10000/0x10000\n") Expect(buf.egressPorts.Bytes()).To(Equal(portRules)) - toRules := []byte("-A MULTI-0-EGRESS-0-TO -o net1 -d 10.1.1.1 -j DROP\n-A MULTI-0-EGRESS-0-TO -o net1 -d 10.1.1.1/24 -j MARK --set-xmark 0x20000/0x20000\n") + toRules := []byte("-A MULTI-0-EGRESS-0-TO -o net1 -d 10.1.1.254 -j DROP\n-A MULTI-0-EGRESS-0-TO -o net1 -d 10.1.1.1/24 -j MARK --set-xmark 0x20000/0x20000\n-A MULTI-0-EGRESS-0-TO -o net1 -d 10.1.1.1 -j MARK --set-xmark 0x20000/0x20000\n") Expect(buf.egressTo.Bytes()).To(Equal(toRules)) buf.FinalizeRules() @@ -500,15 +674,16 @@ COMMIT :MULTI-0-EGRESS - [0:0] :MULTI-0-EGRESS-0-PORTS - [0:0] :MULTI-0-EGRESS-0-TO - [0:0] +-A MULTI-EGRESS -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A MULTI-EGRESS -m comment --comment "policy:EgressPolicies1 net-attach-def:testns1/net-attach1" -o net1 -j MULTI-0-EGRESS +-A MULTI-EGRESS -m mark --mark 0x30000/0x30000 -j RETURN -A MULTI-0-EGRESS -j MARK --set-xmark 0x0/0x30000 -A MULTI-0-EGRESS -j MULTI-0-EGRESS-0-PORTS -A MULTI-0-EGRESS -j MULTI-0-EGRESS-0-TO --A MULTI-0-EGRESS -m mark --mark 0x30000/0x30000 -j RETURN --A MULTI-0-EGRESS -j DROP -A MULTI-0-EGRESS-0-PORTS -o net1 -m tcp -p tcp --dport 8888 -j MARK --set-xmark 0x10000/0x10000 --A MULTI-0-EGRESS-0-TO -o net1 -d 10.1.1.1 -j DROP +-A MULTI-0-EGRESS-0-TO -o net1 -d 10.1.1.254 -j DROP -A MULTI-0-EGRESS-0-TO -o net1 -d 10.1.1.1/24 -j MARK --set-xmark 0x20000/0x20000 +-A MULTI-0-EGRESS-0-TO -o net1 -d 10.1.1.1 -j MARK --set-xmark 0x20000/0x20000 COMMIT `) Expect(buf.filterRules.Bytes()).To(Equal(finalizedRules)) @@ -587,7 +762,7 @@ COMMIT portRules := []byte("-A MULTI-0-EGRESS-0-PORTS -o net1 -m tcp -p tcp --dport 8888 -j MARK --set-xmark 0x10000/0x10000\n") Expect(buf.egressPorts.Bytes()).To(Equal(portRules)) - toRules := []byte("-A MULTI-0-EGRESS-0-TO -o net1 -d 10.1.1.2 -j MARK --set-xmark 0x20000/0x20000\n") + toRules := []byte("-A MULTI-0-EGRESS-0-TO -o net1 -d 10.1.1.2 -j MARK --set-xmark 0x20000/0x20000\n-A MULTI-0-EGRESS-0-TO -o net1 -d 10.1.1.1 -j MARK --set-xmark 0x20000/0x20000\n") Expect(buf.egressTo.Bytes()).To(Equal(toRules)) buf.FinalizeRules() @@ -598,19 +773,86 @@ COMMIT :MULTI-0-EGRESS - [0:0] :MULTI-0-EGRESS-0-PORTS - [0:0] :MULTI-0-EGRESS-0-TO - [0:0] +-A MULTI-EGRESS -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A MULTI-EGRESS -m comment --comment "policy:EgressPolicies1 net-attach-def:testns1/net-attach1" -o net1 -j MULTI-0-EGRESS +-A MULTI-EGRESS -m mark --mark 0x30000/0x30000 -j RETURN -A MULTI-0-EGRESS -j MARK --set-xmark 0x0/0x30000 -A MULTI-0-EGRESS -j MULTI-0-EGRESS-0-PORTS -A MULTI-0-EGRESS -j MULTI-0-EGRESS-0-TO --A MULTI-0-EGRESS -m mark --mark 0x30000/0x30000 -j RETURN --A MULTI-0-EGRESS -j DROP -A MULTI-0-EGRESS-0-PORTS -o net1 -m tcp -p tcp --dport 8888 -j MARK --set-xmark 0x10000/0x10000 -A MULTI-0-EGRESS-0-TO -o net1 -d 10.1.1.2 -j MARK --set-xmark 0x20000/0x20000 +-A MULTI-0-EGRESS-0-TO -o net1 -d 10.1.1.1 -j MARK --set-xmark 0x20000/0x20000 COMMIT `) Expect(buf.filterRules.Bytes()).To(Equal(finalizedRules)) }) + It("default values", func() { + port := intstr.FromInt(8888) + policies1 := &multiv1beta1.MultiNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "policies1", + Namespace: "testns1", + }, + Spec: multiv1beta1.MultiNetworkPolicySpec{ + Ingress: []multiv1beta1.MultiNetworkPolicyIngressRule{ + { + Ports: []multiv1beta1.MultiNetworkPolicyPort{ + { + Port: &port, + }, + }, + }, + }, + Egress: []multiv1beta1.MultiNetworkPolicyEgressRule{ + { + Ports: []multiv1beta1.MultiNetworkPolicyPort{ + { + Port: &port, + }, + }, + }, + }, + }, + } + + ipt := fakeiptables.NewFake() + Expect(ipt).NotTo(BeNil()) + buf := newIptableBuffer() + Expect(buf).NotTo(BeNil()) + buf.Init(ipt) + + s := NewFakeServer("samplehost") + Expect(s).NotTo(BeNil()) + + AddNamespace(s, "testns1") + + Expect(s.netdefChanges.Update( + nil, + NewNetDef("testns1", "net-attach1", NewCNIConfig("testCNI", "multi"))), + ).To(BeTrue()) + Expect(s.netdefChanges.GetPluginType(types.NamespacedName{Namespace: "testns1", Name: "net-attach1"})). + To(Equal("multi")) + + pod1 := NewFakePodWithNetAnnotation( + "testns1", + "testpod1", + "net-attach1", + NewFakeNetworkStatus("testns1", "net-attach1", "192.168.1.1", "10.1.1.1"), + nil) + AddPod(s, pod1) + podInfo1, err := s.podMap.GetPodInfo(pod1) + Expect(err).To(BeNil()) + + buf.renderIngress(s, podInfo1, 0, policies1, []string{"testns1/net-attach1"}) + buf.renderEgress(s, podInfo1, 0, policies1, []string{"testns1/net-attach1"}) + + portRules := []byte("-A MULTI-0-INGRESS-0-PORTS -i net1 -m tcp -p tcp --dport 8888 -j MARK --set-xmark 0x10000/0x10000\n") + Expect(buf.ingressPorts.Bytes()).To(Equal(portRules)) + + portRules = []byte("-A MULTI-0-EGRESS-0-PORTS -o net1 -m tcp -p tcp --dport 8888 -j MARK --set-xmark 0x10000/0x10000\n") + Expect(buf.egressPorts.Bytes()).To(Equal(portRules)) + }) }) var _ = Describe("policyrules testing - invalid case", func() { @@ -716,11 +958,10 @@ var _ = Describe("policyrules testing - invalid case", func() { :MULTI-0-INGRESS - [0:0] :MULTI-0-INGRESS-0-PORTS - [0:0] :MULTI-0-INGRESS-0-FROM - [0:0] +-A MULTI-INGRESS -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A MULTI-0-INGRESS -j MARK --set-xmark 0x0/0x30000 -A MULTI-0-INGRESS -j MULTI-0-INGRESS-0-PORTS -A MULTI-0-INGRESS -j MULTI-0-INGRESS-0-FROM --A MULTI-0-INGRESS -m mark --mark 0x30000/0x30000 -j RETURN --A MULTI-0-INGRESS -j DROP -A MULTI-0-INGRESS-0-PORTS -m comment --comment "no ingress ports, skipped" -j MARK --set-xmark 0x10000/0x10000 -A MULTI-0-INGRESS-0-FROM -m comment --comment "no ingress from, skipped" -j MARK --set-xmark 0x20000/0x20000 COMMIT @@ -806,11 +1047,10 @@ COMMIT :MULTI-0-INGRESS - [0:0] :MULTI-0-INGRESS-0-PORTS - [0:0] :MULTI-0-INGRESS-0-FROM - [0:0] +-A MULTI-INGRESS -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A MULTI-0-INGRESS -j MARK --set-xmark 0x0/0x30000 -A MULTI-0-INGRESS -j MULTI-0-INGRESS-0-PORTS -A MULTI-0-INGRESS -j MULTI-0-INGRESS-0-FROM --A MULTI-0-INGRESS -m mark --mark 0x30000/0x30000 -j RETURN --A MULTI-0-INGRESS -j DROP -A MULTI-0-INGRESS-0-PORTS -m comment --comment "no ingress ports, skipped" -j MARK --set-xmark 0x10000/0x10000 -A MULTI-0-INGRESS-0-FROM -m comment --comment "no ingress from, skipped" -j MARK --set-xmark 0x20000/0x20000 COMMIT @@ -883,11 +1123,10 @@ COMMIT :MULTI-0-EGRESS - [0:0] :MULTI-0-EGRESS-0-PORTS - [0:0] :MULTI-0-EGRESS-0-TO - [0:0] +-A MULTI-EGRESS -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A MULTI-0-EGRESS -j MARK --set-xmark 0x0/0x30000 -A MULTI-0-EGRESS -j MULTI-0-EGRESS-0-PORTS -A MULTI-0-EGRESS -j MULTI-0-EGRESS-0-TO --A MULTI-0-EGRESS -m mark --mark 0x30000/0x30000 -j RETURN --A MULTI-0-EGRESS -j DROP -A MULTI-0-EGRESS-0-PORTS -m comment --comment "no egress ports, skipped" -j MARK --set-xmark 0x10000/0x10000 -A MULTI-0-EGRESS-0-TO -m comment --comment "no egress to, skipped" -j MARK --set-xmark 0x20000/0x20000 COMMIT @@ -973,11 +1212,10 @@ COMMIT :MULTI-0-EGRESS - [0:0] :MULTI-0-EGRESS-0-PORTS - [0:0] :MULTI-0-EGRESS-0-TO - [0:0] +-A MULTI-EGRESS -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A MULTI-0-EGRESS -j MARK --set-xmark 0x0/0x30000 -A MULTI-0-EGRESS -j MULTI-0-EGRESS-0-PORTS -A MULTI-0-EGRESS -j MULTI-0-EGRESS-0-TO --A MULTI-0-EGRESS -m mark --mark 0x30000/0x30000 -j RETURN --A MULTI-0-EGRESS -j DROP -A MULTI-0-EGRESS-0-PORTS -m comment --comment "no egress ports, skipped" -j MARK --set-xmark 0x10000/0x10000 -A MULTI-0-EGRESS-0-TO -m comment --comment "no egress to, skipped" -j MARK --set-xmark 0x20000/0x20000 COMMIT diff --git a/pkg/server/server.go b/pkg/server/server.go index ec36c8f0..50cfc5d9 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -180,7 +180,7 @@ func NewServer(o *Options) (*Server, error) { ).ClientConfig() } if err != nil { - return nil, err + return nil, fmt.Errorf("server creation failed for kubeconfig [%s] master URL [%s]: %w", o.Kubeconfig, o.master, err) } if o.podIptables != "" { @@ -188,34 +188,34 @@ func NewServer(o *Options) (*Server, error) { if _, err := os.Stat(o.podIptables); err == nil || !os.IsNotExist(err) { err = os.RemoveAll(o.podIptables) if err != nil { - return nil, err + return nil, fmt.Errorf("server creation failed while deleting pod iptables directory [%s]: %w", o.podIptables, err) } } // create pod iptables directory err = os.Mkdir(o.podIptables, 0700) if err != nil { - return nil, err + return nil, fmt.Errorf("server creation failed while creating pod iptables directory [%s]: %w", o.podIptables, err) } } client, err := clientset.NewForConfig(kubeConfig) if err != nil { - return nil, err + return nil, fmt.Errorf("server creation failed while creating clientset for kubeconfig [%s]: %w", kubeConfig, err) } networkPolicyClient, err := multiclient.NewForConfig(kubeConfig) if err != nil { - return nil, err + return nil, fmt.Errorf("server creation failed while multi network policy creating clientset for kubeconfig [%s]: %w", kubeConfig, err) } netdefClient, err := netdefclient.NewForConfig(kubeConfig) if err != nil { - return nil, err + return nil, fmt.Errorf("server creation failed while creating net-attach-def clientset for kubeconfig [%s]: %w", kubeConfig, err) } hostname, err := utilnode.GetHostname(o.hostnameOverride) if err != nil { - return nil, err + return nil, fmt.Errorf("server creation failed while getting hostname with override [%s]: %w", o.hostnameOverride, err) } eventBroadcaster := record.NewBroadcaster() @@ -298,7 +298,7 @@ func (s *Server) OnPodAdd(pod *v1.Pod) { // OnPodUpdate ... func (s *Server) OnPodUpdate(oldPod, pod *v1.Pod) { - klog.V(4).Infof("OnPodUpdate") + klog.V(4).Infof("OnPodUpdate %s -> %s", podNamespacedName(oldPod), podNamespacedName(pod)) if s.podChanges.Update(oldPod, pod) && s.podSynced { s.Sync() } @@ -338,7 +338,7 @@ func (s *Server) OnPolicyAdd(policy *multiv1beta1.MultiNetworkPolicy) { // OnPolicyUpdate ... func (s *Server) OnPolicyUpdate(oldPolicy, policy *multiv1beta1.MultiNetworkPolicy) { - klog.V(4).Infof("OnPolicyUpdate") + klog.V(4).Infof("OnPolicyUpdate %s -> %s", policyNamespacedName(oldPolicy), policyNamespacedName(policy)) if s.policyChanges.Update(oldPolicy, policy) && s.isInitialized() { s.Sync() } @@ -371,7 +371,7 @@ func (s *Server) OnNetDefAdd(net *netdefv1.NetworkAttachmentDefinition) { // OnNetDefUpdate ... func (s *Server) OnNetDefUpdate(oldNet, net *netdefv1.NetworkAttachmentDefinition) { - klog.V(4).Infof("OnNetDefUpdate") + klog.V(4).Infof("OnNetDefUpdate %s -> %s", nadNamespacedName(oldNet), nadNamespacedName(net)) if s.netdefChanges.Update(oldNet, net) && s.isInitialized() { s.Sync() } @@ -404,7 +404,7 @@ func (s *Server) OnNamespaceAdd(ns *v1.Namespace) { // OnNamespaceUpdate ... func (s *Server) OnNamespaceUpdate(oldNamespace, ns *v1.Namespace) { - klog.V(4).Infof("OnNamespaceUpdate") + klog.V(4).Infof("OnNamespaceUpdate: %s -> %s", namespaceName(oldNamespace), namespaceName(ns)) if s.nsChanges.Update(oldNamespace, ns) && s.isInitialized() { s.Sync() } @@ -437,7 +437,7 @@ func (s *Server) syncMultiPolicy() { pods, err := s.podLister.Pods(metav1.NamespaceAll).List(labels.Everything()) if err != nil { - klog.Errorf("failed to get pods") + klog.Errorf("failed to get pods: %v", err) } for _, p := range pods { s.podMap.Update(s.podChanges) @@ -515,7 +515,7 @@ const ( ) func (s *Server) generatePolicyRules(pod *v1.Pod, podInfo *controllers.PodInfo) error { - klog.V(8).Infof("Generate rules for Pod :%v/%v\n", podInfo.Namespace, podInfo.Name) + klog.V(8).Infof("Generate rules for Pod: %v/%v\n", podInfo.Namespace, podInfo.Name) // -t filter -N MULTI-POLICY-INGRESS # ensure chain s.ip4Tables.EnsureChain(utiliptables.TableFilter, ingressChain) // -t filter -N MULTI-POLICY-EGRESS # ensure chain @@ -538,6 +538,8 @@ func (s *Server) generatePolicyRules(pod *v1.Pod, podInfo *controllers.PodInfo) iptableBuffer.Reset() idx := 0 + ingressRendered := 0 + egressRendered := 0 for _, p := range s.policyMap { policy := p.Policy if policy.GetNamespace() != pod.Namespace { @@ -546,7 +548,7 @@ func (s *Server) generatePolicyRules(pod *v1.Pod, podInfo *controllers.PodInfo) if policy.Spec.PodSelector.Size() != 0 { policyMap, err := metav1.LabelSelectorAsMap(&policy.Spec.PodSelector) if err != nil { - klog.Errorf("label selector: %v", err) + klog.Errorf("bad label selector for policy [%s]: %v", policyNamespacedName(policy), err) continue } policyPodSelector := labels.Set(policyMap).AsSelectorPreValidated() @@ -586,13 +588,21 @@ func (s *Server) generatePolicyRules(pod *v1.Pod, podInfo *controllers.PodInfo) if podInfo.CheckPolicyNetwork(policyNetworks) { if ingressEnable { iptableBuffer.renderIngress(s, podInfo, idx, policy, policyNetworks) + ingressRendered++ } if egressEnable { iptableBuffer.renderEgress(s, podInfo, idx, policy, policyNetworks) + egressRendered++ } idx++ } } + if ingressRendered != 0 { + writeLine(iptableBuffer.policyIndex, "-A", "MULTI-INGRESS", "-j", "DROP") + } + if egressRendered != 0 { + writeLine(iptableBuffer.policyIndex, "-A", "MULTI-EGRESS", "-j", "DROP") + } if !iptableBuffer.IsUsed() { iptableBuffer.Init(s.ip4Tables) @@ -607,9 +617,37 @@ func (s *Server) generatePolicyRules(pod *v1.Pod, podInfo *controllers.PodInfo) } if err := iptableBuffer.SyncRules(s.ip4Tables); err != nil { - klog.Errorf("sync rules failed: %v", err) + klog.Errorf("sync rules failed for pod [%s]: %v", podNamespacedName(pod), err) return err } return nil } + +func podNamespacedName(o *v1.Pod) string { + if o == nil { + return "" + } + return o.GetNamespace() + "/" + o.GetName() +} + +func namespaceName(o *v1.Namespace) string { + if o == nil { + return "" + } + return o.GetName() +} + +func policyNamespacedName(o *multiv1beta1.MultiNetworkPolicy) string { + if o == nil { + return "" + } + return o.GetNamespace() + "/" + o.GetName() +} + +func nadNamespacedName(o *netdefv1.NetworkAttachmentDefinition) string { + if o == nil { + return "" + } + return o.GetNamespace() + "/" + o.GetName() +}