diff --git a/conformance/base/baseline_admin_network_policy/core-gress-rules-combined.yaml b/conformance/base/baseline_admin_network_policy/core-gress-rules-combined.yaml new file mode 100644 index 00000000..d076c6cb --- /dev/null +++ b/conformance/base/baseline_admin_network_policy/core-gress-rules-combined.yaml @@ -0,0 +1,121 @@ +apiVersion: policy.networking.k8s.io/v1alpha1 +kind: BaselineAdminNetworkPolicy +metadata: + name: default +spec: + subject: + namespaces: + matchLabels: + kubernetes.io/metadata.name: network-policy-conformance-gryffindor + egress: + - name: "allow-to-ravenclaw-everything" + action: "Allow" + to: + - namespaces: + namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: network-policy-conformance-ravenclaw + - name: "deny-to-ravenclaw-everything" + action: "Deny" + to: + - namespaces: + namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: network-policy-conformance-ravenclaw + - name: "deny-to-slytherin-at-ports-80-53-9003" + action: "Deny" + to: + - namespaces: + namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: network-policy-conformance-slytherin + ports: + - portNumber: + protocol: TCP + port: 80 + - portNumber: + protocol: UDP + port: 53 + - portNumber: + protocol: SCTP + port: 9003 + - name: "allow-to-hufflepuff-at-ports-8080-5353" + action: "Allow" + to: + - namespaces: + namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: network-policy-conformance-hufflepuff + ports: + - portNumber: + protocol: TCP + port: 8080 + - portNumber: + protocol: UDP + port: 5353 + - portNumber: + protocol: SCTP + port: 9003 + - name: "deny-to-hufflepuff-everything-else" + action: "Deny" + to: + - namespaces: + namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: network-policy-conformance-hufflepuff + ingress: + - name: "allow-from-ravenclaw-everything" + action: "Allow" + from: + - namespaces: + namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: network-policy-conformance-ravenclaw + - name: "deny-from-ravenclaw-everything" + action: "Deny" + from: + - namespaces: + namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: network-policy-conformance-ravenclaw + - name: "deny-from-slytherin-at-port-80-53-9003" + action: "Deny" + from: + - namespaces: + namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: network-policy-conformance-slytherin + ports: + - portNumber: + protocol: TCP + port: 80 + - portNumber: + protocol: UDP + port: 53 + - portNumber: + protocol: SCTP + port: 9003 + - name: "allow-from-hufflepuff-at-port-80-5353-9003" + action: "Allow" + from: + - namespaces: + namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: network-policy-conformance-hufflepuff + ports: + - portNumber: + protocol: TCP + port: 80 + - portNumber: + protocol: UDP + port: 5353 + - portNumber: + protocol: SCTP + port: 9003 + - name: "deny-from-hufflepuff-everything-else" + action: "Deny" + from: + - namespaces: + namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: network-policy-conformance-hufflepuff diff --git a/conformance/tests/admin-network-policy-core-gress-rules.go b/conformance/tests/admin-network-policy-core-gress-rules.go index 4aee11e0..460f1717 100644 --- a/conformance/tests/admin-network-policy-core-gress-rules.go +++ b/conformance/tests/admin-network-policy-core-gress-rules.go @@ -42,7 +42,7 @@ var AdminNetworkPolicyGress = suite.ConformanceTest{ Features: []suite.SupportedFeature{ suite.SupportAdminNetworkPolicy, }, - Manifests: []string{"base/admin-network-policy/core-gress-rules-combined.yaml"}, + Manifests: []string{"base/admin_network_policy/core-gress-rules-combined.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { t.Run("Should support an 'allow-gress' policy across different protocols", func(t *testing.T) { diff --git a/conformance/tests/baseline-admin-network-policy-core-gress-rules.go b/conformance/tests/baseline-admin-network-policy-core-gress-rules.go new file mode 100644 index 00000000..16f4c5a9 --- /dev/null +++ b/conformance/tests/baseline-admin-network-policy-core-gress-rules.go @@ -0,0 +1,322 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package tests + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + v1 "k8s.io/api/core/v1" + "k8s.io/kubernetes/test/e2e/framework" + "sigs.k8s.io/controller-runtime/pkg/client" + + "sigs.k8s.io/network-policy-api/apis/v1alpha1" + "sigs.k8s.io/network-policy-api/conformance/utils/kubernetes" + "sigs.k8s.io/network-policy-api/conformance/utils/suite" +) + +func init() { + ConformanceTests = append(ConformanceTests, + BaselineAdminNetworkPolicyGress, + ) +} + +var BaselineAdminNetworkPolicyGress = suite.ConformanceTest{ + ShortName: "BaselineAdminNetworkPolicyGress", + Description: "Tests support for combined ingress and egress traffic rules in the baseline admin network policy API based on a server and client model", + Features: []suite.SupportedFeature{ + suite.SupportBaselineAdminNetworkPolicy, + }, + Manifests: []string{"base/baseline_admin_network_policy/core-gress-rules-combined.yaml"}, + Test: func(t *testing.T, s *suite.ConformanceTestSuite) { + + t.Run("Should support an 'allow-gress' policy across different protocols", func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), s.TimeoutConfig.GetTimeout) + defer cancel() + // This test uses `default` BANP + + /* First; let's test egress works! */ + // luna-lovegood-0 is our server pod in ravenclaw namespace + clientPod := &v1.Pod{} + err := s.Client.Get(ctx, client.ObjectKey{ + Namespace: "network-policy-conformance-ravenclaw", + Name: "luna-lovegood-0", + }, clientPod) + framework.ExpectNoError(err, "unable to fetch the server pod") + // harry-potter-x is our client pod in gryffindor namespace + // ensure egress is ALLOWED to ravenclaw from gryffindor + // egressRule at index0 will take precedence over egressRule at index1; thus ALLOW takes precedence over DENY since rules are ordered + success := kubernetes.PokeServer(t, "network-policy-conformance-gryffindor", "harry-potter-0", "tcp", + clientPod.Status.PodIP, int32(80), s.TimeoutConfig.RequestTimeout, true) + assert.Equal(t, true, success) + success = kubernetes.PokeServer(t, "network-policy-conformance-gryffindor", "harry-potter-1", "udp", + clientPod.Status.PodIP, int32(53), s.TimeoutConfig.RequestTimeout, true) + assert.Equal(t, true, success) + success = kubernetes.PokeServer(t, "network-policy-conformance-gryffindor", "harry-potter-0", "sctp", + clientPod.Status.PodIP, int32(9003), s.TimeoutConfig.RequestTimeout, true) + assert.Equal(t, true, success) + + /* Second; let's test ingress works! */ + // harry-potter-0 is our server pod in gryffindor namespace + err = s.Client.Get(ctx, client.ObjectKey{ + Namespace: "network-policy-conformance-gryffindor", + Name: "harry-potter-0", + }, clientPod) + framework.ExpectNoError(err, "unable to fetch the server pod") + // luna-lovegood-x is our client pod in ravenclaw namespace + // ensure ingress is ALLOWED from ravenclaw to gryffindor + // ingressRule at index0 will take precedence over ingressRule at index1; thus ALLOW takes precedence over DENY since rules are ordered + success = kubernetes.PokeServer(t, "network-policy-conformance-ravenclaw", "luna-lovegood-0", "tcp", + clientPod.Status.PodIP, int32(80), s.TimeoutConfig.RequestTimeout, true) + assert.Equal(t, true, success) + success = kubernetes.PokeServer(t, "network-policy-conformance-ravenclaw", "luna-lovegood-1", "udp", + clientPod.Status.PodIP, int32(53), s.TimeoutConfig.RequestTimeout, true) + assert.Equal(t, true, success) + success = kubernetes.PokeServer(t, "network-policy-conformance-ravenclaw", "luna-lovegood-1", "sctp", + clientPod.Status.PodIP, int32(9003), s.TimeoutConfig.RequestTimeout, true) + assert.Equal(t, true, success) + }) + + t.Run("Should support an 'allow-gress' policy across different protocols at the specified ports", func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), s.TimeoutConfig.GetTimeout) + defer cancel() + // This test uses `default` BANP + + /* First; let's test egress works! */ + // cedric-diggory-1 is our server pod in hufflepuff namespace + clientPod := &v1.Pod{} + err := s.Client.Get(ctx, client.ObjectKey{ + Namespace: "network-policy-conformance-hufflepuff", + Name: "cedric-diggory-1", + }, clientPod) + framework.ExpectNoError(err, "unable to fetch the server pod") + // harry-potter-0 is our client pod in gryffindor namespace + // ensure egress is ALLOWED to hufflepuff from gryffindor at port 8080; egressRule at index5 + success := kubernetes.PokeServer(t, "network-policy-conformance-gryffindor", "harry-potter-0", "tcp", + clientPod.Status.PodIP, int32(8080), s.TimeoutConfig.RequestTimeout, true) + assert.Equal(t, true, success) + // harry-potter-1 is our client pod in gryffindor namespace + // ensure egress is DENIED to hufflepuff from gryffindor for rest of the traffic; egressRule at index6 + success = kubernetes.PokeServer(t, "network-policy-conformance-gryffindor", "harry-potter-1", "tcp", + clientPod.Status.PodIP, int32(80), s.TimeoutConfig.RequestTimeout, false) + assert.Equal(t, true, success) + // harry-potter-0 is our client pod in gryffindor namespace + // ensure egress is ALLOWED to hufflepuff from gryffindor at port 5353; egressRule at index5 + success = kubernetes.PokeServer(t, "network-policy-conformance-gryffindor", "harry-potter-0", "udp", + clientPod.Status.PodIP, int32(5353), s.TimeoutConfig.RequestTimeout, true) + assert.Equal(t, true, success) + // harry-potter-1 is our client pod in gryffindor namespace + // ensure egress is DENIED to hufflepuff from gryffindor for rest of the traffic; egressRule at index6 + success = kubernetes.PokeServer(t, "network-policy-conformance-gryffindor", "harry-potter-1", "udp", + clientPod.Status.PodIP, int32(53), s.TimeoutConfig.RequestTimeout, false) + assert.Equal(t, true, success) + // harry-potter-0 is our client pod in gryffindor namespace + // ensure egress is ALLOWED to hufflepuff from gryffindor at port 9003; egressRule at index5 + success = kubernetes.PokeServer(t, "network-policy-conformance-gryffindor", "harry-potter-0", "sctp", + clientPod.Status.PodIP, int32(9003), s.TimeoutConfig.RequestTimeout, true) + assert.Equal(t, true, success) + // harry-potter-1 is our client pod in gryffindor namespace + // ensure egress is DENIED to hufflepuff from gryffindor for rest of the traffic; egressRule at index6 + success = kubernetes.PokeServer(t, "network-policy-conformance-gryffindor", "harry-potter-1", "sctp", + clientPod.Status.PodIP, int32(9005), s.TimeoutConfig.RequestTimeout, false) + assert.Equal(t, true, success) + + /* Second; let's test ingress works! */ + // harry-potter-1 is our server pod in gryffindor namespace + err = s.Client.Get(ctx, client.ObjectKey{ + Namespace: "network-policy-conformance-gryffindor", + Name: "harry-potter-1", + }, clientPod) + framework.ExpectNoError(err, "unable to fetch the server pod") + // cedric-diggory-0 is our client pod in hufflepuff namespace + // ensure ingress is ALLOWED from hufflepuff to gryffindor at port 80; ingressRule at index5 + success = kubernetes.PokeServer(t, "network-policy-conformance-hufflepuff", "cedric-diggory-0", "tcp", + clientPod.Status.PodIP, int32(80), s.TimeoutConfig.RequestTimeout, true) + assert.Equal(t, true, success) + // cedric-diggory-1 is our client pod in hufflepuff namespace + // ensure ingress is DENIED from hufflepuff to gryffindor for rest of the traffic; ingressRule at index6 + success = kubernetes.PokeServer(t, "network-policy-conformance-hufflepuff", "cedric-diggory-1", "tcp", + clientPod.Status.PodIP, int32(8080), s.TimeoutConfig.RequestTimeout, false) + assert.Equal(t, true, success) + // cedric-diggory-0 is our client pod in hufflepuff namespace + // ensure ingress is ALLOWED from hufflepuff to gryffindor at port 5353; ingressRule at index5 + success = kubernetes.PokeServer(t, "network-policy-conformance-hufflepuff", "cedric-diggory-0", "udp", + clientPod.Status.PodIP, int32(5353), s.TimeoutConfig.RequestTimeout, true) + assert.Equal(t, true, success) + // cedric-diggory-1 is our client pod in hufflepuff namespace + // ensure ingress is DENIED from hufflepuff to gryffindor for rest of the traffic; ingressRule at index6 + success = kubernetes.PokeServer(t, "network-policy-conformance-hufflepuff", "cedric-diggory-1", "udp", + clientPod.Status.PodIP, int32(53), s.TimeoutConfig.RequestTimeout, false) + assert.Equal(t, true, success) + // cedric-diggory-0 is our client pod in hufflepuff namespace + // ensure ingress is ALLOWED from hufflepuff to gryffindor at port 9003; ingressRule at index5 + success = kubernetes.PokeServer(t, "network-policy-conformance-hufflepuff", "cedric-diggory-0", "sctp", + clientPod.Status.PodIP, int32(9003), s.TimeoutConfig.RequestTimeout, true) + assert.Equal(t, true, success) + // cedric-diggory-1 is our client pod in hufflepuff namespace + // ensure ingress is DENIED from hufflepuff to gryffindor for rest of the traffic; ingressRule at index6 + success = kubernetes.PokeServer(t, "network-policy-conformance-hufflepuff", "cedric-diggory-1", "sctp", + clientPod.Status.PodIP, int32(9005), s.TimeoutConfig.RequestTimeout, false) + assert.Equal(t, true, success) + }) + + t.Run("Should support an 'deny-gress' policy across different protocols", func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), s.TimeoutConfig.GetTimeout) + defer cancel() + // This test uses `default` BANP + + /* First; let's test egress works! */ + // luna-lovegood-1 is our server pod in ravenclaw namespace + clientPod := &v1.Pod{} + err := s.Client.Get(ctx, client.ObjectKey{ + Namespace: "network-policy-conformance-ravenclaw", + Name: "luna-lovegood-1", + }, clientPod) + framework.ExpectNoError(err, "unable to fetch the server pod") + banp := &v1alpha1.BaselineAdminNetworkPolicy{} + err = s.Client.Get(ctx, client.ObjectKey{ + Name: "default", + }, banp) + framework.ExpectNoError(err, "unable to fetch the baseline admin network policy") + // swap rules at index0 and index1 for both ingress and egress + allowOutRule := banp.DeepCopy().Spec.Egress[0] + banp.Spec.Egress[0] = banp.DeepCopy().Spec.Egress[1] + banp.Spec.Egress[1] = allowOutRule + allowInRule := banp.DeepCopy().Spec.Ingress[0] + banp.Spec.Ingress[0] = banp.DeepCopy().Spec.Ingress[1] + banp.Spec.Ingress[1] = allowInRule + err = s.Client.Update(ctx, banp) + framework.ExpectNoError(err, "unable to update the baseline admin network policy") + // harry-potter-x is our client pod in gryffindor namespace + // ensure egress is DENIED to ravenclaw from gryffindor + // egressRule at index0 will take precedence over egressRule at index1; thus DENY takes precedence over ALLOW since rules are ordered + success := kubernetes.PokeServer(t, "network-policy-conformance-gryffindor", "harry-potter-0", "tcp", + clientPod.Status.PodIP, int32(80), s.TimeoutConfig.RequestTimeout, false) + assert.Equal(t, true, success) + success = kubernetes.PokeServer(t, "network-policy-conformance-gryffindor", "harry-potter-1", "udp", + clientPod.Status.PodIP, int32(53), s.TimeoutConfig.RequestTimeout, false) + assert.Equal(t, true, success) + success = kubernetes.PokeServer(t, "network-policy-conformance-gryffindor", "harry-potter-0", "sctp", + clientPod.Status.PodIP, int32(9003), s.TimeoutConfig.RequestTimeout, false) + assert.Equal(t, true, success) + + /* Second; let's test ingress works! */ + // harry-potter-1 is our server pod in gryffindor namespace + err = s.Client.Get(ctx, client.ObjectKey{ + Namespace: "network-policy-conformance-gryffindor", + Name: "harry-potter-1", + }, clientPod) + framework.ExpectNoError(err, "unable to fetch the server pod") + // luna-lovegood-x is our client pod in ravenclaw namespace + // ensure ingress is DENIED from ravenclaw to gryffindor + // ingressRule at index0 will take precedence over ingressRule at index1; thus DENY takes precedence over ALLOW since rules are ordered + success = kubernetes.PokeServer(t, "network-policy-conformance-ravenclaw", "luna-lovegood-0", "tcp", + clientPod.Status.PodIP, int32(80), s.TimeoutConfig.RequestTimeout, false) + assert.Equal(t, true, success) + success = kubernetes.PokeServer(t, "network-policy-conformance-ravenclaw", "luna-lovegood-1", "udp", + clientPod.Status.PodIP, int32(53), s.TimeoutConfig.RequestTimeout, false) + assert.Equal(t, true, success) + success = kubernetes.PokeServer(t, "network-policy-conformance-ravenclaw", "luna-lovegood-1", "sctp", + clientPod.Status.PodIP, int32(9003), s.TimeoutConfig.RequestTimeout, false) + assert.Equal(t, true, success) + }) + + t.Run("Should support a 'deny-gress' policy across different protocols at the specified ports", func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), s.TimeoutConfig.GetTimeout) + defer cancel() + // This test uses `default` BANP + + /* First; let's test egress works! */ + // draco-malfoy-0 is our server pod in slytherin namespace + clientPod := &v1.Pod{} + err := s.Client.Get(ctx, client.ObjectKey{ + Namespace: "network-policy-conformance-slytherin", + Name: "draco-malfoy-0", + }, clientPod) + framework.ExpectNoError(err, "unable to fetch the server pod") + // harry-potter-0 is our client pod in gryffindor namespace + // ensure egress to slytherin is DENIED from gryffindor at port 80; egressRule at index3 + success := kubernetes.PokeServer(t, "network-policy-conformance-gryffindor", "harry-potter-0", "tcp", + clientPod.Status.PodIP, int32(80), s.TimeoutConfig.RequestTimeout, false) + assert.Equal(t, true, success) + // harry-potter-1 is our client pod in gryffindor namespace + // ensure egress to slytherin is ALLOWED from gryffindor for rest of the traffic; matches no rules hence allowed + success = kubernetes.PokeServer(t, "network-policy-conformance-gryffindor", "harry-potter-1", "tcp", + clientPod.Status.PodIP, int32(8080), s.TimeoutConfig.RequestTimeout, true) + assert.Equal(t, true, success) + // harry-potter-0 is our client pod in gryffindor namespace + // ensure egress to slytherin is DENIED from gryffindor at port 53; egressRule at index3 + success = kubernetes.PokeServer(t, "network-policy-conformance-gryffindor", "harry-potter-0", "udp", + clientPod.Status.PodIP, int32(53), s.TimeoutConfig.RequestTimeout, false) + assert.Equal(t, true, success) + // harry-potter-1 is our client pod in gryffindor namespace + // ensure egress to slytherin is ALLOWED from gryffindor for rest of the traffic; matches no rules hence allowed + success = kubernetes.PokeServer(t, "network-policy-conformance-gryffindor", "harry-potter-1", "udp", + clientPod.Status.PodIP, int32(5353), s.TimeoutConfig.RequestTimeout, true) + assert.Equal(t, true, success) + // harry-potter-0 is our client pod in gryffindor namespace + // ensure egress to slytherin is DENIED from gryffindor at port 53; egressRule at index3 + success = kubernetes.PokeServer(t, "network-policy-conformance-gryffindor", "harry-potter-0", "sctp", + clientPod.Status.PodIP, int32(9003), s.TimeoutConfig.RequestTimeout, false) + assert.Equal(t, true, success) + // harry-potter-1 is our client pod in gryffindor namespace + // ensure egress to slytherin is ALLOWED from gryffindor for rest of the traffic; matches no rules hence allowed + success = kubernetes.PokeServer(t, "network-policy-conformance-gryffindor", "harry-potter-1", "sctp", + clientPod.Status.PodIP, int32(9005), s.TimeoutConfig.RequestTimeout, true) + assert.Equal(t, true, success) + + /* Second; let's test ingress works! */ + // harry-potter-0 is our server pod in gryffindor namespace + err = s.Client.Get(ctx, client.ObjectKey{ + Namespace: "network-policy-conformance-gryffindor", + Name: "harry-potter-0", + }, clientPod) + framework.ExpectNoError(err, "unable to fetch the server pod") + // draco-malfoy-0 is our client pod in slytherin namespace + // ensure ingress from slytherin is DENIED to gryffindor at port 80; ingressRule at index3 + success = kubernetes.PokeServer(t, "network-policy-conformance-slytherin", "draco-malfoy-0", "tcp", + clientPod.Status.PodIP, int32(80), s.TimeoutConfig.RequestTimeout, false) + assert.Equal(t, true, success) + // draco-malfoy-1 is our client pod in slytherin namespace + // ensure ingress from slytherin is ALLOWED to gryffindor for rest of the traffic; matches no rules hence allowed + success = kubernetes.PokeServer(t, "network-policy-conformance-slytherin", "draco-malfoy-1", "tcp", + clientPod.Status.PodIP, int32(8080), s.TimeoutConfig.RequestTimeout, true) + assert.Equal(t, true, success) + // draco-malfoy-0 is our client pod in slytherin namespace + // ensure ingress from slytherin is DENIED to gryffindor at port 80; ingressRule at index3 + success = kubernetes.PokeServer(t, "network-policy-conformance-slytherin", "draco-malfoy-0", "udp", + clientPod.Status.PodIP, int32(53), s.TimeoutConfig.RequestTimeout, false) + assert.Equal(t, true, success) + // draco-malfoy-1 is our client pod in slytherin namespace + // ensure ingress from slytherin is ALLOWED to gryffindor for rest of the traffic; matches no rules hence allowed + success = kubernetes.PokeServer(t, "network-policy-conformance-slytherin", "draco-malfoy-1", "udp", + clientPod.Status.PodIP, int32(5353), s.TimeoutConfig.RequestTimeout, true) + assert.Equal(t, true, success) + // draco-malfoy-0 is our client pod in slytherin namespace + // ensure ingress from slytherin is DENIED to gryffindor at port 80; ingressRule at index3 + success = kubernetes.PokeServer(t, "network-policy-conformance-slytherin", "draco-malfoy-0", "sctp", + clientPod.Status.PodIP, int32(9003), s.TimeoutConfig.RequestTimeout, false) + assert.Equal(t, true, success) + // draco-malfoy-1 is our client pod in slytherin namespace + // ensure ingress from slytherin is ALLOWED to gryffindor for rest of the traffic; matches no rules hence allowed + success = kubernetes.PokeServer(t, "network-policy-conformance-slytherin", "draco-malfoy-1", "sctp", + clientPod.Status.PodIP, int32(9005), s.TimeoutConfig.RequestTimeout, true) + assert.Equal(t, true, success) + }) + }, +}