diff --git a/npm/pod.go b/npm/pod.go index 1c2a11560..01f6f44b1 100644 --- a/npm/pod.go +++ b/npm/pod.go @@ -21,6 +21,10 @@ func isSystemPod(podObj *corev1.Pod) bool { return podObj.ObjectMeta.Namespace == util.KubeSystemFlag } +func isHostNetworkPod(podObj *corev1.Pod) bool { + return podObj.Spec.HostNetwork +} + func isInvalidPodUpdate(oldPodObj, newPodObj *corev1.Pod) (isInvalidUpdate bool) { isInvalidUpdate = oldPodObj.ObjectMeta.Namespace == newPodObj.ObjectMeta.Namespace && oldPodObj.ObjectMeta.Name == newPodObj.ObjectMeta.Name && @@ -61,6 +65,12 @@ func (npMgr *NetworkPolicyManager) AddPod(podObj *corev1.Pod) error { } } + // Ignore adding the HostNetwork pod to any ipsets. + if isHostNetworkPod(podObj) { + log.Logf("HostNetwork POD IGNORED: [%s%s/%s/%s%+v%s]", podUid, podNs, podName, podNodeName, podLabels, podIP) + return nil + } + // Add the pod to its namespace's ipset. log.Logf("Adding pod %s to ipset %s", podIP, podNs) if err = ipsMgr.AddToSet(podNs, podIP, util.IpsetNetHashFlag, podUid); err != nil { @@ -116,6 +126,17 @@ func (npMgr *NetworkPolicyManager) UpdatePod(oldPodObj, newPodObj *corev1.Pod) e return nil } + // today K8s does not allow updating HostNetwork flag for an existing Pod. So NPM can safely + // check on the oldPodObj for hostNework value + if isHostNetworkPod(oldPodObj) { + log.Logf( + "POD UPDATING ignored for HostNetwork Pod:\n old pod: [%s/%s/%+v/%s/%s]\n new pod: [%s/%s/%+v/%s/%s]", + oldPodObj.ObjectMeta.Namespace, oldPodObj.ObjectMeta.Name, oldPodObj.Status.PodIP, + newPodObj.ObjectMeta.Namespace, newPodObj.ObjectMeta.Name, newPodObj.Status.PodIP, + ) + return nil + } + if isInvalidPodUpdate(oldPodObj, newPodObj) { return nil } diff --git a/npm/pod_test.go b/npm/pod_test.go index 2f114ba55..5ffe95797 100644 --- a/npm/pod_test.go +++ b/npm/pod_test.go @@ -202,3 +202,183 @@ func TestDeletePod(t *testing.T) { } npMgr.Unlock() } + +func TestAddHostNetworkPod(t *testing.T) { + npMgr := &NetworkPolicyManager{ + nsMap: make(map[string]*namespace), + podMap: make(map[string]string), + TelemetryEnabled: false, + } + + allNs, err := newNs(util.KubeAllNamespacesFlag) + if err != nil { + panic(err.Error) + } + npMgr.nsMap[util.KubeAllNamespacesFlag] = allNs + + ipsMgr := ipsm.NewIpsetManager() + if err := ipsMgr.Save(util.IpsetTestConfigFile); err != nil { + t.Errorf("TestAddHostNetworkPod failed @ ipsMgr.Save") + } + + defer func() { + if err := ipsMgr.Restore(util.IpsetTestConfigFile); err != nil { + t.Errorf("TestAddHostNetworkPod failed @ ipsMgr.Restore") + } + }() + + podObj := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pod", + Namespace: "test-namespace", + Labels: map[string]string{ + "app": "test-pod", + }, + }, + Status: corev1.PodStatus{ + Phase: "Running", + PodIP: "1.2.3.4", + }, + Spec: corev1.PodSpec{ + HostNetwork: true, + }, + } + + npMgr.Lock() + if err := npMgr.AddPod(podObj); err != nil { + t.Errorf("TestAddHostNetworkPod failed @ AddPod") + } + + if len(npMgr.podMap) >= 1 { + t.Errorf("TestAddHostNetworkPod failed @ podMap length check") + } + npMgr.Unlock() +} + +func TestUpdateHostNetworkPod(t *testing.T) { + npMgr := &NetworkPolicyManager{ + nsMap: make(map[string]*namespace), + podMap: make(map[string]string), + TelemetryEnabled: false, + } + + allNs, err := newNs(util.KubeAllNamespacesFlag) + if err != nil { + panic(err.Error) + } + npMgr.nsMap[util.KubeAllNamespacesFlag] = allNs + + ipsMgr := ipsm.NewIpsetManager() + if err := ipsMgr.Save(util.IpsetTestConfigFile); err != nil { + t.Errorf("TestUpdateHostNetworkPod failed @ ipsMgr.Save") + } + + defer func() { + if err := ipsMgr.Restore(util.IpsetTestConfigFile); err != nil { + t.Errorf("TestUpdateHostNetworkPod failed @ ipsMgr.Restore") + } + }() + + // HostNetwork check is done on the oldPodObj, + // so intentionally not adding hostnet true in newPodObj + oldPodObj := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "old-test-pod", + Namespace: "test-namespace", + Labels: map[string]string{ + "app": "old-test-pod", + }, + }, + Status: corev1.PodStatus{ + Phase: "Running", + PodIP: "1.2.3.4", + }, + Spec: corev1.PodSpec{ + HostNetwork: true, + }, + } + + newPodObj := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "new-test-pod", + Namespace: "test-namespace", + Labels: map[string]string{ + "app": "new-test-pod", + }, + }, + Status: corev1.PodStatus{ + Phase: "Running", + PodIP: "4.3.2.1", + }, + } + + npMgr.Lock() + if err := npMgr.AddPod(oldPodObj); err != nil { + t.Errorf("TestUpdateHostNetworkPod failed @ AddPod") + } + + if err := npMgr.UpdatePod(oldPodObj, newPodObj); err != nil { + t.Errorf("TestUpdateHostNetworkPod failed @ UpdatePod") + } + + if len(npMgr.podMap) >= 1 { + t.Errorf("TestUpdateHostNetworkPod failed @ podMap length check") + } + npMgr.Unlock() +} + +func TestDeleteHostNetworkPod(t *testing.T) { + npMgr := &NetworkPolicyManager{ + nsMap: make(map[string]*namespace), + podMap: make(map[string]string), + TelemetryEnabled: false, + } + + allNs, err := newNs(util.KubeAllNamespacesFlag) + if err != nil { + panic(err.Error) + } + npMgr.nsMap[util.KubeAllNamespacesFlag] = allNs + + ipsMgr := ipsm.NewIpsetManager() + if err := ipsMgr.Save(util.IpsetTestConfigFile); err != nil { + t.Errorf("TestDeleteHostNetworkPod failed @ ipsMgr.Save") + } + + defer func() { + if err := ipsMgr.Restore(util.IpsetTestConfigFile); err != nil { + t.Errorf("TestDeleteHostNetworkPod failed @ ipsMgr.Restore") + } + }() + + podObj := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pod", + Namespace: "test-namespace", + Labels: map[string]string{ + "app": "test-pod", + }, + }, + Status: corev1.PodStatus{ + Phase: "Running", + PodIP: "1.2.3.4", + }, + Spec: corev1.PodSpec{ + HostNetwork: true, + }, + } + + npMgr.Lock() + if err := npMgr.AddPod(podObj); err != nil { + t.Errorf("TestDeleteHostNetworkPod failed @ AddPod") + } + + if len(npMgr.podMap) >= 1 { + t.Errorf("TestDeleteHostNetworkPod failed @ podMap length check") + } + + if err := npMgr.DeletePod(podObj); err != nil { + t.Errorf("TestDeleteHostNetworkPod failed @ DeletePod") + } + npMgr.Unlock() +}