From 9aa7044f1e818690d9d2383b620cd43d7ff91271 Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Sun, 22 Oct 2017 19:42:08 +0200 Subject: [PATCH] npc: Add unit tests for default-allow ipsets --- npc/controller_test.go | 143 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 136 insertions(+), 7 deletions(-) diff --git a/npc/controller_test.go b/npc/controller_test.go index b8dacdd2..314fb3e7 100644 --- a/npc/controller_test.go +++ b/npc/controller_test.go @@ -9,6 +9,7 @@ import ( "github.com/weaveworks/weave/npc/ipset" coreapi "k8s.io/api/core/v1" extnapi "k8s.io/api/extensions/v1beta1" + networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" ) @@ -40,12 +41,22 @@ func (i *mockIPSet) Create(ipsetName ipset.Name, ipsetType ipset.Type) error { } func (i *mockIPSet) AddEntry(ipsetName ipset.Name, entry string, comment string) error { + return i.addEntry(ipsetName, entry, comment, true) +} + +func (i *mockIPSet) AddEntryIfNotExist(ipsetName ipset.Name, entry string, comment string) error { + return i.addEntry(ipsetName, entry, comment, false) +} + +func (i *mockIPSet) addEntry(ipsetName ipset.Name, entry string, comment string, checkIfExists bool) error { log.Printf("adding entry %s to %s", entry, ipsetName) - if _, ok := i.sets[entry]; !ok { + if _, ok := i.sets[string(ipsetName)]; !ok { return errors.Errorf("ipset %s does not exist", entry) } - if _, ok := i.sets[string(ipsetName)].subSets[entry]; ok { - return errors.Errorf("ipset %s is already a member of %s", entry, ipsetName) + if checkIfExists { + if _, ok := i.sets[string(ipsetName)].subSets[entry]; ok { + return errors.Errorf("ipset %s is already a member of %s", entry, ipsetName) + } } i.sets[string(ipsetName)].subSets[entry] = true @@ -53,18 +64,33 @@ func (i *mockIPSet) AddEntry(ipsetName ipset.Name, entry string, comment string) } func (i *mockIPSet) DelEntry(ipsetName ipset.Name, entry string) error { + return i.delEntry(ipsetName, entry, true) +} + +func (i *mockIPSet) DelEntryIfExists(ipsetName ipset.Name, entry string) error { + return i.delEntry(ipsetName, entry, false) +} + +func (i *mockIPSet) delEntry(ipsetName ipset.Name, entry string, checkIfExists bool) error { log.Printf("deleting entry %s from %s", entry, ipsetName) if _, ok := i.sets[string(ipsetName)]; !ok { return errors.Errorf("ipset %s does not exist", ipsetName) } - if _, ok := i.sets[string(ipsetName)].subSets[entry]; !ok { - return errors.Errorf("ipset %s is not a member of %s", entry, ipsetName) + if checkIfExists { + if _, ok := i.sets[string(ipsetName)].subSets[entry]; !ok { + return errors.Errorf("ipset %s is not a member of %s", entry, ipsetName) + } } delete(i.sets[string(ipsetName)].subSets, entry) return nil } +func (i *mockIPSet) Exist(ipsetName ipset.Name, entry string) bool { + _, found := i.sets[string(ipsetName)].subSets[entry] + return found +} + func (i *mockIPSet) Flush(ipsetName ipset.Name) error { return errors.New("Not Implemented") } @@ -154,7 +180,7 @@ func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) { // Namespaces first m := newMockIPSet() - controller := New("foo", &mockIPTables{}, &m) + controller := New("foo", true, &mockIPTables{}, &m) const ( selectorIPSetName = "weave-I239Zp%sCvoVt*D6u=A!2]YEk" @@ -170,7 +196,7 @@ func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) { // NetworkPolicy first m = newMockIPSet() - controller = New("foo", &mockIPTables{}, &m) + controller = New("foo", true, &mockIPTables{}, &m) controller.AddNetworkPolicy(networkPolicy) @@ -180,3 +206,106 @@ func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) { require.Equal(t, true, m.sets[selectorIPSetName].subSets[sourceIPSetName]) } + +// Tests default-allow ipset behavior when running in non-legacy mode. +func TestDefaultAllow(t *testing.T) { + const ( + defaultAllowIPSetName = "weave-E.1.0W^NGSp]0_t5WwH/]gX@L" + fooPodIP = "10.32.0.10" + barPodIP = "10.32.0.11" + barPodNewIP = "10.32.0.12" + ) + + m := newMockIPSet() + controller := New("bar", false, &mockIPTables{}, &m) + + defaultNamespace := &coreapi.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "default", + }, + } + controller.AddNamespace(defaultNamespace) + + // Should create an ipset for default-allow + require.Contains(t, m.sets, defaultAllowIPSetName) + + podFoo := &coreapi.Pod{ + ObjectMeta: metav1.ObjectMeta{ + UID: "foo", + Namespace: "default", + Name: "foo", + Labels: map[string]string{"run": "foo"}}, + Status: coreapi.PodStatus{PodIP: fooPodIP}} + controller.AddPod(podFoo) + + // Should add the foo pod to default-allow + require.True(t, m.Exist(defaultAllowIPSetName, fooPodIP)) + + podBar := &coreapi.Pod{ + ObjectMeta: metav1.ObjectMeta{ + UID: "bar", + Namespace: "default", + Name: "bar", + Labels: map[string]string{"run": "bar"}}, + Status: coreapi.PodStatus{PodIP: barPodIP}} + podBarNoIP := &coreapi.Pod{ObjectMeta: podBar.ObjectMeta} + controller.AddPod(podBarNoIP) + controller.UpdatePod(podBarNoIP, podBar) + + // Should add the bar pod to default-allow + require.True(t, m.Exist(defaultAllowIPSetName, barPodIP)) + + // Allow access from the bar pod to the foo pod + netpol := &networkingv1.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-from-bar-to-foo", + Namespace: "default", + }, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{MatchLabels: map[string]string{"run": "foo"}}, + Ingress: []networkingv1.NetworkPolicyIngressRule{{ + From: []networkingv1.NetworkPolicyPeer{{ + PodSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"run": "bar"}, + }, + }}, + }}, + }, + } + controller.AddNetworkPolicy(netpol) + + // Should remove the foo pod from default-allow as the netpol selects it + require.False(t, m.Exist(defaultAllowIPSetName, fooPodIP)) + require.True(t, m.Exist(defaultAllowIPSetName, barPodIP)) + + podBarWithNewIP := *podBar + podBarWithNewIP.Status.PodIP = barPodNewIP + controller.UpdatePod(podBar, &podBarWithNewIP) + + // Should update IP addr of the bar pod in default-allow + require.False(t, m.Exist(defaultAllowIPSetName, barPodIP)) + require.True(t, m.Exist(defaultAllowIPSetName, barPodNewIP)) + + controller.UpdatePod(&podBarWithNewIP, podBarNoIP) + // Should remove the bar pod from default-allow as it does not have any IP addr + require.False(t, m.Exist(defaultAllowIPSetName, barPodNewIP)) + + podFooWithNewLabel := *podFoo + podFooWithNewLabel.ObjectMeta.Labels = map[string]string{"run": "new-foo"} + controller.UpdatePod(podFoo, &podFooWithNewLabel) + + // Should bring back the foo pod to default-allow as it does not match dst of any netpol + require.True(t, m.Exist(defaultAllowIPSetName, fooPodIP)) + + controller.UpdatePod(&podFooWithNewLabel, podFoo) + // Should remove from default-allow as it matches the netpol after the update + require.False(t, m.Exist(defaultAllowIPSetName, fooPodIP)) + + controller.DeleteNetworkPolicy(netpol) + // Should bring back the foo pod to default-allow as no netpol selects it + require.True(t, m.Exist(defaultAllowIPSetName, fooPodIP)) + + controller.DeletePod(podFoo) + // Should remove foo pod to default-allow + require.False(t, m.Exist(defaultAllowIPSetName, fooPodIP)) +}