mirror of https://github.com/k3s-io/k3s
Add e2e network policy tests.
parent
03c9c48c81
commit
e3762c60a6
|
@ -82,6 +82,7 @@ go_library(
|
|||
"monitoring.go",
|
||||
"namespace.go",
|
||||
"network_partition.go",
|
||||
"network_policy.go",
|
||||
"networking.go",
|
||||
"networking_perf.go",
|
||||
"nodeoutofdisk.go",
|
||||
|
|
|
@ -0,0 +1,692 @@
|
|||
/*
|
||||
Copyright 2016 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 e2e
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||
"k8s.io/kubernetes/test/e2e/framework"
|
||||
|
||||
"fmt"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
/*
|
||||
The following Network Policy tests verify that policy object definitions
|
||||
are correctly enforced by a networking plugin. It accomplishes this by launching
|
||||
a simple netcat server, and two clients with different
|
||||
attributes. Each test case creates a network policy which should only allow
|
||||
connections from one of the clients. The test then asserts that the clients
|
||||
failed or succesfully connected as expected.
|
||||
*/
|
||||
|
||||
var _ = framework.KubeDescribe("NetworkPolicy", func() {
|
||||
f := framework.NewDefaultFramework("network-policy")
|
||||
|
||||
It("should support setting DefaultDeny namespace policy [Feature:NetworkPolicy]", func() {
|
||||
ns := f.Namespace
|
||||
|
||||
By("Create a simple server.")
|
||||
podServer, service := createServerPodAndService(f, ns, "server", []int{80})
|
||||
defer func() {
|
||||
By("Cleaning up the server.")
|
||||
if err := f.ClientSet.Core().Pods(ns.Name).Delete(podServer.Name, nil); err != nil {
|
||||
framework.Failf("unable to cleanup pod %v: %v", podServer.Name, err)
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
By("Cleaning up the server's service.")
|
||||
if err := f.ClientSet.Core().Services(ns.Name).Delete(service.Name, nil); err != nil {
|
||||
framework.Failf("unable to cleanup svc %v: %v", service.Name, err)
|
||||
}
|
||||
}()
|
||||
framework.Logf("Waiting for Server to come up.")
|
||||
err := framework.WaitForPodRunningInNamespace(f.ClientSet, podServer)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Create a pod with name 'client-a', which should be able to communicate with server.
|
||||
By("Creating client which will be able to contact the server since isolation is off.")
|
||||
testCanConnect(f, ns, "client-can-connect", service, 80)
|
||||
|
||||
framework.Logf("Enabling network isolation.")
|
||||
setNamespaceIsolation(f, ns, "DefaultDeny")
|
||||
|
||||
// Create a pod with name 'client-b', which will attempt to comunicate with the server,
|
||||
// but should not be able to now that isolation is on.
|
||||
testCannotConnect(f, ns, "client-cannot-connect", service, 80)
|
||||
})
|
||||
|
||||
It("should enforce policy based on PodSelector [Feature:NetworkPolicy]", func() {
|
||||
ns := f.Namespace
|
||||
setNamespaceIsolation(f, ns, "DefaultDeny")
|
||||
|
||||
By("Creating a simple server.")
|
||||
serverPod, service := createServerPodAndService(f, ns, "server", []int{80})
|
||||
defer func() {
|
||||
By("Cleaning up the server.")
|
||||
if err := f.ClientSet.Core().Pods(ns.Name).Delete(serverPod.Name, nil); err != nil {
|
||||
framework.Failf("unable to cleanup pod %v: %v", serverPod.Name, err)
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
By("Cleaning up the server's service.")
|
||||
if err := f.ClientSet.Core().Services(ns.Name).Delete(service.Name, nil); err != nil {
|
||||
framework.Failf("unable to cleanup svc %v: %v", service.Name, err)
|
||||
}
|
||||
}()
|
||||
framework.Logf("Waiting for Server to come up.")
|
||||
err := framework.WaitForPodRunningInNamespace(f.ClientSet, serverPod)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
By("Creating a network policy for the server which allows traffic from the pod 'client-a'.")
|
||||
|
||||
policy := v1beta1.NetworkPolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "allow-client-a-via-pod-selector",
|
||||
},
|
||||
Spec: v1beta1.NetworkPolicySpec{
|
||||
// Apply this policy to the Server
|
||||
PodSelector: metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"pod-name": serverPod.Name,
|
||||
},
|
||||
},
|
||||
// Allow traffic only from client-a
|
||||
Ingress: []v1beta1.NetworkPolicyIngressRule{{
|
||||
From: []v1beta1.NetworkPolicyPeer{{
|
||||
PodSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"pod-name": "client-a",
|
||||
},
|
||||
},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
result := v1beta1.NetworkPolicy{}
|
||||
err = f.ClientSet.Extensions().RESTClient().Post().Namespace(ns.Name).
|
||||
Resource("networkpolicies").Body(&policy).Do().Into(&result)
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer func() {
|
||||
By("Cleaning up the policy.")
|
||||
if err = f.ClientSet.Extensions().RESTClient().
|
||||
Delete().
|
||||
Namespace(ns.Name).
|
||||
Resource("networkpolicies").
|
||||
Name(policy.Name).
|
||||
Do().Error(); err != nil {
|
||||
framework.Failf("unable to cleanup policy %v: %v", policy.Name, err)
|
||||
}
|
||||
}()
|
||||
|
||||
By("Creating client-a which should be able to contact the server.")
|
||||
testCanConnect(f, ns, "client-a", service, 80)
|
||||
testCannotConnect(f, ns, "client-b", service, 80)
|
||||
})
|
||||
|
||||
It("should enforce policy based on Ports [Feature:NetworkPolicy]", func() {
|
||||
ns := f.Namespace
|
||||
|
||||
// Create Server with Service
|
||||
By("Creating a simple server.")
|
||||
serverPod, service := createServerPodAndService(f, ns, "server", []int{80, 81})
|
||||
defer func() {
|
||||
By("Cleaning up the server.")
|
||||
if err := f.ClientSet.Core().Pods(ns.Name).Delete(serverPod.Name, nil); err != nil {
|
||||
framework.Failf("unable to cleanup pod %v: %v", serverPod.Name, err)
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
By("Cleaning up the server's service.")
|
||||
if err := f.ClientSet.Core().Services(ns.Name).Delete(service.Name, nil); err != nil {
|
||||
framework.Failf("unable to cleanup svc %v: %v", service.Name, err)
|
||||
}
|
||||
}()
|
||||
framework.Logf("Waiting for Server to come up.")
|
||||
err := framework.WaitForPodRunningInNamespace(f.ClientSet, serverPod)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
By("Testing pods can connect to both ports when isolation is off.")
|
||||
testCanConnect(f, ns, "basecase-reachable-80", service, 80)
|
||||
testCanConnect(f, ns, "basecase-reachable-81", service, 81)
|
||||
|
||||
setNamespaceIsolation(f, ns, "DefaultDeny")
|
||||
|
||||
By("Testing pods cannot by default when isolation is turned on.")
|
||||
testCannotConnect(f, ns, "basecase-unreachable-80", service, 80)
|
||||
testCannotConnect(f, ns, "basecase-unreachable-81", service, 81)
|
||||
|
||||
By("Creating a network policy for the Service which allows traffic only to one port.")
|
||||
policy := v1beta1.NetworkPolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "allow-ingress-on-port-81",
|
||||
},
|
||||
Spec: v1beta1.NetworkPolicySpec{
|
||||
// Apply to server
|
||||
PodSelector: metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"pod-name": serverPod.Name,
|
||||
},
|
||||
},
|
||||
// Allow traffic only to one port.
|
||||
Ingress: []v1beta1.NetworkPolicyIngressRule{{
|
||||
Ports: []v1beta1.NetworkPolicyPort{{
|
||||
Port: &intstr.IntOrString{IntVal: 81},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
}
|
||||
result := v1beta1.NetworkPolicy{}
|
||||
err = f.ClientSet.Extensions().RESTClient().Post().Namespace(ns.Name).
|
||||
Resource("networkpolicies").Body(&policy).Do().Into(&result)
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer func() {
|
||||
By("Cleaning up the policy.")
|
||||
if err = f.ClientSet.Extensions().RESTClient().
|
||||
Delete().
|
||||
Namespace(ns.Name).
|
||||
Resource("networkpolicies").
|
||||
Name(policy.Name).
|
||||
Do().Error(); err != nil {
|
||||
framework.Failf("unable to cleanup policy %v: %v", policy.Name, err)
|
||||
}
|
||||
}()
|
||||
|
||||
testCannotConnect(f, ns, "client-a", service, 80)
|
||||
testCanConnect(f, ns, "client-b", service, 81)
|
||||
})
|
||||
|
||||
It("shouldn't enforce policy when isolation is off [Feature:NetworkPolicy]", func() {
|
||||
ns := f.Namespace
|
||||
|
||||
// Create Server with Service
|
||||
By("Creating a simple server.")
|
||||
serverPod, service := createServerPodAndService(f, ns, "server", []int{80, 81})
|
||||
defer func() {
|
||||
By("Cleaning up the server.")
|
||||
if err := f.ClientSet.Core().Pods(ns.Name).Delete(serverPod.Name, nil); err != nil {
|
||||
framework.Failf("unable to cleanup pod %v: %v", serverPod.Name, err)
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
By("Cleaning up the server's service.")
|
||||
if err := f.ClientSet.Core().Services(ns.Name).Delete(service.Name, nil); err != nil {
|
||||
framework.Failf("unable to cleanup svc %v: %v", service.Name, err)
|
||||
}
|
||||
}()
|
||||
framework.Logf("Waiting for Server to come up.")
|
||||
err := framework.WaitForPodRunningInNamespace(f.ClientSet, serverPod)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
By("Testing pods can connect to both ports when isolation is off and no policy is defined.")
|
||||
testCanConnect(f, ns, "basecase-reachable-a", service, 80)
|
||||
testCanConnect(f, ns, "basecase-reachable-b", service, 81)
|
||||
|
||||
By("Creating a network policy for the Service which allows traffic only to one port.")
|
||||
policy := v1beta1.NetworkPolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "allow-ingress-on-port-81",
|
||||
},
|
||||
Spec: v1beta1.NetworkPolicySpec{
|
||||
// Apply to server
|
||||
PodSelector: metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"pod-name": serverPod.Name,
|
||||
},
|
||||
},
|
||||
// Allow traffic only to one port.
|
||||
Ingress: []v1beta1.NetworkPolicyIngressRule{{
|
||||
Ports: []v1beta1.NetworkPolicyPort{{
|
||||
Port: &intstr.IntOrString{IntVal: 81},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
}
|
||||
result := v1beta1.NetworkPolicy{}
|
||||
err = f.ClientSet.Extensions().RESTClient().Post().Namespace(ns.Name).
|
||||
Resource("networkpolicies").Body(&policy).Do().Into(&result)
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer func() {
|
||||
By("Cleaning up the policy.")
|
||||
if err = f.ClientSet.Extensions().RESTClient().
|
||||
Delete().
|
||||
Namespace(ns.Name).
|
||||
Resource("networkpolicies").
|
||||
Name(policy.Name).
|
||||
Do().Error(); err != nil {
|
||||
framework.Failf("unable to cleanup policy %v: %v", policy.Name, err)
|
||||
}
|
||||
}()
|
||||
|
||||
testCanConnect(f, ns, "client-a", service, 80)
|
||||
testCanConnect(f, ns, "client-b", service, 81)
|
||||
})
|
||||
|
||||
It("should enforce multiple, stacked policies with overlapping podSelectors [Feature:NetworkPolicy]", func() {
|
||||
ns := f.Namespace
|
||||
|
||||
// Create Server with Service
|
||||
By("Creating a simple server.")
|
||||
serverPod, service := createServerPodAndService(f, ns, "server", []int{80, 81})
|
||||
defer func() {
|
||||
By("Cleaning up the server.")
|
||||
if err := f.ClientSet.Core().Pods(ns.Name).Delete(serverPod.Name, nil); err != nil {
|
||||
framework.Failf("unable to cleanup pod %v: %v", serverPod.Name, err)
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
By("Cleaning up the server's service.")
|
||||
if err := f.ClientSet.Core().Services(ns.Name).Delete(service.Name, nil); err != nil {
|
||||
framework.Failf("unable to cleanup svc %v: %v", service.Name, err)
|
||||
}
|
||||
}()
|
||||
framework.Logf("Waiting for Server to come up.")
|
||||
err := framework.WaitForPodRunningInNamespace(f.ClientSet, serverPod)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
By("Testing pods can connect to both ports when isolation is off.")
|
||||
testCanConnect(f, ns, "test-a", service, 80)
|
||||
testCanConnect(f, ns, "test-b", service, 81)
|
||||
|
||||
setNamespaceIsolation(f, ns, "DefaultDeny")
|
||||
|
||||
By("Testing pods cannot connect to either port when no policy is defined.")
|
||||
testCannotConnect(f, ns, "test-a-2", service, 80)
|
||||
testCannotConnect(f, ns, "test-b-2", service, 81)
|
||||
|
||||
By("Creating a network policy for the Service which allows traffic only to one port.")
|
||||
policy := v1beta1.NetworkPolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "allow-ingress-on-port-80",
|
||||
},
|
||||
Spec: v1beta1.NetworkPolicySpec{
|
||||
// Apply to server
|
||||
PodSelector: metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"pod-name": serverPod.Name,
|
||||
},
|
||||
},
|
||||
// Allow traffic only to one port.
|
||||
Ingress: []v1beta1.NetworkPolicyIngressRule{{
|
||||
Ports: []v1beta1.NetworkPolicyPort{{
|
||||
Port: &intstr.IntOrString{IntVal: 80},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
}
|
||||
result := v1beta1.NetworkPolicy{}
|
||||
err = f.ClientSet.Extensions().RESTClient().Post().Namespace(ns.Name).
|
||||
Resource("networkpolicies").Body(&policy).Do().Into(&result)
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer func() {
|
||||
By("Cleaning up the policy.")
|
||||
if err = f.ClientSet.Extensions().RESTClient().
|
||||
Delete().
|
||||
Namespace(ns.Name).
|
||||
Resource("networkpolicies").
|
||||
Name(policy.Name).
|
||||
Do().Error(); err != nil {
|
||||
framework.Failf("unable to cleanup policy %v: %v", policy.Name, err)
|
||||
}
|
||||
}()
|
||||
|
||||
By("Creating a network policy for the Service which allows traffic only to another port.")
|
||||
policy2 := v1beta1.NetworkPolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "allow-ingress-on-port-81",
|
||||
},
|
||||
Spec: v1beta1.NetworkPolicySpec{
|
||||
// Apply to server
|
||||
PodSelector: metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"pod-name": serverPod.Name,
|
||||
},
|
||||
},
|
||||
// Allow traffic only to one port.
|
||||
Ingress: []v1beta1.NetworkPolicyIngressRule{{
|
||||
Ports: []v1beta1.NetworkPolicyPort{{
|
||||
Port: &intstr.IntOrString{IntVal: 81},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
}
|
||||
result = v1beta1.NetworkPolicy{}
|
||||
err = f.ClientSet.Extensions().RESTClient().Post().Namespace(ns.Name).
|
||||
Resource("networkpolicies").Body(&policy2).Do().Into(&result)
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer func() {
|
||||
By("Cleaning up the policy.")
|
||||
if err = f.ClientSet.Extensions().RESTClient().
|
||||
Delete().
|
||||
Namespace(ns.Name).
|
||||
Resource("networkpolicies").
|
||||
Name(policy2.Name).
|
||||
Do().Error(); err != nil {
|
||||
framework.Failf("unable to cleanup policy %v: %v", policy2.Name, err)
|
||||
}
|
||||
}()
|
||||
|
||||
testCanConnect(f, ns, "client-a", service, 80)
|
||||
testCanConnect(f, ns, "client-b", service, 81)
|
||||
})
|
||||
|
||||
It("should support allow-all policy [Feature:NetworkPolicy]", func() {
|
||||
ns := f.Namespace
|
||||
|
||||
// Create Server with Service
|
||||
By("Creating a simple server.")
|
||||
serverPod, service := createServerPodAndService(f, ns, "server", []int{80, 81})
|
||||
defer func() {
|
||||
By("Cleaning up the server.")
|
||||
if err := f.ClientSet.Core().Pods(ns.Name).Delete(serverPod.Name, nil); err != nil {
|
||||
framework.Failf("unable to cleanup pod %v: %v", serverPod.Name, err)
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
By("Cleaning up the server's service.")
|
||||
if err := f.ClientSet.Core().Services(ns.Name).Delete(service.Name, nil); err != nil {
|
||||
framework.Failf("unable to cleanup svc %v: %v", service.Name, err)
|
||||
}
|
||||
}()
|
||||
framework.Logf("Waiting for Server to come up.")
|
||||
err := framework.WaitForPodRunningInNamespace(f.ClientSet, serverPod)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
By("Testing pods can connect to both ports when isolation is off.")
|
||||
testCanConnect(f, ns, "test-a", service, 80)
|
||||
testCanConnect(f, ns, "test-b", service, 81)
|
||||
|
||||
setNamespaceIsolation(f, ns, "DefaultDeny")
|
||||
|
||||
By("Testing pods cannot connect to either port when isolation is on.")
|
||||
testCannotConnect(f, ns, "test-a", service, 80)
|
||||
testCannotConnect(f, ns, "test-b", service, 81)
|
||||
|
||||
By("Creating a network policy which allows all traffic.")
|
||||
policy := v1beta1.NetworkPolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "allow-all",
|
||||
},
|
||||
Spec: v1beta1.NetworkPolicySpec{
|
||||
// Allow all traffic
|
||||
PodSelector: metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{},
|
||||
},
|
||||
Ingress: []v1beta1.NetworkPolicyIngressRule{{}},
|
||||
},
|
||||
}
|
||||
result := v1beta1.NetworkPolicy{}
|
||||
err = f.ClientSet.Extensions().RESTClient().Post().Namespace(ns.Name).
|
||||
Resource("networkpolicies").Body(&policy).Do().Into(&result)
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer func() {
|
||||
By("Cleaning up the policy.")
|
||||
if err = f.ClientSet.Extensions().RESTClient().
|
||||
Delete().
|
||||
Namespace(ns.Name).
|
||||
Resource("networkpolicies").
|
||||
Name(policy.Name).
|
||||
Do().Error(); err != nil {
|
||||
framework.Failf("unable to cleanup policy %v: %v", policy.Name, err)
|
||||
}
|
||||
}()
|
||||
|
||||
testCanConnect(f, ns, "client-a", service, 80)
|
||||
testCanConnect(f, ns, "client-b", service, 81)
|
||||
})
|
||||
|
||||
It("should enforce policy based on NamespaceSelector [Feature:NetworkPolicy]", func() {
|
||||
nsA := f.Namespace
|
||||
nsBName := f.BaseName + "-b"
|
||||
// The CreateNamespace helper uses the input name as a Name Generator, so the namespace itself
|
||||
// will have a different name than what we are setting as the value of ns-name.
|
||||
// This is fine as long as we don't try to match the label as nsB.Name in our policy.
|
||||
nsB, err := f.CreateNamespace(nsBName, map[string]string{
|
||||
"ns-name": nsBName,
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
setNamespaceIsolation(f, nsA, "DefaultDeny")
|
||||
|
||||
// Create Server with Service in NS-B
|
||||
By("Creating a webserver tied to a service.")
|
||||
serverPod, service := createServerPodAndService(f, nsA, "server", []int{80})
|
||||
defer func() {
|
||||
By("Cleaning up the server.")
|
||||
if err := f.ClientSet.Core().Pods(nsA.Name).Delete(serverPod.Name, nil); err != nil {
|
||||
framework.Failf("unable to cleanup pod %v: %v", serverPod.Name, err)
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
By("Cleaning up the server's service.")
|
||||
if err := f.ClientSet.Core().Services(nsA.Name).Delete(service.Name, nil); err != nil {
|
||||
framework.Failf("unable to cleanup svc %v: %v", service.Name, err)
|
||||
}
|
||||
}()
|
||||
framework.Logf("Waiting for server to come up.")
|
||||
err = framework.WaitForPodRunningInNamespace(f.ClientSet, serverPod)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Create Policy for that service that allows traffic only via namespace B
|
||||
By("Creating a network policy for the server which allows traffic from namespace-b.")
|
||||
policy := v1beta1.NetworkPolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "allow-ns-b-via-namespace-selector",
|
||||
},
|
||||
Spec: v1beta1.NetworkPolicySpec{
|
||||
// Apply to server
|
||||
PodSelector: metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"pod-name": serverPod.Name,
|
||||
},
|
||||
},
|
||||
// Allow traffic only from NS-B
|
||||
Ingress: []v1beta1.NetworkPolicyIngressRule{{
|
||||
From: []v1beta1.NetworkPolicyPeer{{
|
||||
NamespaceSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"ns-name": nsBName,
|
||||
},
|
||||
},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
}
|
||||
result := v1beta1.NetworkPolicy{}
|
||||
err = f.ClientSet.Extensions().RESTClient().Post().Namespace(nsA.Name).
|
||||
Resource("networkpolicies").Body(&policy).Do().Into(&result)
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer func() {
|
||||
By("Cleaning up the policy.")
|
||||
if err = f.ClientSet.Extensions().RESTClient().
|
||||
Delete().
|
||||
Namespace(nsA.Name).
|
||||
Resource("networkpolicies").
|
||||
Name(policy.Name).
|
||||
Do().Error(); err != nil {
|
||||
framework.Failf("unable to cleanup policy %v: %v", policy.Name, err)
|
||||
}
|
||||
}()
|
||||
|
||||
testCannotConnect(f, nsA, "client-a", service, 80)
|
||||
testCanConnect(f, nsB, "client-b", service, 80)
|
||||
})
|
||||
})
|
||||
|
||||
func testCanConnect(f *framework.Framework, ns *v1.Namespace, podName string, service *v1.Service, targetPort int) {
|
||||
By(fmt.Sprintf("Creating client pod %s that should successfully connect to %s.", podName, service.Name))
|
||||
podClient := createNetworkClientPod(f, ns, podName, service, targetPort)
|
||||
defer func() {
|
||||
By(fmt.Sprintf("Cleaning up the pod %s", podName))
|
||||
if err := f.ClientSet.Core().Pods(ns.Name).Delete(podClient.Name, nil); err != nil {
|
||||
framework.Failf("unable to cleanup pod %v: %v", podClient.Name, err)
|
||||
}
|
||||
}()
|
||||
|
||||
framework.Logf("Waiting for %s to complete.", podClient.Name)
|
||||
err := framework.WaitForPodNoLongerRunningInNamespace(f.ClientSet, podClient.Name, ns.Name)
|
||||
Expect(err).NotTo(HaveOccurred(), "Pod did not finish as expected.")
|
||||
|
||||
framework.Logf("Waiting for %s to complete.", podClient.Name)
|
||||
err = framework.WaitForPodSuccessInNamespace(f.ClientSet, podClient.Name, ns.Name)
|
||||
Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("checking %s could communicate with server.", podClient.Name))
|
||||
}
|
||||
|
||||
func testCannotConnect(f *framework.Framework, ns *v1.Namespace, podName string, service *v1.Service, targetPort int) {
|
||||
By(fmt.Sprintf("Creating client pod %s that should not be able to connect to %s.", podName, service.Name))
|
||||
podClient := createNetworkClientPod(f, ns, podName, service, targetPort)
|
||||
defer func() {
|
||||
By(fmt.Sprintf("Cleaning up the pod %s", podName))
|
||||
if err := f.ClientSet.Core().Pods(ns.Name).Delete(podClient.Name, nil); err != nil {
|
||||
framework.Failf("unable to cleanup pod %v: %v", podClient.Name, err)
|
||||
}
|
||||
}()
|
||||
|
||||
framework.Logf("Waiting for %s to complete.", podClient.Name)
|
||||
err := framework.WaitForPodSuccessInNamespace(f.ClientSet, podClient.Name, ns.Name)
|
||||
Expect(err).To(HaveOccurred(), fmt.Sprintf("checking %s could not communicate with server.", podName))
|
||||
}
|
||||
|
||||
// Create a server pod with a listening container for each port in ports[].
|
||||
// Will also assign a pod label with key: "pod-name" and label set to the given podname for later use by the network
|
||||
// policy.
|
||||
func createServerPodAndService(f *framework.Framework, namespace *v1.Namespace, podName string, ports []int) (*v1.Pod, *v1.Service) {
|
||||
// Because we have a variable amount of ports, we'll first loop through and generate our Containers for our pod,
|
||||
// and ServicePorts.for our Service.
|
||||
containers := []v1.Container{}
|
||||
servicePorts := []v1.ServicePort{}
|
||||
for _, port := range ports {
|
||||
// Build the containers for the server pod.
|
||||
containers = append(containers, v1.Container{
|
||||
Name: fmt.Sprintf("%s-container-%d", podName, port),
|
||||
Image: "gcr.io/google_containers/redis:e2e",
|
||||
Args: []string{
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
fmt.Sprintf("/bin/nc -kl %d", port),
|
||||
},
|
||||
Ports: []v1.ContainerPort{{ContainerPort: int32(port)}},
|
||||
})
|
||||
|
||||
// Build the Service Ports for the service.
|
||||
servicePorts = append(servicePorts, v1.ServicePort{
|
||||
Name: fmt.Sprintf("%s-%d", podName, port),
|
||||
Port: int32(port),
|
||||
TargetPort: intstr.FromInt(port),
|
||||
})
|
||||
}
|
||||
|
||||
By(fmt.Sprintf("Creating a server pod %s in namespace %s", podName, namespace.Name))
|
||||
pod, err := f.ClientSet.Core().Pods(namespace.Name).Create(&v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: podName,
|
||||
Labels: map[string]string{
|
||||
"pod-name": podName,
|
||||
},
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
Containers: containers,
|
||||
RestartPolicy: v1.RestartPolicyNever,
|
||||
},
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
framework.Logf("Created pod %v", pod.ObjectMeta.Name)
|
||||
|
||||
svcName := fmt.Sprintf("svc-%s", podName)
|
||||
By(fmt.Sprintf("Creating a service %s for pod %s in namespace %s", svcName, podName, namespace.Name))
|
||||
svc, err := f.ClientSet.Core().Services(namespace.Name).Create(&v1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: svcName,
|
||||
},
|
||||
Spec: v1.ServiceSpec{
|
||||
Ports: servicePorts,
|
||||
Selector: map[string]string{
|
||||
"pod-name": podName,
|
||||
},
|
||||
},
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
framework.Logf("Created service %s", svc.Name)
|
||||
|
||||
return pod, svc
|
||||
}
|
||||
|
||||
// Create a client pod which will attempt a netcat to the provided service, on the specified port.
|
||||
// This client will attempt a oneshot connection, then die, without restarting the pod.
|
||||
// Test can then be asserted based on whether the pod quit with an error or not.
|
||||
func createNetworkClientPod(f *framework.Framework, namespace *v1.Namespace, podName string, targetService *v1.Service, targetPort int) *v1.Pod {
|
||||
pod, err := f.ClientSet.Core().Pods(namespace.Name).Create(&v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: podName,
|
||||
Labels: map[string]string{
|
||||
"pod-name": podName,
|
||||
},
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
RestartPolicy: v1.RestartPolicyNever,
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: fmt.Sprintf("%s-container", podName),
|
||||
Image: "gcr.io/google_containers/redis:e2e",
|
||||
Args: []string{
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
fmt.Sprintf("/usr/bin/printf dummy-data | /bin/nc -w 8 %s.%s %d", targetService.Name, targetService.Namespace, targetPort),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return pod
|
||||
}
|
||||
|
||||
// Configure namespace network isolation by setting the network-policy annotation
|
||||
// on the namespace.
|
||||
func setNamespaceIsolation(f *framework.Framework, namespace *v1.Namespace, ingressIsolation string) {
|
||||
var annotations = map[string]string{}
|
||||
if ingressIsolation != "" {
|
||||
By(fmt.Sprintf("Enabling isolation through namespace annotations on namespace %v", namespace.Name))
|
||||
policy := fmt.Sprintf(`{"ingress":{"isolation":"%s"}}`, ingressIsolation)
|
||||
annotations["net.beta.kubernetes.io/network-policy"] = policy
|
||||
} else {
|
||||
By(fmt.Sprintf("Disabling isolation through namespace annotations on namespace %v", namespace.Name))
|
||||
delete(annotations, "net.beta.kubernetes.io/network-policy")
|
||||
}
|
||||
|
||||
// Update the namespace. We set the resource version to be an empty
|
||||
// string, this forces the update. If we weren't to do this, we would
|
||||
// either need to re-query the namespace, or update the namespace
|
||||
// references with the one returned by the update. This approach
|
||||
// requires less plumbing.
|
||||
namespace.ObjectMeta.Annotations = annotations
|
||||
namespace.ObjectMeta.ResourceVersion = ""
|
||||
_, err := f.ClientSet.Core().Namespaces().Update(namespace)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
1036
test/test_owners.csv
1036
test/test_owners.csv
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue