1
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
44
45
46
47
48
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
111
112 var _ = common.SIGDescribe("Netpol", func() {
113 f := framework.NewDefaultFramework("netpol")
114 f.SkipNamespaceCreation = true
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
123 protocols := []v1.Protocol{protocolTCP}
124
125
126 ports := []int32{80}
127
128
129 k8s = initializeResources(ctx, f, protocols, ports)
130
131
132 nsX, _, _ := getK8sNamespaces(k8s)
133 policy := GenNetworkPolicyWithNameAndPodSelector("deny-ingress", metav1.LabelSelector{}, SetSpecIngressRules())
134
135
136 CreatePolicy(ctx, k8s, policy, nsX)
137
138
139 reachability := NewReachability(k8s.AllPodStrings(), true)
140
141 reachability.ExpectPeer(&Peer{}, &Peer{Namespace: nsX}, false)
142
143
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
192 policy := GenNetworkPolicyWithNameAndPodSelector("deny-all", metav1.LabelSelector{}, SetSpecIngressRules())
193 CreatePolicy(ctx, k8s, policy, nsX)
194 })
195
196
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
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
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
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
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
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
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
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
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
631 AddNamespaceLabel(ctx, k8s, nsY, "ns2", "updated")
632
633
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
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
743 policy.Spec.Egress = []networkingv1.NetworkPolicyEgressRule{
744 {
745 Ports: []networkingv1.NetworkPolicyPort{
746 {
747
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
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
776
777
778
779
780 protocols := []v1.Protocol{protocolTCP}
781 ports := []int32{80}
782 k8s = initializeResources(ctx, f, protocols, ports)
783 nsX, nsY, _ := getK8sNamespaces(k8s)
784
785
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
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
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856 reachability := NewReachability(k8s.AllPodStrings(), true)
857
858
859
860
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
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
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)
983 framework.ExpectNoError(err, "unable to clean network policies")
984
985
986 reachabilityAll := NewReachability(k8s.AllPodStrings(), true)
987 ValidateOrFail(k8s, &TestCase{ToPort: 80, Protocol: v1.ProtocolTCP, Reachability: reachabilityAll})
988 })
989
990
991
992 f.It("should allow egress access to server in CIDR block", feature.NetworkPolicy, func(ctx context.Context) {
993
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
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
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
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
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
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
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
1137
1138
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
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
1163
1164
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
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
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
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
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
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
1408
1409
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
1421
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
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
1461
1462
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 }
1468
View as plain text