k8s.io/kubernetes@v1.29.3/test/e2e/network/netpol/network_policy.go (about)

     1  /*
     2  Copyright 2016 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package netpol
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"time"
    23  
    24  	"k8s.io/apimachinery/pkg/util/intstr"
    25  
    26  	v1 "k8s.io/api/core/v1"
    27  	networkingv1 "k8s.io/api/networking/v1"
    28  
    29  	"github.com/onsi/ginkgo/v2"
    30  
    31  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    32  	"k8s.io/kubernetes/test/e2e/feature"
    33  	"k8s.io/kubernetes/test/e2e/framework"
    34  	e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
    35  	"k8s.io/kubernetes/test/e2e/network/common"
    36  	admissionapi "k8s.io/pod-security-admission/api"
    37  	utilnet "k8s.io/utils/net"
    38  )
    39  
    40  const (
    41  	isVerbose = true
    42  
    43  	// See https://github.com/kubernetes/kubernetes/issues/95879
    44  	// The semantics of the effect of network policies on loopback calls may be undefined: should
    45  	//   they always be ALLOWED; how do Services affect this?
    46  	//   Calico, Cillium, Antrea seem to do different things.
    47  	// Since different CNIs have different results, that causes tests including loopback to fail
    48  	//   on some CNIs.  So let's just ignore loopback calls for the purposes of deciding test pass/fail.
    49  	ignoreLoopback    = true
    50  	namespaceLabelKey = "kubernetes.io/metadata.name"
    51  )
    52  
    53  var (
    54  	protocolTCP  = v1.ProtocolTCP
    55  	protocolUDP  = v1.ProtocolUDP
    56  	protocolSCTP = v1.ProtocolSCTP
    57  )
    58  
    59  /*
    60  You might be wondering, why are there multiple namespaces used for each test case?
    61  
    62  These tests are based on "truth tables" that compare the expected and actual connectivity of each pair of pods.
    63  Since network policies live in namespaces, and peers can be selected by namespace,
    64  howing the connectivity of pods in other namespaces is key information to show whether a network policy is working as intended or not.
    65  
    66  We use 3 namespaces each with 3 pods, and probe all combinations ( 9 pods x 9 pods = 81 data points ) -- including cross-namespace calls.
    67  
    68  Here's an example of a test run, showing the expected and actual connectivity, along with the differences.  Note how the
    69  visual representation as a truth table greatly aids in understanding what a network policy is intended to do in theory
    70  and what is happening in practice:
    71  
    72  		Oct 19 10:34:16.907: INFO: expected:
    73  
    74  		-	x/a	x/b	x/c	y/a	y/b	y/c	z/a	z/b	z/c
    75  		x/a	X	.	.	.	.	.	.	.	.
    76  		x/b	X	.	.	.	.	.	.	.	.
    77  		x/c	X	.	.	.	.	.	.	.	.
    78  		y/a	.	.	.	.	.	.	.	.	.
    79  		y/b	.	.	.	.	.	.	.	.	.
    80  		y/c	.	.	.	.	.	.	.	.	.
    81  		z/a	X	.	.	.	.	.	.	.	.
    82  		z/b	X	.	.	.	.	.	.	.	.
    83  		z/c	X	.	.	.	.	.	.	.	.
    84  
    85  		Oct 19 10:34:16.907: INFO: observed:
    86  
    87  		-	x/a	x/b	x/c	y/a	y/b	y/c	z/a	z/b	z/c
    88  		x/a	X	.	.	.	.	.	.	.	.
    89  		x/b	X	.	.	.	.	.	.	.	.
    90  		x/c	X	.	.	.	.	.	.	.	.
    91  		y/a	.	.	.	.	.	.	.	.	.
    92  		y/b	.	.	.	.	.	.	.	.	.
    93  		y/c	.	.	.	.	.	.	.	.	.
    94  		z/a	X	.	.	.	.	.	.	.	.
    95  		z/b	X	.	.	.	.	.	.	.	.
    96  		z/c	X	.	.	.	.	.	.	.	.
    97  
    98  		Oct 19 10:34:16.907: INFO: comparison:
    99  
   100  		-	x/a	x/b	x/c	y/a	y/b	y/c	z/a	z/b	z/c
   101  		x/a	.	.	.	.	.	.	.	.	.
   102  		x/b	.	.	.	.	.	.	.	.	.
   103  		x/c	.	.	.	.	.	.	.	.	.
   104  		y/a	.	.	.	.	.	.	.	.	.
   105  		y/b	.	.	.	.	.	.	.	.	.
   106  		y/c	.	.	.	.	.	.	.	.	.
   107  		z/a	.	.	.	.	.	.	.	.	.
   108  		z/b	.	.	.	.	.	.	.	.	.
   109  		z/c	.	.	.	.	.	.	.	.	.
   110  */
   111  
   112  var _ = common.SIGDescribe("Netpol", func() {
   113  	f := framework.NewDefaultFramework("netpol")
   114  	f.SkipNamespaceCreation = true // we create our own 3 test namespaces, we don't need the default one
   115  	f.NamespacePodSecurityLevel = admissionapi.LevelBaseline
   116  
   117  	ginkgo.Context("NetworkPolicy between server and client", func() {
   118  		var k8s *kubeManager
   119  
   120  		f.It("should support a 'default-deny-ingress' policy", feature.NetworkPolicy, func(ctx context.Context) {
   121  
   122  			// Only poll TCP
   123  			protocols := []v1.Protocol{protocolTCP}
   124  
   125  			// Only testing port 80
   126  			ports := []int32{80}
   127  
   128  			// Create pods and namespaces for this test
   129  			k8s = initializeResources(ctx, f, protocols, ports)
   130  
   131  			// Only going to make a policy in namespace X
   132  			nsX, _, _ := getK8sNamespaces(k8s)
   133  			policy := GenNetworkPolicyWithNameAndPodSelector("deny-ingress", metav1.LabelSelector{}, SetSpecIngressRules())
   134  
   135  			// Create the policy
   136  			CreatePolicy(ctx, k8s, policy, nsX)
   137  
   138  			// Make a truth table of connectivity for all pods in ns x y z
   139  			reachability := NewReachability(k8s.AllPodStrings(), true)
   140  			// Set the nsX as false, since it has a policy that blocks traffic
   141  			reachability.ExpectPeer(&Peer{}, &Peer{Namespace: nsX}, false)
   142  
   143  			// Confirm that the real world connectivity matches our matrix
   144  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   145  		})
   146  
   147  		f.It("should support a 'default-deny-all' policy", feature.NetworkPolicy, func(ctx context.Context) {
   148  			policy := GenNetworkPolicyWithNameAndPodSelector("deny-all", metav1.LabelSelector{}, SetSpecIngressRules(), SetSpecEgressRules())
   149  			protocols := []v1.Protocol{protocolTCP}
   150  			ports := []int32{80}
   151  			k8s = initializeResources(ctx, f, protocols, ports)
   152  			nsX, _, _ := getK8sNamespaces(k8s)
   153  			CreatePolicy(ctx, k8s, policy, nsX)
   154  
   155  			reachability := NewReachability(k8s.AllPodStrings(), true)
   156  			reachability.ExpectPeer(&Peer{}, &Peer{Namespace: nsX}, false)
   157  			reachability.ExpectPeer(&Peer{Namespace: nsX}, &Peer{}, false)
   158  
   159  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   160  		})
   161  
   162  		f.It("should enforce policy to allow traffic from pods within server namespace based on PodSelector", feature.NetworkPolicy, func(ctx context.Context) {
   163  			allowedPods := metav1.LabelSelector{
   164  				MatchLabels: map[string]string{
   165  					"pod": "b",
   166  				},
   167  			}
   168  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
   169  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{PodSelector: &allowedPods})
   170  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("x-a-allows-x-b", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
   171  
   172  			protocols := []v1.Protocol{protocolTCP}
   173  			ports := []int32{80}
   174  			k8s = initializeResources(ctx, f, protocols, ports)
   175  			nsX, _, _ := getK8sNamespaces(k8s)
   176  			CreatePolicy(ctx, k8s, policy, nsX)
   177  
   178  			reachability := NewReachability(k8s.AllPodStrings(), true)
   179  			reachability.ExpectAllIngress(NewPodString(nsX, "a"), false)
   180  			reachability.Expect(NewPodString(nsX, "b"), NewPodString(nsX, "a"), true)
   181  
   182  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   183  		})
   184  
   185  		f.It("should enforce policy to allow ingress traffic for a target", feature.NetworkPolicy, func(ctx context.Context) {
   186  			protocols := []v1.Protocol{protocolTCP}
   187  			ports := []int32{80}
   188  			k8s = initializeResources(ctx, f, protocols, ports)
   189  			nsX, _, _ := getK8sNamespaces(k8s)
   190  			ginkgo.By("having a deny all ingress policy", func() {
   191  				// Deny all Ingress traffic policy to pods on namespace nsX
   192  				policy := GenNetworkPolicyWithNameAndPodSelector("deny-all", metav1.LabelSelector{}, SetSpecIngressRules())
   193  				CreatePolicy(ctx, k8s, policy, nsX)
   194  			})
   195  
   196  			// Allow Ingress traffic only to pod x/a from any pod
   197  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
   198  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{PodSelector: &metav1.LabelSelector{}, NamespaceSelector: &metav1.LabelSelector{}})
   199  			allowPolicy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-all-to-a", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
   200  			CreatePolicy(ctx, k8s, allowPolicy, nsX)
   201  
   202  			reachability := NewReachability(k8s.AllPodStrings(), true)
   203  			reachability.ExpectAllIngress(NewPodString(nsX, "a"), true)
   204  			reachability.ExpectAllIngress(NewPodString(nsX, "b"), false)
   205  			reachability.ExpectAllIngress(NewPodString(nsX, "c"), false)
   206  
   207  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   208  		})
   209  
   210  		f.It("should enforce policy to allow ingress traffic from pods in all namespaces", feature.NetworkPolicy, func(ctx context.Context) {
   211  			protocols := []v1.Protocol{protocolTCP}
   212  			ports := []int32{80}
   213  			k8s = initializeResources(ctx, f, protocols, ports)
   214  			nsX, _, _ := getK8sNamespaces(k8s)
   215  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
   216  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{NamespaceSelector: &metav1.LabelSelector{MatchLabels: map[string]string{}}})
   217  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-from-another-ns", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
   218  			CreatePolicy(ctx, k8s, policy, nsX)
   219  
   220  			reachability := NewReachability(k8s.AllPodStrings(), true)
   221  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   222  		})
   223  
   224  		f.It("should enforce policy to allow traffic only from a different namespace, based on NamespaceSelector", feature.NetworkPolicy, func(ctx context.Context) {
   225  			protocols := []v1.Protocol{protocolTCP}
   226  			ports := []int32{80}
   227  			k8s = initializeResources(ctx, f, protocols, ports)
   228  			nsX, nsY, nsZ := getK8sNamespaces(k8s)
   229  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
   230  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{NamespaceSelector: &metav1.LabelSelector{MatchLabels: map[string]string{namespaceLabelKey: nsY}}})
   231  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-client-a-via-ns-selector", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
   232  			CreatePolicy(ctx, k8s, policy, nsX)
   233  
   234  			reachability := NewReachability(k8s.AllPodStrings(), true)
   235  			// disallow all traffic from the x or z namespaces
   236  			reachability.ExpectPeer(&Peer{Namespace: nsX}, &Peer{Namespace: nsX, Pod: "a"}, false)
   237  			reachability.ExpectPeer(&Peer{Namespace: nsZ}, &Peer{Namespace: nsX, Pod: "a"}, false)
   238  
   239  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   240  		})
   241  
   242  		f.It("should enforce policy based on PodSelector with MatchExpressions", feature.NetworkPolicy, func(ctx context.Context) {
   243  			allowedPods := metav1.LabelSelector{
   244  				MatchExpressions: []metav1.LabelSelectorRequirement{{
   245  					Key:      "pod",
   246  					Operator: metav1.LabelSelectorOpIn,
   247  					Values:   []string{"b"},
   248  				}},
   249  			}
   250  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
   251  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{PodSelector: &allowedPods})
   252  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("x-a-allows-x-b", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
   253  
   254  			protocols := []v1.Protocol{protocolTCP}
   255  			ports := []int32{80}
   256  			k8s = initializeResources(ctx, f, protocols, ports)
   257  			nsX, _, _ := getK8sNamespaces(k8s)
   258  			CreatePolicy(ctx, k8s, policy, nsX)
   259  
   260  			reachability := NewReachability(k8s.AllPodStrings(), true)
   261  			reachability.ExpectAllIngress(NewPodString(nsX, "a"), false)
   262  			reachability.Expect(NewPodString(nsX, "b"), NewPodString(nsX, "a"), true)
   263  
   264  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   265  		})
   266  
   267  		f.It("should enforce policy based on NamespaceSelector with MatchExpressions", feature.NetworkPolicy, func(ctx context.Context) {
   268  			protocols := []v1.Protocol{protocolTCP}
   269  			ports := []int32{80}
   270  			k8s = initializeResources(ctx, f, protocols, ports)
   271  			nsX, nsY, nsZ := getK8sNamespaces(k8s)
   272  			allowedNamespaces := &metav1.LabelSelector{
   273  				MatchExpressions: []metav1.LabelSelectorRequirement{{
   274  					Key:      namespaceLabelKey,
   275  					Operator: metav1.LabelSelectorOpIn,
   276  					Values:   []string{nsY},
   277  				}},
   278  			}
   279  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
   280  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{NamespaceSelector: allowedNamespaces})
   281  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-ns-y-match-selector", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
   282  			CreatePolicy(ctx, k8s, policy, nsX)
   283  
   284  			reachability := NewReachability(k8s.AllPodStrings(), true)
   285  			// disallow all traffic from the x or z namespaces
   286  			reachability.ExpectPeer(&Peer{Namespace: nsX}, &Peer{Namespace: nsX, Pod: "a"}, false)
   287  			reachability.ExpectPeer(&Peer{Namespace: nsZ}, &Peer{Namespace: nsX, Pod: "a"}, false)
   288  
   289  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   290  		})
   291  
   292  		f.It("should enforce policy based on PodSelector or NamespaceSelector", feature.NetworkPolicy, func(ctx context.Context) {
   293  			protocols := []v1.Protocol{protocolTCP}
   294  			ports := []int32{80}
   295  			k8s = initializeResources(ctx, f, protocols, ports)
   296  			nsX, _, _ := getK8sNamespaces(k8s)
   297  			allowedNamespaces := &metav1.LabelSelector{
   298  				MatchExpressions: []metav1.LabelSelectorRequirement{{
   299  					Key:      namespaceLabelKey,
   300  					Operator: metav1.LabelSelectorOpNotIn,
   301  					Values:   []string{nsX},
   302  				}},
   303  			}
   304  			podBAllowlisting := &metav1.LabelSelector{
   305  				MatchLabels: map[string]string{
   306  					"pod": "b",
   307  				},
   308  			}
   309  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
   310  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{NamespaceSelector: allowedNamespaces}, networkingv1.NetworkPolicyPeer{PodSelector: podBAllowlisting})
   311  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-ns-y-match-selector", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
   312  			CreatePolicy(ctx, k8s, policy, nsX)
   313  
   314  			reachability := NewReachability(k8s.AllPodStrings(), true)
   315  			reachability.Expect(NewPodString(nsX, "a"), NewPodString(nsX, "a"), false)
   316  			reachability.Expect(NewPodString(nsX, "c"), NewPodString(nsX, "a"), false)
   317  
   318  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   319  		})
   320  
   321  		f.It("should enforce policy based on PodSelector and NamespaceSelector", feature.NetworkPolicy, func(ctx context.Context) {
   322  			protocols := []v1.Protocol{protocolTCP}
   323  			ports := []int32{80}
   324  			k8s = initializeResources(ctx, f, protocols, ports)
   325  			nsX, nsY, nsZ := getK8sNamespaces(k8s)
   326  			allowedNamespaces := &metav1.LabelSelector{
   327  				MatchExpressions: []metav1.LabelSelectorRequirement{{
   328  					Key:      namespaceLabelKey,
   329  					Operator: metav1.LabelSelectorOpNotIn,
   330  					Values:   []string{nsX},
   331  				}},
   332  			}
   333  			allowedPod := &metav1.LabelSelector{
   334  				MatchLabels: map[string]string{
   335  					"pod": "b",
   336  				},
   337  			}
   338  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
   339  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{NamespaceSelector: allowedNamespaces, PodSelector: allowedPod})
   340  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-ns-y-podselector-and-nsselector", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
   341  			CreatePolicy(ctx, k8s, policy, nsX)
   342  
   343  			reachability := NewReachability(k8s.AllPodStrings(), true)
   344  			reachability.ExpectAllIngress(NewPodString(nsX, "a"), false)
   345  			reachability.Expect(NewPodString(nsY, "b"), NewPodString(nsX, "a"), true)
   346  			reachability.Expect(NewPodString(nsZ, "b"), NewPodString(nsX, "a"), true)
   347  
   348  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   349  		})
   350  
   351  		f.It("should enforce policy based on Multiple PodSelectors and NamespaceSelectors", feature.NetworkPolicy, func(ctx context.Context) {
   352  			protocols := []v1.Protocol{protocolTCP}
   353  			ports := []int32{80}
   354  			k8s = initializeResources(ctx, f, protocols, ports)
   355  			nsX, nsY, nsZ := getK8sNamespaces(k8s)
   356  			allowedNamespaces := &metav1.LabelSelector{
   357  				MatchExpressions: []metav1.LabelSelectorRequirement{{
   358  					Key:      namespaceLabelKey,
   359  					Operator: metav1.LabelSelectorOpNotIn,
   360  					Values:   []string{nsX},
   361  				}},
   362  			}
   363  			allowedPod := &metav1.LabelSelector{
   364  				MatchExpressions: []metav1.LabelSelectorRequirement{{
   365  					Key:      "pod",
   366  					Operator: metav1.LabelSelectorOpIn,
   367  					Values:   []string{"b", "c"},
   368  				}},
   369  			}
   370  
   371  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
   372  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{NamespaceSelector: allowedNamespaces, PodSelector: allowedPod})
   373  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-ns-y-z-pod-b-c", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
   374  			CreatePolicy(ctx, k8s, policy, nsX)
   375  
   376  			reachability := NewReachability(k8s.AllPodStrings(), true)
   377  			reachability.ExpectPeer(&Peer{Namespace: nsX}, &Peer{Namespace: nsX, Pod: "a"}, false)
   378  			reachability.Expect(NewPodString(nsY, "a"), NewPodString(nsX, "a"), false)
   379  			reachability.Expect(NewPodString(nsZ, "a"), NewPodString(nsX, "a"), false)
   380  
   381  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   382  		})
   383  
   384  		f.It("should enforce policy based on any PodSelectors", feature.NetworkPolicy, func(ctx context.Context) {
   385  			protocols := []v1.Protocol{protocolTCP}
   386  			ports := []int32{80}
   387  			k8s = initializeResources(ctx, f, protocols, ports)
   388  			nsX, _, _ := getK8sNamespaces(k8s)
   389  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
   390  			for _, label := range []map[string]string{{"pod": "b"}, {"pod": "c"}} {
   391  				ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{PodSelector: &metav1.LabelSelector{MatchLabels: label}})
   392  			}
   393  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-ns-x-pod-b-c", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
   394  			CreatePolicy(ctx, k8s, policy, nsX)
   395  
   396  			reachability := NewReachability(k8s.AllPodStrings(), true)
   397  			reachability.ExpectAllIngress(NewPodString(nsX, "a"), false)
   398  
   399  			// Connect Pods b and c to pod a from namespace nsX
   400  			reachability.Expect(NewPodString(nsX, "b"), NewPodString(nsX, "a"), true)
   401  			reachability.Expect(NewPodString(nsX, "c"), NewPodString(nsX, "a"), true)
   402  
   403  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   404  		})
   405  
   406  		f.It("should enforce policy to allow traffic only from a pod in a different namespace based on PodSelector and NamespaceSelector", feature.NetworkPolicy, func(ctx context.Context) {
   407  			protocols := []v1.Protocol{protocolTCP}
   408  			ports := []int32{80}
   409  			k8s = initializeResources(ctx, f, protocols, ports)
   410  			nsX, nsY, _ := getK8sNamespaces(k8s)
   411  			allowedNamespaces := &metav1.LabelSelector{
   412  				MatchLabels: map[string]string{
   413  					namespaceLabelKey: nsY,
   414  				},
   415  			}
   416  			allowedPods := &metav1.LabelSelector{
   417  				MatchLabels: map[string]string{
   418  					"pod": "a",
   419  				},
   420  			}
   421  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
   422  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{NamespaceSelector: allowedNamespaces, PodSelector: allowedPods})
   423  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-ns-y-pod-a-via-namespace-pod-selector", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
   424  			CreatePolicy(ctx, k8s, policy, nsX)
   425  
   426  			reachability := NewReachability(k8s.AllPodStrings(), true)
   427  			reachability.ExpectAllIngress(NewPodString(nsX, "a"), false)
   428  			reachability.Expect(NewPodString(nsY, "a"), NewPodString(nsX, "a"), true)
   429  
   430  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   431  		})
   432  
   433  		f.It("should enforce policy based on Ports", feature.NetworkPolicy, func(ctx context.Context) {
   434  			ginkgo.By("Creating a network allowPort81Policy which only allows allow listed namespaces (y) to connect on exactly one port (81)")
   435  			protocols := []v1.Protocol{protocolTCP}
   436  			ports := []int32{81}
   437  			k8s = initializeResources(ctx, f, protocols, ports)
   438  			nsX, nsY, nsZ := getK8sNamespaces(k8s)
   439  			allowedLabels := &metav1.LabelSelector{
   440  				MatchLabels: map[string]string{
   441  					namespaceLabelKey: nsY,
   442  				},
   443  			}
   444  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
   445  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{NamespaceSelector: allowedLabels})
   446  			ingressRule.Ports = append(ingressRule.Ports, networkingv1.NetworkPolicyPort{Port: &intstr.IntOrString{IntVal: 81}, Protocol: &protocolTCP})
   447  			allowPort81Policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-client-a-via-ns-selector", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
   448  			CreatePolicy(ctx, k8s, allowPort81Policy, nsX)
   449  
   450  			reachability := NewReachability(k8s.AllPodStrings(), true)
   451  			reachability.ExpectPeer(&Peer{Namespace: nsX}, &Peer{Namespace: nsX, Pod: "a"}, false)
   452  			reachability.ExpectPeer(&Peer{Namespace: nsY}, &Peer{Namespace: nsX, Pod: "a"}, true)
   453  			reachability.ExpectPeer(&Peer{Namespace: nsZ}, &Peer{Namespace: nsX, Pod: "a"}, false)
   454  
   455  			ValidateOrFail(k8s, &TestCase{ToPort: 81, Protocol: v1.ProtocolTCP, Reachability: reachability})
   456  		})
   457  
   458  		f.It("should enforce multiple, stacked policies with overlapping podSelectors", feature.NetworkPolicy, func(ctx context.Context) {
   459  			ginkgo.By("Creating a network allowPort81Policy which only allows allow listed namespaces (y) to connect on exactly one port (81)")
   460  			protocols := []v1.Protocol{protocolTCP}
   461  			ports := []int32{80, 81}
   462  			k8s = initializeResources(ctx, f, protocols, ports)
   463  			nsX, nsY, nsZ := getK8sNamespaces(k8s)
   464  			allowedLabels := &metav1.LabelSelector{
   465  				MatchLabels: map[string]string{
   466  					namespaceLabelKey: nsY,
   467  				},
   468  			}
   469  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
   470  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{NamespaceSelector: allowedLabels})
   471  			ingressRule.Ports = append(ingressRule.Ports, networkingv1.NetworkPolicyPort{Port: &intstr.IntOrString{IntVal: 81}, Protocol: &protocolTCP})
   472  			allowPort81Policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-client-a-via-ns-selector", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
   473  			CreatePolicy(ctx, k8s, allowPort81Policy, nsX)
   474  
   475  			reachabilityALLOW := NewReachability(k8s.AllPodStrings(), true)
   476  			reachabilityALLOW.ExpectPeer(&Peer{Namespace: nsX}, &Peer{Namespace: nsX, Pod: "a"}, false)
   477  			reachabilityALLOW.ExpectPeer(&Peer{Namespace: nsY}, &Peer{Namespace: nsX, Pod: "a"}, true)
   478  			reachabilityALLOW.ExpectPeer(&Peer{Namespace: nsZ}, &Peer{Namespace: nsX, Pod: "a"}, false)
   479  
   480  			ginkgo.By("Verifying traffic on port 81.")
   481  			ValidateOrFail(k8s, &TestCase{ToPort: 81, Protocol: v1.ProtocolTCP, Reachability: reachabilityALLOW})
   482  
   483  			reachabilityDENY := NewReachability(k8s.AllPodStrings(), true)
   484  			reachabilityDENY.ExpectAllIngress(NewPodString(nsX, "a"), false)
   485  
   486  			ginkgo.By("Verifying traffic on port 80.")
   487  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachabilityDENY})
   488  
   489  			ingressRule = networkingv1.NetworkPolicyIngressRule{}
   490  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{NamespaceSelector: allowedLabels})
   491  			ingressRule.Ports = append(ingressRule.Ports, networkingv1.NetworkPolicyPort{Port: &intstr.IntOrString{IntVal: 80}, Protocol: &protocolTCP})
   492  
   493  			allowPort80Policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-client-a-via-ns-selector-80", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
   494  			CreatePolicy(ctx, k8s, allowPort80Policy, nsX)
   495  
   496  			ginkgo.By("Verifying that we can add a policy to unblock port 80")
   497  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachabilityALLOW})
   498  		})
   499  
   500  		f.It("should support allow-all policy", feature.NetworkPolicy, func(ctx context.Context) {
   501  			ginkgo.By("Creating a network policy which allows all traffic.")
   502  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-all", map[string]string{}, SetSpecIngressRules(networkingv1.NetworkPolicyIngressRule{}))
   503  			protocols := []v1.Protocol{protocolTCP}
   504  			ports := []int32{80, 81}
   505  			k8s = initializeResources(ctx, f, protocols, ports)
   506  			nsX, _, _ := getK8sNamespaces(k8s)
   507  			CreatePolicy(ctx, k8s, policy, nsX)
   508  
   509  			ginkgo.By("Testing pods can connect to both ports when an 'allow-all' policy is present.")
   510  			reachability := NewReachability(k8s.AllPodStrings(), true)
   511  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   512  			ValidateOrFail(k8s, &TestCase{ToPort: 81, Protocol: v1.ProtocolTCP, Reachability: reachability})
   513  		})
   514  
   515  		f.It("should allow ingress access on one named port", feature.NetworkPolicy, func(ctx context.Context) {
   516  			IngressRules := networkingv1.NetworkPolicyIngressRule{}
   517  			IngressRules.Ports = append(IngressRules.Ports, networkingv1.NetworkPolicyPort{Port: &intstr.IntOrString{Type: intstr.String, StrVal: "serve-81-tcp"}})
   518  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-all", map[string]string{}, SetSpecIngressRules(IngressRules))
   519  			protocols := []v1.Protocol{protocolTCP}
   520  			ports := []int32{80, 81}
   521  			k8s = initializeResources(ctx, f, protocols, ports)
   522  			nsX, _, _ := getK8sNamespaces(k8s)
   523  			CreatePolicy(ctx, k8s, policy, nsX)
   524  
   525  			ginkgo.By("Blocking all ports other then 81 in the entire namespace")
   526  
   527  			reachabilityPort81 := NewReachability(k8s.AllPodStrings(), true)
   528  			ValidateOrFail(k8s, &TestCase{ToPort: 81, Protocol: v1.ProtocolTCP, Reachability: reachabilityPort81})
   529  
   530  			// disallow all traffic to the x namespace
   531  			reachabilityPort80 := NewReachability(k8s.AllPodStrings(), true)
   532  			reachabilityPort80.ExpectPeer(&Peer{}, &Peer{Namespace: nsX}, false)
   533  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachabilityPort80})
   534  		})
   535  
   536  		f.It("should allow ingress access from namespace on one named port", feature.NetworkPolicy, func(ctx context.Context) {
   537  			protocols := []v1.Protocol{protocolTCP}
   538  			ports := []int32{80, 81}
   539  			k8s = initializeResources(ctx, f, protocols, ports)
   540  			nsX, nsY, nsZ := getK8sNamespaces(k8s)
   541  			allowedLabels := &metav1.LabelSelector{
   542  				MatchLabels: map[string]string{
   543  					namespaceLabelKey: nsY,
   544  				},
   545  			}
   546  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
   547  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{NamespaceSelector: allowedLabels})
   548  			ingressRule.Ports = append(ingressRule.Ports, networkingv1.NetworkPolicyPort{Port: &intstr.IntOrString{Type: intstr.String, StrVal: "serve-80-tcp"}, Protocol: &protocolTCP})
   549  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-client-a-via-ns-selector-80", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
   550  			CreatePolicy(ctx, k8s, policy, nsX)
   551  
   552  			reachability := NewReachability(k8s.AllPodStrings(), true)
   553  			// disallow all traffic from the x or z namespaces
   554  			reachability.ExpectPeer(&Peer{Namespace: nsX}, &Peer{Namespace: nsX, Pod: "a"}, false)
   555  			reachability.ExpectPeer(&Peer{Namespace: nsZ}, &Peer{Namespace: nsX, Pod: "a"}, false)
   556  
   557  			ginkgo.By("Verify that port 80 is allowed for namespace y")
   558  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   559  
   560  			ginkgo.By("Verify that port 81 is blocked for all namespaces including y")
   561  			reachabilityFAIL := NewReachability(k8s.AllPodStrings(), true)
   562  			reachabilityFAIL.ExpectAllIngress(NewPodString(nsX, "a"), false)
   563  			ValidateOrFail(k8s, &TestCase{ToPort: 81, Protocol: v1.ProtocolTCP, Reachability: reachabilityFAIL})
   564  		})
   565  
   566  		f.It("should allow egress access on one named port", feature.NetworkPolicy, func(ctx context.Context) {
   567  			ginkgo.By("validating egress from port 81 to port 80")
   568  			egressRule := networkingv1.NetworkPolicyEgressRule{}
   569  			egressRule.Ports = append(egressRule.Ports, networkingv1.NetworkPolicyPort{Port: &intstr.IntOrString{Type: intstr.String, StrVal: "serve-80-tcp"}})
   570  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-egress", map[string]string{}, SetSpecEgressRules(egressRule))
   571  
   572  			protocols := []v1.Protocol{protocolTCP}
   573  			ports := []int32{80, 81}
   574  			k8s = initializeResources(ctx, f, protocols, ports)
   575  			nsX, _, _ := getK8sNamespaces(k8s)
   576  			CreatePolicy(ctx, k8s, policy, nsX)
   577  
   578  			reachabilityPort80 := NewReachability(k8s.AllPodStrings(), true)
   579  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachabilityPort80})
   580  
   581  			// meanwhile no traffic over 81 should work, since our egress policy is on 80
   582  			reachabilityPort81 := NewReachability(k8s.AllPodStrings(), true)
   583  			reachabilityPort81.ExpectPeer(&Peer{Namespace: nsX}, &Peer{}, false)
   584  			ValidateOrFail(k8s, &TestCase{ToPort: 81, Protocol: v1.ProtocolTCP, Reachability: reachabilityPort81})
   585  		})
   586  
   587  		f.It("should enforce updated policy", feature.NetworkPolicy, func(ctx context.Context) {
   588  			ginkgo.By("Using the simplest possible mutation: start with allow all, then switch to deny all")
   589  			// part 1) allow all
   590  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-all-mutate-to-deny-all", map[string]string{}, SetSpecIngressRules(networkingv1.NetworkPolicyIngressRule{}))
   591  			protocols := []v1.Protocol{protocolTCP}
   592  			ports := []int32{81}
   593  			k8s = initializeResources(ctx, f, protocols, ports)
   594  			nsX, _, _ := getK8sNamespaces(k8s)
   595  			CreatePolicy(ctx, k8s, policy, nsX)
   596  
   597  			reachability := NewReachability(k8s.AllPodStrings(), true)
   598  			ValidateOrFail(k8s, &TestCase{ToPort: 81, Protocol: v1.ProtocolTCP, Reachability: reachability})
   599  
   600  			// part 2) update the policy to deny all
   601  			policy.Spec.Ingress = []networkingv1.NetworkPolicyIngressRule{}
   602  			UpdatePolicy(ctx, k8s, policy, nsX)
   603  
   604  			reachabilityDeny := NewReachability(k8s.AllPodStrings(), true)
   605  			reachabilityDeny.ExpectPeer(&Peer{}, &Peer{Namespace: nsX}, false)
   606  			ValidateOrFail(k8s, &TestCase{ToPort: 81, Protocol: v1.ProtocolTCP, Reachability: reachabilityDeny})
   607  		})
   608  
   609  		f.It("should allow ingress access from updated namespace", feature.NetworkPolicy, func(ctx context.Context) {
   610  			protocols := []v1.Protocol{protocolTCP}
   611  			ports := []int32{80}
   612  			k8s = initializeResources(ctx, f, protocols, ports)
   613  			nsX, nsY, _ := getK8sNamespaces(k8s)
   614  			ginkgo.DeferCleanup(DeleteNamespaceLabel, k8s, nsY, "ns2")
   615  
   616  			allowedLabels := &metav1.LabelSelector{
   617  				MatchLabels: map[string]string{
   618  					"ns2": "updated",
   619  				},
   620  			}
   621  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
   622  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{NamespaceSelector: allowedLabels})
   623  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-client-a-via-ns-selector", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
   624  			CreatePolicy(ctx, k8s, policy, nsX)
   625  
   626  			reachability := NewReachability(k8s.AllPodStrings(), true)
   627  			reachability.ExpectAllIngress(NewPodString(nsX, "a"), false)
   628  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   629  
   630  			// add a new label
   631  			AddNamespaceLabel(ctx, k8s, nsY, "ns2", "updated")
   632  
   633  			// anything from namespace 'y' should be able to get to x/a
   634  			reachabilityWithLabel := NewReachability(k8s.AllPodStrings(), true)
   635  			reachabilityWithLabel.ExpectAllIngress(NewPodString(nsX, "a"), false)
   636  			reachabilityWithLabel.ExpectPeer(&Peer{Namespace: nsY}, &Peer{}, true)
   637  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachabilityWithLabel})
   638  		})
   639  
   640  		f.It("should allow ingress access from updated pod", feature.NetworkPolicy, func(ctx context.Context) {
   641  			protocols := []v1.Protocol{protocolTCP}
   642  			ports := []int32{80}
   643  			k8s = initializeResources(ctx, f, protocols, ports)
   644  			nsX, _, _ := getK8sNamespaces(k8s)
   645  			ginkgo.DeferCleanup(ResetPodLabels, k8s, nsX, "b")
   646  
   647  			// add a new label
   648  			matchLabels := map[string]string{"pod": "b", "pod2": "updated"}
   649  			allowedLabels := &metav1.LabelSelector{MatchLabels: matchLabels}
   650  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
   651  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{PodSelector: allowedLabels})
   652  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-client-a-via-pod-selector", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
   653  			CreatePolicy(ctx, k8s, policy, nsX)
   654  
   655  			reachability := NewReachability(k8s.AllPodStrings(), true)
   656  			reachability.ExpectAllIngress(NewPodString(nsX, "a"), false)
   657  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   658  
   659  			AddPodLabels(ctx, k8s, nsX, "b", matchLabels)
   660  
   661  			ginkgo.By("x/b is able to reach x/a when label is updated")
   662  
   663  			reachabilityWithLabel := NewReachability(k8s.AllPodStrings(), true)
   664  			reachabilityWithLabel.ExpectAllIngress(NewPodString(nsX, "a"), false)
   665  			reachabilityWithLabel.Expect(NewPodString(nsX, "b"), NewPodString(nsX, "a"), true)
   666  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachabilityWithLabel})
   667  		})
   668  
   669  		f.It("should deny ingress from pods on other namespaces", feature.NetworkPolicy, func(ctx context.Context) {
   670  			protocols := []v1.Protocol{protocolTCP}
   671  			ports := []int32{80}
   672  			k8s = initializeResources(ctx, f, protocols, ports)
   673  			nsX, nsY, nsZ := getK8sNamespaces(k8s)
   674  			IngressRules := networkingv1.NetworkPolicyIngressRule{}
   675  			IngressRules.From = append(IngressRules.From, networkingv1.NetworkPolicyPeer{PodSelector: &metav1.LabelSelector{MatchLabels: map[string]string{}}})
   676  			policy := GenNetworkPolicyWithNameAndPodSelector("deny-empty-policy", metav1.LabelSelector{}, SetSpecIngressRules(IngressRules))
   677  			CreatePolicy(ctx, k8s, policy, nsX)
   678  
   679  			reachability := NewReachability(k8s.AllPodStrings(), true)
   680  			reachability.ExpectPeer(&Peer{Namespace: nsY}, &Peer{Namespace: nsX}, false)
   681  			reachability.ExpectPeer(&Peer{Namespace: nsZ}, &Peer{Namespace: nsX}, false)
   682  
   683  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   684  		})
   685  
   686  		f.It("should deny ingress access to updated pod", feature.NetworkPolicy, func(ctx context.Context) {
   687  			protocols := []v1.Protocol{protocolTCP}
   688  			ports := []int32{80}
   689  			k8s = initializeResources(ctx, f, protocols, ports)
   690  			nsX, _, _ := getK8sNamespaces(k8s)
   691  			ginkgo.DeferCleanup(ResetPodLabels, k8s, nsX, "a")
   692  
   693  			policy := GenNetworkPolicyWithNameAndPodSelector("deny-ingress-via-label-selector",
   694  				metav1.LabelSelector{MatchLabels: map[string]string{"target": "isolated"}}, SetSpecIngressRules())
   695  			CreatePolicy(ctx, k8s, policy, nsX)
   696  
   697  			ginkgo.By("Verify that everything can reach x/a")
   698  			reachability := NewReachability(k8s.AllPodStrings(), true)
   699  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   700  
   701  			AddPodLabels(ctx, k8s, nsX, "a", map[string]string{"target": "isolated"})
   702  
   703  			reachabilityIsolated := NewReachability(k8s.AllPodStrings(), true)
   704  			reachabilityIsolated.ExpectAllIngress(NewPodString(nsX, "a"), false)
   705  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachabilityIsolated})
   706  		})
   707  
   708  		f.It("should deny egress from pods based on PodSelector", feature.NetworkPolicy, func(ctx context.Context) {
   709  			protocols := []v1.Protocol{protocolTCP}
   710  			ports := []int32{80}
   711  			k8s = initializeResources(ctx, f, protocols, ports)
   712  			nsX, _, _ := getK8sNamespaces(k8s)
   713  			policy := GenNetworkPolicyWithNameAndPodSelector("deny-egress-pod-a", metav1.LabelSelector{MatchLabels: map[string]string{"pod": "a"}}, SetSpecEgressRules())
   714  			CreatePolicy(ctx, k8s, policy, nsX)
   715  
   716  			reachability := NewReachability(k8s.AllPodStrings(), true)
   717  			reachability.ExpectAllEgress(NewPodString(nsX, "a"), false)
   718  
   719  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   720  		})
   721  
   722  		f.It("should deny egress from all pods in a namespace", feature.NetworkPolicy, func(ctx context.Context) {
   723  			protocols := []v1.Protocol{protocolTCP}
   724  			ports := []int32{80}
   725  			k8s = initializeResources(ctx, f, protocols, ports)
   726  			nsX, _, _ := getK8sNamespaces(k8s)
   727  			policy := GenNetworkPolicyWithNameAndPodSelector("deny-egress-ns-x", metav1.LabelSelector{}, SetSpecEgressRules())
   728  			CreatePolicy(ctx, k8s, policy, nsX)
   729  
   730  			reachability := NewReachability(k8s.AllPodStrings(), true)
   731  			reachability.ExpectPeer(&Peer{Namespace: nsX}, &Peer{}, false)
   732  
   733  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   734  		})
   735  
   736  		f.It("should work with Ingress, Egress specified together", feature.NetworkPolicy, func(ctx context.Context) {
   737  			allowedPodLabels := &metav1.LabelSelector{MatchLabels: map[string]string{"pod": "b"}}
   738  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
   739  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{PodSelector: allowedPodLabels})
   740  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-client-a-via-pod-selector", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
   741  
   742  			// add an egress rule on to it...
   743  			policy.Spec.Egress = []networkingv1.NetworkPolicyEgressRule{
   744  				{
   745  					Ports: []networkingv1.NetworkPolicyPort{
   746  						{
   747  							// don't use named ports
   748  							Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 80},
   749  						},
   750  					},
   751  				},
   752  			}
   753  			policy.Spec.PolicyTypes = []networkingv1.PolicyType{networkingv1.PolicyTypeEgress, networkingv1.PolicyTypeIngress}
   754  			protocols := []v1.Protocol{protocolTCP}
   755  			ports := []int32{80, 81}
   756  			k8s = initializeResources(ctx, f, protocols, ports)
   757  			nsX, _, _ := getK8sNamespaces(k8s)
   758  			CreatePolicy(ctx, k8s, policy, nsX)
   759  
   760  			reachabilityPort80 := NewReachability(k8s.AllPodStrings(), true)
   761  			reachabilityPort80.ExpectAllIngress(NewPodString(nsX, "a"), false)
   762  			reachabilityPort80.Expect(NewPodString(nsX, "b"), NewPodString(nsX, "a"), true)
   763  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachabilityPort80})
   764  
   765  			ginkgo.By("validating that port 81 doesn't work")
   766  			// meanwhile no egress traffic on 81 should work, since our egress policy is on 80
   767  			reachabilityPort81 := NewReachability(k8s.AllPodStrings(), true)
   768  			reachabilityPort81.ExpectAllIngress(NewPodString(nsX, "a"), false)
   769  			reachabilityPort81.ExpectAllEgress(NewPodString(nsX, "a"), false)
   770  			reachabilityPort81.Expect(NewPodString(nsX, "b"), NewPodString(nsX, "a"), true)
   771  			ValidateOrFail(k8s, &TestCase{ToPort: 81, Protocol: v1.ProtocolTCP, Reachability: reachabilityPort81})
   772  		})
   773  
   774  		f.It("should support denying of egress traffic on the client side (even if the server explicitly allows this traffic)", feature.NetworkPolicy, func(ctx context.Context) {
   775  			// x/a --> y/a and y/b
   776  			// Egress allowed to y/a only. Egress to y/b should be blocked
   777  			// Ingress on y/a and y/b allow traffic from x/a
   778  			// Expectation: traffic from x/a to y/a allowed only, traffic from x/a to y/b denied by egress policy
   779  
   780  			protocols := []v1.Protocol{protocolTCP}
   781  			ports := []int32{80}
   782  			k8s = initializeResources(ctx, f, protocols, ports)
   783  			nsX, nsY, _ := getK8sNamespaces(k8s)
   784  
   785  			// Building egress policy for x/a to y/a only
   786  			allowedEgressNamespaces := &metav1.LabelSelector{
   787  				MatchLabels: map[string]string{
   788  					namespaceLabelKey: nsY,
   789  				},
   790  			}
   791  			allowedEgressPods := &metav1.LabelSelector{
   792  				MatchLabels: map[string]string{
   793  					"pod": "a",
   794  				},
   795  			}
   796  			egressRule1 := networkingv1.NetworkPolicyEgressRule{}
   797  			egressRule1.To = append(egressRule1.To, networkingv1.NetworkPolicyPeer{NamespaceSelector: allowedEgressNamespaces, PodSelector: allowedEgressPods})
   798  			egressPolicy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-to-ns-y-pod-a", map[string]string{"pod": "a"}, SetSpecEgressRules(egressRule1))
   799  			CreatePolicy(ctx, k8s, egressPolicy, nsX)
   800  
   801  			// Creating ingress policy to allow from x/a to y/a and y/b
   802  			allowedIngressNamespaces := &metav1.LabelSelector{
   803  				MatchLabels: map[string]string{
   804  					namespaceLabelKey: nsX,
   805  				},
   806  			}
   807  			allowedIngressPods := &metav1.LabelSelector{
   808  				MatchLabels: map[string]string{
   809  					"pod": "a",
   810  				},
   811  			}
   812  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
   813  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{NamespaceSelector: allowedIngressNamespaces, PodSelector: allowedIngressPods})
   814  			allowIngressPolicyPodA := GenNetworkPolicyWithNameAndPodMatchLabel("allow-from-xa-on-ya-match-selector", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
   815  			allowIngressPolicyPodB := GenNetworkPolicyWithNameAndPodMatchLabel("allow-from-xa-on-yb-match-selector", map[string]string{"pod": "b"}, SetSpecIngressRules(ingressRule))
   816  
   817  			CreatePolicy(ctx, k8s, allowIngressPolicyPodA, nsY)
   818  			CreatePolicy(ctx, k8s, allowIngressPolicyPodB, nsY)
   819  
   820  			// While applying the policies, traffic needs to be allowed by both egress and ingress rules.
   821  			// Egress rules only
   822  			// 	xa	xb	xc	ya	yb	yc	za	zb	zc
   823  			// xa	X	X	X	.	*X*	X	X	X	X
   824  			// xb	.	.	.	.	.	.	.	.	.
   825  			// xc	.	.	.	.	.	.	.	.	.
   826  			// ya	.	.	.	.	.	.	.	.	.
   827  			// yb	.	.	.	.	.	.	.	.	.
   828  			// yc	.	.	.	.	.	.	.	.	.
   829  			// za	.	.	.	.	.	.	.	.	.
   830  			// zb	.	.	.	.	.	.	.	.	.
   831  			// zc	.	.	.	.	.	.	.	.	.
   832  			// Ingress rules only
   833  			// 	xa	xb	xc	ya	yb	yc	za	zb	zc
   834  			// xa	.	.	.	*.*	.	.	.	.	.
   835  			// xb	.	.	X	X	.	.	.	.	.
   836  			// xc	.	.	X	X	.	.	.	.	.
   837  			// ya	.	.	X	X	.	.	.	.	.
   838  			// yb	.	.	X	X	.	.	.	.	.
   839  			// yc	.	.	X	X	.	.	.	.	.
   840  			// za	.	.	X	X	.	.	.	.	.
   841  			// zb	.	.	X	X	.	.	.	.	.
   842  			// zc	.	.	X	X	.	.	.	.	.
   843  			// In the resulting truth table, connections from x/a should only be allowed to y/a. x/a to y/b should be blocked by the egress on x/a.
   844  			// Expected results
   845  			// 	xa	xb	xc	ya	yb	yc	za	zb	zc
   846  			// xa	X	X	X	.	*X*	X	X	X	X
   847  			// xb	.	.	.	X	X	.	.	.	.
   848  			// xc	.	.	.	X	X	.	.	.	.
   849  			// ya	.	.	.	X	X	.	.	.	.
   850  			// yb	.	.	.	X	X	.	.	.	.
   851  			// yc	.	.	.	X	X	.	.	.	.
   852  			// za	.	.	.	X	X	.	.	.	.
   853  			// zb	.	.	.	X	X	.	.	.	.
   854  			// zc	.	.	.	X	X	.	.	.	.
   855  
   856  			reachability := NewReachability(k8s.AllPodStrings(), true)
   857  			// Default all traffic flows.
   858  			// Exception: x/a can only egress to y/a, others are false
   859  			// Exception: y/a can only allow ingress from x/a, others are false
   860  			// Exception: y/b has no allowed traffic (due to limit on x/a egress)
   861  
   862  			reachability.ExpectPeer(&Peer{Namespace: nsX, Pod: "a"}, &Peer{}, false)
   863  			reachability.ExpectPeer(&Peer{}, &Peer{Namespace: nsY, Pod: "a"}, false)
   864  			reachability.ExpectPeer(&Peer{Namespace: nsX, Pod: "a"}, &Peer{Namespace: nsY, Pod: "a"}, true)
   865  			reachability.ExpectPeer(&Peer{}, &Peer{Namespace: nsY, Pod: "b"}, false)
   866  
   867  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   868  		})
   869  
   870  		f.It("should enforce egress policy allowing traffic to a server in a different namespace based on PodSelector and NamespaceSelector", feature.NetworkPolicy, func(ctx context.Context) {
   871  			protocols := []v1.Protocol{protocolTCP}
   872  			ports := []int32{80}
   873  			k8s = initializeResources(ctx, f, protocols, ports)
   874  			nsX, nsY, _ := getK8sNamespaces(k8s)
   875  			allowedNamespaces := &metav1.LabelSelector{
   876  				MatchLabels: map[string]string{
   877  					namespaceLabelKey: nsY,
   878  				},
   879  			}
   880  			allowedPods := &metav1.LabelSelector{
   881  				MatchLabels: map[string]string{
   882  					"pod": "a",
   883  				},
   884  			}
   885  			egressRule1 := networkingv1.NetworkPolicyEgressRule{}
   886  			egressRule1.To = append(egressRule1.To, networkingv1.NetworkPolicyPeer{NamespaceSelector: allowedNamespaces, PodSelector: allowedPods})
   887  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-to-ns-y-pod-a", map[string]string{"pod": "a"}, SetSpecEgressRules(egressRule1))
   888  			CreatePolicy(ctx, k8s, policy, nsX)
   889  
   890  			reachability := NewReachability(k8s.AllPodStrings(), true)
   891  			reachability.ExpectAllEgress(NewPodString(nsX, "a"), false)
   892  			reachability.Expect(NewPodString(nsX, "a"), NewPodString(nsY, "a"), true)
   893  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   894  		})
   895  
   896  		f.It("should enforce ingress policy allowing any port traffic to a server on a specific protocol", feature.NetworkPolicy, feature.UDP, func(ctx context.Context) {
   897  			protocols := []v1.Protocol{protocolTCP, protocolUDP}
   898  			ports := []int32{80}
   899  			k8s = initializeResources(ctx, f, protocols, ports)
   900  			nsX, _, _ := getK8sNamespaces(k8s)
   901  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
   902  			ingressRule.Ports = append(ingressRule.Ports, networkingv1.NetworkPolicyPort{Protocol: &protocolTCP})
   903  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-ingress-by-proto", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
   904  			CreatePolicy(ctx, k8s, policy, nsX)
   905  
   906  			reachabilityTCP := NewReachability(k8s.AllPodStrings(), true)
   907  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachabilityTCP})
   908  
   909  			reachabilityUDP := NewReachability(k8s.AllPodStrings(), true)
   910  			reachabilityUDP.ExpectPeer(&Peer{}, &Peer{Namespace: nsX, Pod: "a"}, false)
   911  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolUDP, Reachability: reachabilityUDP})
   912  		})
   913  
   914  		f.It("should enforce multiple ingress policies with ingress allow-all policy taking precedence", feature.NetworkPolicy, func(ctx context.Context) {
   915  			protocols := []v1.Protocol{protocolTCP}
   916  			ports := []int32{81}
   917  			k8s = initializeResources(ctx, f, protocols, ports)
   918  			nsX, _, _ := getK8sNamespaces(k8s)
   919  			IngressRules := networkingv1.NetworkPolicyIngressRule{}
   920  			IngressRules.Ports = append(IngressRules.Ports, networkingv1.NetworkPolicyPort{Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 80}})
   921  			policyAllowOnlyPort80 := GenNetworkPolicyWithNameAndPodMatchLabel("allow-ingress-port-80", map[string]string{}, SetSpecIngressRules(IngressRules))
   922  			CreatePolicy(ctx, k8s, policyAllowOnlyPort80, nsX)
   923  
   924  			ginkgo.By("The policy targets port 80 -- so let's make sure traffic on port 81 is blocked")
   925  
   926  			reachability := NewReachability(k8s.AllPodStrings(), true)
   927  			reachability.ExpectPeer(&Peer{}, &Peer{Namespace: nsX}, false)
   928  			ValidateOrFail(k8s, &TestCase{ToPort: 81, Protocol: v1.ProtocolTCP, Reachability: reachability})
   929  
   930  			ginkgo.By("Allowing all ports")
   931  
   932  			policyAllowAll := GenNetworkPolicyWithNameAndPodMatchLabel("allow-ingress", map[string]string{}, SetSpecIngressRules(networkingv1.NetworkPolicyIngressRule{}))
   933  			CreatePolicy(ctx, k8s, policyAllowAll, nsX)
   934  
   935  			reachabilityAll := NewReachability(k8s.AllPodStrings(), true)
   936  			ValidateOrFail(k8s, &TestCase{ToPort: 81, Protocol: v1.ProtocolTCP, Reachability: reachabilityAll})
   937  		})
   938  
   939  		f.It("should enforce multiple egress policies with egress allow-all policy taking precedence", feature.NetworkPolicy, func(ctx context.Context) {
   940  			egressRule := networkingv1.NetworkPolicyEgressRule{}
   941  			egressRule.Ports = append(egressRule.Ports, networkingv1.NetworkPolicyPort{Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 80}})
   942  			policyAllowPort80 := GenNetworkPolicyWithNameAndPodMatchLabel("allow-egress-port-80", map[string]string{}, SetSpecEgressRules(egressRule))
   943  			protocols := []v1.Protocol{protocolTCP}
   944  			ports := []int32{81}
   945  			k8s = initializeResources(ctx, f, protocols, ports)
   946  			nsX, _, _ := getK8sNamespaces(k8s)
   947  			CreatePolicy(ctx, k8s, policyAllowPort80, nsX)
   948  
   949  			ginkgo.By("Making sure ingress doesn't work other than port 80")
   950  
   951  			reachability := NewReachability(k8s.AllPodStrings(), true)
   952  			reachability.ExpectPeer(&Peer{Namespace: nsX}, &Peer{}, false)
   953  			ValidateOrFail(k8s, &TestCase{ToPort: 81, Protocol: v1.ProtocolTCP, Reachability: reachability})
   954  
   955  			ginkgo.By("Allowing all ports")
   956  
   957  			policyAllowAll := GenNetworkPolicyWithNameAndPodMatchLabel("allow-egress", map[string]string{}, SetSpecEgressRules(networkingv1.NetworkPolicyEgressRule{}))
   958  			CreatePolicy(ctx, k8s, policyAllowAll, nsX)
   959  
   960  			reachabilityAll := NewReachability(k8s.AllPodStrings(), true)
   961  			ValidateOrFail(k8s, &TestCase{ToPort: 81, Protocol: v1.ProtocolTCP, Reachability: reachabilityAll})
   962  		})
   963  
   964  		f.It("should stop enforcing policies after they are deleted", feature.NetworkPolicy, func(ctx context.Context) {
   965  			ginkgo.By("Creating a network policy for the server which denies all traffic.")
   966  
   967  			// Deny all traffic into and out of "x".
   968  			policy := GenNetworkPolicyWithNameAndPodSelector("deny-all", metav1.LabelSelector{}, SetSpecIngressRules(), SetSpecEgressRules())
   969  			protocols := []v1.Protocol{protocolTCP}
   970  			ports := []int32{80}
   971  			k8s = initializeResources(ctx, f, protocols, ports)
   972  			nsX, _, _ := getK8sNamespaces(k8s)
   973  			CreatePolicy(ctx, k8s, policy, nsX)
   974  			reachability := NewReachability(k8s.AllPodStrings(), true)
   975  
   976  			// Expect all traffic into, and out of "x" to be False.
   977  			reachability.ExpectPeer(&Peer{Namespace: nsX}, &Peer{}, false)
   978  			reachability.ExpectPeer(&Peer{}, &Peer{Namespace: nsX}, false)
   979  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
   980  
   981  			err := k8s.cleanNetworkPolicies(ctx)
   982  			time.Sleep(3 * time.Second) // TODO we can remove this eventually, its just a hack to keep CI stable.
   983  			framework.ExpectNoError(err, "unable to clean network policies")
   984  
   985  			// Now the policy is deleted, we expect all connectivity to work again.
   986  			reachabilityAll := NewReachability(k8s.AllPodStrings(), true)
   987  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachabilityAll})
   988  		})
   989  
   990  		// TODO, figure out how the next 3 tests should work with dual stack : do we need a different abstraction then just "podIP"?
   991  
   992  		f.It("should allow egress access to server in CIDR block", feature.NetworkPolicy, func(ctx context.Context) {
   993  			// Getting podServer's status to get podServer's IP, to create the CIDR
   994  			protocols := []v1.Protocol{protocolTCP}
   995  			ports := []int32{80}
   996  			k8s = initializeResources(ctx, f, protocols, ports)
   997  			nsX, nsY, _ := getK8sNamespaces(k8s)
   998  			podList, err := f.ClientSet.CoreV1().Pods(nsY).List(ctx, metav1.ListOptions{LabelSelector: "pod=b"})
   999  			framework.ExpectNoError(err, "Failing to list pods in namespace y")
  1000  			pod := podList.Items[0]
  1001  
  1002  			hostMask := 32
  1003  			if utilnet.IsIPv6String(pod.Status.PodIP) {
  1004  				hostMask = 128
  1005  			}
  1006  			podServerCIDR := fmt.Sprintf("%s/%d", pod.Status.PodIP, hostMask)
  1007  			egressRule1 := networkingv1.NetworkPolicyEgressRule{}
  1008  			egressRule1.To = append(egressRule1.To, networkingv1.NetworkPolicyPeer{IPBlock: &networkingv1.IPBlock{CIDR: podServerCIDR}})
  1009  			policyAllowCIDR := GenNetworkPolicyWithNameAndPodMatchLabel("allow-client-a-via-cidr-egress-rule",
  1010  				map[string]string{"pod": "a"}, SetSpecEgressRules(egressRule1))
  1011  			CreatePolicy(ctx, k8s, policyAllowCIDR, nsX)
  1012  
  1013  			reachability := NewReachability(k8s.AllPodStrings(), true)
  1014  			reachability.ExpectAllEgress(NewPodString(nsX, "a"), false)
  1015  			reachability.Expect(NewPodString(nsX, "a"), NewPodString(nsY, "b"), true)
  1016  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
  1017  		})
  1018  
  1019  		f.It("should enforce except clause while egress access to server in CIDR block", feature.NetworkPolicy, func(ctx context.Context) {
  1020  			// Getting podServer's status to get podServer's IP, to create the CIDR with except clause
  1021  			protocols := []v1.Protocol{protocolTCP}
  1022  			ports := []int32{80}
  1023  			k8s = initializeResources(ctx, f, protocols, ports)
  1024  			nsX, _, _ := getK8sNamespaces(k8s)
  1025  			podList, err := f.ClientSet.CoreV1().Pods(nsX).List(ctx, metav1.ListOptions{LabelSelector: "pod=a"})
  1026  			framework.ExpectNoError(err, "Failing to find pod x/a")
  1027  			podA := podList.Items[0]
  1028  
  1029  			podServerAllowCIDR := fmt.Sprintf("%s/4", podA.Status.PodIP)
  1030  
  1031  			podList, err = f.ClientSet.CoreV1().Pods(nsX).List(ctx, metav1.ListOptions{LabelSelector: "pod=b"})
  1032  			framework.ExpectNoError(err, "Failing to find pod x/b")
  1033  			podB := podList.Items[0]
  1034  
  1035  			hostMask := 32
  1036  			if utilnet.IsIPv6String(podB.Status.PodIP) {
  1037  				hostMask = 128
  1038  			}
  1039  			podServerExceptList := []string{fmt.Sprintf("%s/%d", podB.Status.PodIP, hostMask)}
  1040  
  1041  			egressRule1 := networkingv1.NetworkPolicyEgressRule{}
  1042  			egressRule1.To = append(egressRule1.To, networkingv1.NetworkPolicyPeer{IPBlock: &networkingv1.IPBlock{CIDR: podServerAllowCIDR, Except: podServerExceptList}})
  1043  			policyAllowCIDR := GenNetworkPolicyWithNameAndPodMatchLabel("allow-client-a-via-cidr-egress-rule", map[string]string{"pod": "a"}, SetSpecEgressRules(egressRule1))
  1044  
  1045  			CreatePolicy(ctx, k8s, policyAllowCIDR, nsX)
  1046  
  1047  			reachability := NewReachability(k8s.AllPodStrings(), true)
  1048  			reachability.Expect(NewPodString(nsX, "a"), NewPodString(nsX, "b"), false)
  1049  
  1050  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
  1051  		})
  1052  
  1053  		f.It("should ensure an IP overlapping both IPBlock.CIDR and IPBlock.Except is allowed", feature.NetworkPolicy, func(ctx context.Context) {
  1054  			// Getting podServer's status to get podServer's IP, to create the CIDR with except clause
  1055  			protocols := []v1.Protocol{protocolTCP}
  1056  			ports := []int32{80}
  1057  			k8s = initializeResources(ctx, f, protocols, ports)
  1058  			nsX, _, _ := getK8sNamespaces(k8s)
  1059  			podList, err := f.ClientSet.CoreV1().Pods(nsX).List(ctx, metav1.ListOptions{LabelSelector: "pod=a"})
  1060  			framework.ExpectNoError(err, "Failing to find pod x/a")
  1061  			podA := podList.Items[0]
  1062  
  1063  			podList, err = f.ClientSet.CoreV1().Pods(nsX).List(ctx, metav1.ListOptions{LabelSelector: "pod=b"})
  1064  			framework.ExpectNoError(err, "Failing to find pod x/b")
  1065  			podB := podList.Items[0]
  1066  
  1067  			// Exclude podServer's IP with an Except clause
  1068  			hostMask := 32
  1069  			if utilnet.IsIPv6String(podB.Status.PodIP) {
  1070  				hostMask = 128
  1071  			}
  1072  
  1073  			podServerAllowCIDR := fmt.Sprintf("%s/4", podA.Status.PodIP)
  1074  			podServerExceptList := []string{fmt.Sprintf("%s/%d", podB.Status.PodIP, hostMask)}
  1075  			egressRule1 := networkingv1.NetworkPolicyEgressRule{}
  1076  			egressRule1.To = append(egressRule1.To, networkingv1.NetworkPolicyPeer{IPBlock: &networkingv1.IPBlock{CIDR: podServerAllowCIDR, Except: podServerExceptList}})
  1077  			policyAllowCIDR := GenNetworkPolicyWithNameAndPodMatchLabel("allow-client-a-via-cidr-egress-rule",
  1078  				map[string]string{"pod": "a"}, SetSpecEgressRules(egressRule1))
  1079  			CreatePolicy(ctx, k8s, policyAllowCIDR, nsX)
  1080  
  1081  			reachability := NewReachability(k8s.AllPodStrings(), true)
  1082  			reachability.Expect(NewPodString(nsX, "a"), NewPodString(nsX, "b"), false)
  1083  
  1084  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
  1085  
  1086  			podBIP := fmt.Sprintf("%s/%d", podB.Status.PodIP, hostMask)
  1087  			//// Create NetworkPolicy which allows access to the podServer using podServer's IP in allow CIDR.
  1088  			egressRule3 := networkingv1.NetworkPolicyEgressRule{}
  1089  			egressRule3.To = append(egressRule3.To, networkingv1.NetworkPolicyPeer{IPBlock: &networkingv1.IPBlock{CIDR: podBIP}})
  1090  			allowPolicy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-client-a-via-cidr-egress-rule",
  1091  				map[string]string{"pod": "a"}, SetSpecEgressRules(egressRule3))
  1092  			// SHOULD THIS BE UPDATE OR CREATE JAY TESTING 10/31
  1093  			UpdatePolicy(ctx, k8s, allowPolicy, nsX)
  1094  
  1095  			reachabilityAllow := NewReachability(k8s.AllPodStrings(), true)
  1096  			reachabilityAllow.ExpectAllEgress(NewPodString(nsX, "a"), false)
  1097  			reachabilityAllow.Expect(NewPodString(nsX, "a"), NewPodString(nsX, "b"), true)
  1098  
  1099  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachabilityAllow})
  1100  		})
  1101  
  1102  		f.It("should enforce policies to check ingress and egress policies can be controlled independently based on PodSelector", feature.NetworkPolicy, func(ctx context.Context) {
  1103  			/*
  1104  					Test steps:
  1105  					1. Verify every pod in every namespace can talk to each other
  1106  				       - including a -> b and b -> a
  1107  					2. Create a policy to allow egress a -> b (target = a)
  1108  				    3. Create a policy to *deny* ingress b -> a (target = a)
  1109  					4. Verify a -> b allowed; b -> a blocked
  1110  			*/
  1111  			targetLabels := map[string]string{"pod": "a"}
  1112  
  1113  			ginkgo.By("Creating a network policy for pod-a which allows Egress traffic to pod-b.")
  1114  
  1115  			allowEgressPolicy := GenNetworkPolicyWithNameAndPodSelector("allow-egress-for-target",
  1116  				metav1.LabelSelector{MatchLabels: targetLabels}, SetSpecEgressRules(networkingv1.NetworkPolicyEgressRule{}))
  1117  			protocols := []v1.Protocol{protocolTCP}
  1118  			ports := []int32{80}
  1119  			k8s = initializeResources(ctx, f, protocols, ports)
  1120  			nsX, _, _ := getK8sNamespaces(k8s)
  1121  			CreatePolicy(ctx, k8s, allowEgressPolicy, nsX)
  1122  
  1123  			allowEgressReachability := NewReachability(k8s.AllPodStrings(), true)
  1124  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: allowEgressReachability})
  1125  
  1126  			ginkgo.By("Creating a network policy for pod-a that denies traffic from pod-b.")
  1127  
  1128  			denyAllIngressPolicy := GenNetworkPolicyWithNameAndPodSelector("deny-ingress-via-label-selector", metav1.LabelSelector{MatchLabels: targetLabels}, SetSpecIngressRules())
  1129  			CreatePolicy(ctx, k8s, denyAllIngressPolicy, nsX)
  1130  
  1131  			denyIngressToXReachability := NewReachability(k8s.AllPodStrings(), true)
  1132  			denyIngressToXReachability.ExpectAllIngress(NewPodString(nsX, "a"), false)
  1133  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: denyIngressToXReachability})
  1134  		})
  1135  
  1136  		// This test *does* apply to plugins that do not implement SCTP. It is a
  1137  		// security hole if you fail this test, because you are allowing TCP
  1138  		// traffic that is supposed to be blocked.
  1139  		f.It("should not mistakenly treat 'protocol: SCTP' as 'protocol: TCP', even if the plugin doesn't support SCTP", feature.NetworkPolicy, func(ctx context.Context) {
  1140  			protocols := []v1.Protocol{protocolTCP}
  1141  			ports := []int32{81}
  1142  			k8s = initializeResources(ctx, f, protocols, ports)
  1143  			nsX, _, _ := getK8sNamespaces(k8s)
  1144  
  1145  			ginkgo.By("Creating a default-deny ingress policy.")
  1146  			// Empty podSelector blocks the entire namespace
  1147  			policy := GenNetworkPolicyWithNameAndPodSelector("deny-ingress", metav1.LabelSelector{}, SetSpecIngressRules())
  1148  			CreatePolicy(ctx, k8s, policy, nsX)
  1149  
  1150  			ginkgo.By("Creating a network policy for the server which allows traffic only via SCTP on port 81.")
  1151  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
  1152  			ingressRule.Ports = append(ingressRule.Ports, networkingv1.NetworkPolicyPort{Port: &intstr.IntOrString{IntVal: 81}, Protocol: &protocolSCTP})
  1153  			policy = GenNetworkPolicyWithNameAndPodMatchLabel("allow-only-sctp-ingress-on-port-81", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
  1154  			CreatePolicy(ctx, k8s, policy, nsX)
  1155  
  1156  			ginkgo.By("Trying to connect to TCP port 81, which should be blocked by the deny-ingress policy.")
  1157  			reachability := NewReachability(k8s.AllPodStrings(), true)
  1158  			reachability.ExpectPeer(&Peer{}, &Peer{Namespace: nsX}, false)
  1159  			ValidateOrFail(k8s, &TestCase{ToPort: 81, Protocol: v1.ProtocolTCP, Reachability: reachability})
  1160  		})
  1161  
  1162  		// This test *does* apply to plugins that do not implement SCTP. It is a
  1163  		// security hole if you fail this test, because you are allowing TCP
  1164  		// traffic that is supposed to be blocked.
  1165  		f.It("should properly isolate pods that are selected by a policy allowing SCTP, even if the plugin doesn't support SCTP", feature.NetworkPolicy, func(ctx context.Context) {
  1166  			ginkgo.By("Creating a network policy for the server which allows traffic only via SCTP on port 80.")
  1167  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
  1168  			ingressRule.Ports = append(ingressRule.Ports, networkingv1.NetworkPolicyPort{Port: &intstr.IntOrString{IntVal: 80}, Protocol: &protocolSCTP})
  1169  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-only-sctp-ingress-on-port-80", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
  1170  			protocols := []v1.Protocol{protocolTCP}
  1171  			ports := []int32{81}
  1172  			k8s = initializeResources(ctx, f, protocols, ports)
  1173  			nsX, _, _ := getK8sNamespaces(k8s)
  1174  			CreatePolicy(ctx, k8s, policy, nsX)
  1175  
  1176  			ginkgo.By("Trying to connect to TCP port 81, which should be blocked by implicit isolation.")
  1177  			reachability := NewReachability(k8s.AllPodStrings(), true)
  1178  			reachability.ExpectAllIngress(NewPodString(nsX, "a"), false)
  1179  			ValidateOrFail(k8s, &TestCase{ToPort: 81, Protocol: v1.ProtocolTCP, Reachability: reachability})
  1180  		})
  1181  
  1182  		f.It("should not allow access by TCP when a policy specifies only UDP", feature.NetworkPolicy, func(ctx context.Context) {
  1183  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
  1184  			ingressRule.Ports = append(ingressRule.Ports, networkingv1.NetworkPolicyPort{Port: &intstr.IntOrString{IntVal: 81}, Protocol: &protocolUDP})
  1185  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-only-udp-ingress-on-port-81", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
  1186  			protocols := []v1.Protocol{protocolTCP}
  1187  			ports := []int32{81}
  1188  			k8s = initializeResources(ctx, f, protocols, ports)
  1189  			nsX, _, _ := getK8sNamespaces(k8s)
  1190  			CreatePolicy(ctx, k8s, policy, nsX)
  1191  
  1192  			ginkgo.By("Creating a network policy for the server which allows traffic only via UDP on port 81.")
  1193  
  1194  			// Probing with TCP, so all traffic should be dropped.
  1195  			reachability := NewReachability(k8s.AllPodStrings(), true)
  1196  			reachability.ExpectAllIngress(NewPodString(nsX, "a"), false)
  1197  			ValidateOrFail(k8s, &TestCase{ToPort: 81, Protocol: v1.ProtocolTCP, Reachability: reachability})
  1198  		})
  1199  
  1200  		// Note that this default ns functionality is maintained by the APIMachinery group, but we test it here anyways because its an important feature.
  1201  		f.It("should enforce policy to allow traffic based on NamespaceSelector with MatchLabels using default ns label", feature.NetworkPolicy, func(ctx context.Context) {
  1202  			protocols := []v1.Protocol{protocolTCP}
  1203  			ports := []int32{80}
  1204  			k8s = initializeResources(ctx, f, protocols, ports)
  1205  			nsX, nsY, nsZ := getK8sNamespaces(k8s)
  1206  			allowedLabels := &metav1.LabelSelector{
  1207  				MatchLabels: map[string]string{
  1208  					v1.LabelMetadataName: nsY,
  1209  				},
  1210  			}
  1211  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
  1212  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{NamespaceSelector: allowedLabels})
  1213  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-client-a-via-ns-selector-for-immutable-ns-label", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
  1214  			CreatePolicy(ctx, k8s, policy, nsX)
  1215  
  1216  			reachability := NewReachability(k8s.AllPodStrings(), true)
  1217  			reachability.ExpectPeer(&Peer{Namespace: nsX}, &Peer{Namespace: nsX, Pod: "a"}, false)
  1218  			reachability.ExpectPeer(&Peer{Namespace: nsZ}, &Peer{Namespace: nsX, Pod: "a"}, false)
  1219  
  1220  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
  1221  		})
  1222  
  1223  		// Note that this default ns functionality is maintained by the APIMachinery group, but we test it here anyways because its an important feature.
  1224  		f.It("should enforce policy based on NamespaceSelector with MatchExpressions using default ns label", feature.NetworkPolicy, func(ctx context.Context) {
  1225  			protocols := []v1.Protocol{protocolTCP}
  1226  			ports := []int32{80}
  1227  			k8s = initializeResources(ctx, f, protocols, ports)
  1228  			nsX, nsY, _ := getK8sNamespaces(k8s)
  1229  			allowedNamespaces := &metav1.LabelSelector{
  1230  				MatchExpressions: []metav1.LabelSelectorRequirement{{
  1231  					Key:      v1.LabelMetadataName,
  1232  					Operator: metav1.LabelSelectorOpNotIn,
  1233  					Values:   []string{nsY},
  1234  				}},
  1235  			}
  1236  			egressRule := networkingv1.NetworkPolicyEgressRule{}
  1237  			egressRule.To = append(egressRule.To, networkingv1.NetworkPolicyPeer{NamespaceSelector: allowedNamespaces})
  1238  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-ns-y-match-selector-for-immutable-ns-label", map[string]string{"pod": "a"}, SetSpecEgressRules(egressRule))
  1239  			CreatePolicy(ctx, k8s, policy, nsX)
  1240  
  1241  			reachability := NewReachability(k8s.AllPodStrings(), true)
  1242  			reachability.ExpectPeer(&Peer{Namespace: nsX, Pod: "a"}, &Peer{Namespace: nsY}, false)
  1243  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachability})
  1244  		})
  1245  	})
  1246  })
  1247  
  1248  var _ = common.SIGDescribe("Netpol [LinuxOnly]", func() {
  1249  	f := framework.NewDefaultFramework("udp-network-policy")
  1250  	f.SkipNamespaceCreation = true
  1251  	f.NamespacePodSecurityLevel = admissionapi.LevelBaseline
  1252  	var k8s *kubeManager
  1253  	ginkgo.BeforeEach(func() {
  1254  		// Windows does not support UDP testing via agnhost.
  1255  		e2eskipper.SkipIfNodeOSDistroIs("windows")
  1256  	})
  1257  
  1258  	ginkgo.Context("NetworkPolicy between server and client using UDP", func() {
  1259  
  1260  		f.It("should support a 'default-deny-ingress' policy", feature.NetworkPolicy, func(ctx context.Context) {
  1261  			protocols := []v1.Protocol{protocolUDP}
  1262  			ports := []int32{80}
  1263  			k8s = initializeResources(ctx, f, protocols, ports)
  1264  			nsX, _, _ := getK8sNamespaces(k8s)
  1265  			policy := GenNetworkPolicyWithNameAndPodSelector("deny-all", metav1.LabelSelector{}, SetSpecIngressRules())
  1266  			CreatePolicy(ctx, k8s, policy, nsX)
  1267  
  1268  			reachability := NewReachability(k8s.AllPodStrings(), true)
  1269  			reachability.ExpectPeer(&Peer{}, &Peer{Namespace: nsX}, false)
  1270  
  1271  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolUDP, Reachability: reachability})
  1272  		})
  1273  
  1274  		f.It("should enforce policy based on Ports", feature.NetworkPolicy, func(ctx context.Context) {
  1275  			ginkgo.By("Creating a network policy allowPort81Policy which only allows allow listed namespaces (y) to connect on exactly one port (81)")
  1276  			protocols := []v1.Protocol{protocolUDP}
  1277  			ports := []int32{81}
  1278  			k8s = initializeResources(ctx, f, protocols, ports)
  1279  			nsX, nsY, nsZ := getK8sNamespaces(k8s)
  1280  			allowedLabels := &metav1.LabelSelector{
  1281  				MatchLabels: map[string]string{
  1282  					namespaceLabelKey: nsY,
  1283  				},
  1284  			}
  1285  
  1286  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
  1287  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{NamespaceSelector: allowedLabels})
  1288  			ingressRule.Ports = append(ingressRule.Ports, networkingv1.NetworkPolicyPort{Port: &intstr.IntOrString{IntVal: 81}, Protocol: &protocolUDP})
  1289  			allowPort81Policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-ingress-on-port-81-ns-x", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
  1290  			CreatePolicy(ctx, k8s, allowPort81Policy, nsX)
  1291  
  1292  			reachability := NewReachability(k8s.AllPodStrings(), true)
  1293  			reachability.ExpectPeer(&Peer{Namespace: nsX}, &Peer{Namespace: nsX, Pod: "a"}, false)
  1294  			reachability.ExpectPeer(&Peer{Namespace: nsZ}, &Peer{Namespace: nsX, Pod: "a"}, false)
  1295  
  1296  			ValidateOrFail(k8s, &TestCase{ToPort: 81, Protocol: v1.ProtocolUDP, Reachability: reachability})
  1297  		})
  1298  
  1299  		f.It("should enforce policy to allow traffic only from a pod in a different namespace based on PodSelector and NamespaceSelector", feature.NetworkPolicy, func(ctx context.Context) {
  1300  			protocols := []v1.Protocol{protocolUDP}
  1301  			ports := []int32{80}
  1302  			k8s = initializeResources(ctx, f, protocols, ports)
  1303  			nsX, nsY, _ := getK8sNamespaces(k8s)
  1304  			allowedNamespaces := &metav1.LabelSelector{
  1305  				MatchLabels: map[string]string{
  1306  					namespaceLabelKey: nsY,
  1307  				},
  1308  			}
  1309  			allowedPods := &metav1.LabelSelector{
  1310  				MatchLabels: map[string]string{
  1311  					"pod": "a",
  1312  				},
  1313  			}
  1314  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
  1315  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{NamespaceSelector: allowedNamespaces, PodSelector: allowedPods})
  1316  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-ns-y-pod-a-via-namespace-pod-selector", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
  1317  			CreatePolicy(ctx, k8s, policy, nsX)
  1318  
  1319  			reachability := NewReachability(k8s.AllPodStrings(), true)
  1320  			reachability.ExpectAllIngress(NewPodString(nsX, "a"), false)
  1321  			reachability.Expect(NewPodString(nsY, "a"), NewPodString(nsX, "a"), true)
  1322  
  1323  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolUDP, Reachability: reachability})
  1324  		})
  1325  	})
  1326  })
  1327  
  1328  var _ = common.SIGDescribe("Netpol", feature.SCTPConnectivity, "[LinuxOnly]", func() {
  1329  	f := framework.NewDefaultFramework("sctp-network-policy")
  1330  	f.SkipNamespaceCreation = true
  1331  	f.NamespacePodSecurityLevel = admissionapi.LevelBaseline
  1332  	var k8s *kubeManager
  1333  	ginkgo.BeforeEach(func() {
  1334  		// Windows does not support network policies.
  1335  		e2eskipper.SkipIfNodeOSDistroIs("windows")
  1336  	})
  1337  
  1338  	ginkgo.Context("NetworkPolicy between server and client using SCTP", func() {
  1339  
  1340  		f.It("should support a 'default-deny-ingress' policy", feature.NetworkPolicy, func(ctx context.Context) {
  1341  			protocols := []v1.Protocol{protocolSCTP}
  1342  			ports := []int32{80}
  1343  			k8s = initializeResources(ctx, f, protocols, ports)
  1344  			nsX, _, _ := getK8sNamespaces(k8s)
  1345  			policy := GenNetworkPolicyWithNameAndPodSelector("deny-all", metav1.LabelSelector{}, SetSpecIngressRules())
  1346  			CreatePolicy(ctx, k8s, policy, nsX)
  1347  
  1348  			reachability := NewReachability(k8s.AllPodStrings(), true)
  1349  			reachability.ExpectPeer(&Peer{}, &Peer{Namespace: nsX}, false)
  1350  
  1351  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolSCTP, Reachability: reachability})
  1352  		})
  1353  
  1354  		f.It("should enforce policy based on Ports", feature.NetworkPolicy, func(ctx context.Context) {
  1355  			ginkgo.By("Creating a network allowPort81Policy which only allows allow listed namespaces (y) to connect on exactly one port (81)")
  1356  			protocols := []v1.Protocol{protocolSCTP}
  1357  			ports := []int32{81}
  1358  			k8s = initializeResources(ctx, f, protocols, ports)
  1359  			nsX, nsY, nsZ := getK8sNamespaces(k8s)
  1360  			allowedLabels := &metav1.LabelSelector{
  1361  				MatchLabels: map[string]string{
  1362  					namespaceLabelKey: nsY,
  1363  				},
  1364  			}
  1365  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
  1366  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{NamespaceSelector: allowedLabels})
  1367  			ingressRule.Ports = append(ingressRule.Ports, networkingv1.NetworkPolicyPort{Port: &intstr.IntOrString{IntVal: 81}, Protocol: &protocolSCTP})
  1368  			allowPort81Policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-ingress-on-port-81-ns-x", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
  1369  			CreatePolicy(ctx, k8s, allowPort81Policy, nsX)
  1370  
  1371  			reachability := NewReachability(k8s.AllPodStrings(), true)
  1372  			reachability.ExpectPeer(&Peer{Namespace: nsX}, &Peer{Namespace: nsX, Pod: "a"}, false)
  1373  			reachability.ExpectPeer(&Peer{Namespace: nsZ}, &Peer{Namespace: nsX, Pod: "a"}, false)
  1374  
  1375  			ValidateOrFail(k8s, &TestCase{ToPort: 81, Protocol: v1.ProtocolSCTP, Reachability: reachability})
  1376  		})
  1377  
  1378  		f.It("should enforce policy to allow traffic only from a pod in a different namespace based on PodSelector and NamespaceSelector", feature.NetworkPolicy, func(ctx context.Context) {
  1379  			protocols := []v1.Protocol{protocolSCTP}
  1380  			ports := []int32{80}
  1381  			k8s = initializeResources(ctx, f, protocols, ports)
  1382  			nsX, nsY, _ := getK8sNamespaces(k8s)
  1383  			allowedNamespaces := &metav1.LabelSelector{
  1384  				MatchLabels: map[string]string{
  1385  					namespaceLabelKey: nsY,
  1386  				},
  1387  			}
  1388  			allowedPods := &metav1.LabelSelector{
  1389  				MatchLabels: map[string]string{
  1390  					"pod": "a",
  1391  				},
  1392  			}
  1393  			ingressRule := networkingv1.NetworkPolicyIngressRule{}
  1394  			ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{NamespaceSelector: allowedNamespaces, PodSelector: allowedPods})
  1395  			policy := GenNetworkPolicyWithNameAndPodMatchLabel("allow-ns-y-pod-a-via-namespace-pod-selector", map[string]string{"pod": "a"}, SetSpecIngressRules(ingressRule))
  1396  			CreatePolicy(ctx, k8s, policy, nsX)
  1397  
  1398  			reachability := NewReachability(k8s.AllPodStrings(), true)
  1399  			reachability.ExpectAllIngress(NewPodString(nsX, "a"), false)
  1400  			reachability.Expect(NewPodString(nsY, "a"), NewPodString(nsX, "a"), true)
  1401  
  1402  			ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolSCTP, Reachability: reachability})
  1403  		})
  1404  	})
  1405  })
  1406  
  1407  // getNamespaceBaseNames returns the set of base namespace names used by this test, taking a root ns as input.
  1408  // The framework will also append a unique suffix when creating the namespaces.
  1409  // This allows tests to run in parallel.
  1410  func getNamespaceBaseNames(rootNs string) []string {
  1411  	if rootNs != "" {
  1412  		rootNs += "-"
  1413  	}
  1414  	nsX := fmt.Sprintf("%sx", rootNs)
  1415  	nsY := fmt.Sprintf("%sy", rootNs)
  1416  	nsZ := fmt.Sprintf("%sz", rootNs)
  1417  	return []string{nsX, nsY, nsZ}
  1418  }
  1419  
  1420  // defaultModel creates a new "model" pod system under namespaces (x,y,z) which has pods a, b, and c.  Thus resulting in the
  1421  // truth table matrix that is identical for all tests, comprising 81 total connections between 9 pods (x/a, x/b, x/c, ..., z/c).
  1422  func defaultModel(namespaces []string, protocols []v1.Protocol, ports []int32) *Model {
  1423  	if framework.NodeOSDistroIs("windows") {
  1424  		return NewWindowsModel(namespaces, []string{"a", "b", "c"}, ports)
  1425  	}
  1426  	return NewModel(namespaces, []string{"a", "b", "c"}, ports, protocols)
  1427  }
  1428  
  1429  // getK8sNamespaces returns the 3 actual namespace names.
  1430  func getK8sNamespaces(k8s *kubeManager) (string, string, string) {
  1431  	ns := k8s.NamespaceNames()
  1432  	return ns[0], ns[1], ns[2]
  1433  }
  1434  
  1435  func initializeCluster(ctx context.Context, f *framework.Framework, protocols []v1.Protocol, ports []int32) (*kubeManager, error) {
  1436  	dnsDomain := framework.TestContext.ClusterDNSDomain
  1437  	framework.Logf("dns domain: %s", dnsDomain)
  1438  
  1439  	k8s := newKubeManager(f, dnsDomain)
  1440  	rootNs := f.BaseName
  1441  	namespaceBaseNames := getNamespaceBaseNames(rootNs)
  1442  
  1443  	model := defaultModel(namespaceBaseNames, protocols, ports)
  1444  
  1445  	framework.Logf("initializing cluster: ensuring namespaces, pods and services exist and are ready")
  1446  
  1447  	if err := k8s.initializeClusterFromModel(ctx, model); err != nil {
  1448  		return nil, err
  1449  	}
  1450  
  1451  	framework.Logf("finished initializing cluster state")
  1452  
  1453  	if err := waitForHTTPServers(k8s, model); err != nil {
  1454  		return nil, err
  1455  	}
  1456  
  1457  	return k8s, nil
  1458  }
  1459  
  1460  // initializeResources uses the e2e framework to create all necessary namespace resources, based on the network policy
  1461  // model derived from the framework.  It then waits for the resources described by the model to be up and running
  1462  // (i.e. all pods are ready and running in their namespaces).
  1463  func initializeResources(ctx context.Context, f *framework.Framework, protocols []v1.Protocol, ports []int32) *kubeManager {
  1464  	k8s, err := initializeCluster(ctx, f, protocols, ports)
  1465  	framework.ExpectNoError(err, "unable to initialize resources")
  1466  	return k8s
  1467  }