Files
kubernetes/test/e2e/network/netpol/policies.go

498 lines
14 KiB
Go

/*
Copyright 2020 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 netpol
import (
"fmt"
"k8s.io/apimachinery/pkg/util/intstr"
v1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// GetDenyIngress returns a default deny ingress policy.
func GetDenyIngress(name string) *networkingv1.NetworkPolicy {
return &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{},
PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress},
Ingress: []networkingv1.NetworkPolicyIngressRule{},
},
}
}
// GetDenyEgressForTarget returns a default deny egress policy.
func GetDenyEgressForTarget(name string, targetSelector metav1.LabelSelector) *networkingv1.NetworkPolicy {
return &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: targetSelector,
PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeEgress},
Egress: []networkingv1.NetworkPolicyEgressRule{},
},
}
}
// GetRandomIngressPolicies returns "num" random policies that allow a unique:n label, i.e.
// unique:1, unique:2, and so on. Used for creating a 'background' set of policies.
func GetRandomIngressPolicies(num int) []*networkingv1.NetworkPolicy {
policies := []*networkingv1.NetworkPolicy{}
for i := 0; i < num; i++ {
policy := &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("allow-all-%v", i),
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{
MatchLabels: map[string]string{
"unique": fmt.Sprintf("%v", i),
},
},
Ingress: []networkingv1.NetworkPolicyIngressRule{{}},
},
}
policies = append(policies, policy)
}
return policies
}
// GetAllowIngress allows all ingress
func GetAllowIngress(name string) *networkingv1.NetworkPolicy {
policy := &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{
MatchLabels: map[string]string{},
},
Ingress: []networkingv1.NetworkPolicyIngressRule{
{},
},
},
}
return policy
}
// GetAllowIngressByPort allows ingress by port
func GetAllowIngressByPort(name string, port *intstr.IntOrString) *networkingv1.NetworkPolicy {
policy := &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{
MatchLabels: map[string]string{},
},
Ingress: []networkingv1.NetworkPolicyIngressRule{
{
Ports: []networkingv1.NetworkPolicyPort{
{Port: port},
},
},
},
},
}
return policy
}
// GetAllowEgressByPort allows egress by port
func GetAllowEgressByPort(name string, port *intstr.IntOrString) *networkingv1.NetworkPolicy {
protocolUDP := v1.ProtocolUDP
policy := &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{
MatchLabels: map[string]string{},
},
Egress: []networkingv1.NetworkPolicyEgressRule{
{
Ports: []networkingv1.NetworkPolicyPort{
{Port: port},
{
Protocol: &protocolUDP,
Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 53},
},
},
},
},
PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeEgress},
},
}
return policy
}
// GetDenyAll denies ingress traffic, AS WELL as egress traffic.
// - BOTH policy types must be specified
// - The Egress rule must (like the ingress default rule) be a array with 0 values.
func GetDenyAll(name string) *networkingv1.NetworkPolicy {
policy := GetDenyIngress(name)
policy.Spec.PolicyTypes = []networkingv1.PolicyType{networkingv1.PolicyTypeEgress, networkingv1.PolicyTypeIngress}
policy.Spec.Egress = []networkingv1.NetworkPolicyEgressRule{}
policy.Spec.Ingress = []networkingv1.NetworkPolicyIngressRule{}
return policy
}
// GetDenyAllWithEgressDNS deny all egress traffic, besides DNS/UDP port
func GetDenyAllWithEgressDNS() *networkingv1.NetworkPolicy {
protocolUDP := v1.ProtocolUDP
return &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "deny-all-tcp-allow-dns",
},
Spec: networkingv1.NetworkPolicySpec{
PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeEgress, networkingv1.PolicyTypeIngress},
PodSelector: metav1.LabelSelector{},
Ingress: []networkingv1.NetworkPolicyIngressRule{},
Egress: []networkingv1.NetworkPolicyEgressRule{
{
Ports: []networkingv1.NetworkPolicyPort{
{
Protocol: &protocolUDP,
Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 53},
},
},
},
},
},
}
}
// GetAllowIngressByPod allows ingress by pod labels
func GetAllowIngressByPod(name string, targetLabels map[string]string, peerPodSelector *metav1.LabelSelector) *networkingv1.NetworkPolicy {
policy := &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{
MatchLabels: targetLabels,
},
Ingress: []networkingv1.NetworkPolicyIngressRule{{
From: []networkingv1.NetworkPolicyPeer{{
PodSelector: peerPodSelector,
}},
}},
},
}
return policy
}
// GetAllowIngressForTarget allows ingress for target
func GetAllowIngressForTarget(name string, targetLabels map[string]string) *networkingv1.NetworkPolicy {
return &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{
MatchLabels: targetLabels,
},
PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress},
Ingress: []networkingv1.NetworkPolicyIngressRule{
{
From: []networkingv1.NetworkPolicyPeer{
{
PodSelector: &metav1.LabelSelector{},
NamespaceSelector: &metav1.LabelSelector{},
},
},
},
},
},
}
}
// GetDenyIngressForTarget denies all ingress for target
func GetDenyIngressForTarget(targetSelector metav1.LabelSelector) *networkingv1.NetworkPolicy {
return &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "deny-ingress-via-label-selector",
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: targetSelector,
PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress},
Ingress: []networkingv1.NetworkPolicyIngressRule{},
},
}
}
// GetAllowIngressByNamespace allows ingress for namespace
func GetAllowIngressByNamespace(name string, targetLabels map[string]string, peerNamespaceSelector *metav1.LabelSelector) *networkingv1.NetworkPolicy {
policy := &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{
MatchLabels: targetLabels,
},
Ingress: []networkingv1.NetworkPolicyIngressRule{{
From: []networkingv1.NetworkPolicyPeer{{
NamespaceSelector: peerNamespaceSelector,
}},
}},
},
}
return policy
}
// GetAllowIngressByNamespaceAndPort allows ingress for namespace AND port AND protocol
func GetAllowIngressByNamespaceAndPort(name string, targetLabels map[string]string, peerNamespaceSelector *metav1.LabelSelector, port *intstr.IntOrString, protocol *v1.Protocol) *networkingv1.NetworkPolicy {
policy := &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{
MatchLabels: targetLabels,
},
Ingress: []networkingv1.NetworkPolicyIngressRule{{
From: []networkingv1.NetworkPolicyPeer{{
NamespaceSelector: peerNamespaceSelector,
}},
Ports: []networkingv1.NetworkPolicyPort{
{
Port: port,
Protocol: protocol,
},
},
}},
},
}
return policy
}
// GetAllowIngressByNamespaceOrPod allows ingress for pods with matching namespace OR pod labels
func GetAllowIngressByNamespaceOrPod(name string, targetLabels map[string]string, peerNamespaceSelector *metav1.LabelSelector, peerPodSelector *metav1.LabelSelector) *networkingv1.NetworkPolicy {
policy := &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{
MatchLabels: targetLabels,
},
Ingress: []networkingv1.NetworkPolicyIngressRule{{
From: []networkingv1.NetworkPolicyPeer{
{
NamespaceSelector: peerNamespaceSelector,
},
{
PodSelector: peerPodSelector,
},
},
}},
},
}
return policy
}
// GetAllowIngressByNamespaceAndPod allows ingress for pods with matching namespace AND pod labels
func GetAllowIngressByNamespaceAndPod(name string, targetLabels map[string]string, peerNamespaceSelector *metav1.LabelSelector, peerPodSelector *metav1.LabelSelector) *networkingv1.NetworkPolicy {
policy := &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{
MatchLabels: targetLabels,
},
Ingress: []networkingv1.NetworkPolicyIngressRule{{
From: []networkingv1.NetworkPolicyPeer{{
NamespaceSelector: peerNamespaceSelector,
PodSelector: peerPodSelector,
}},
}},
},
}
return policy
}
// GetAllowEgressByNamespaceAndPod allows egress for pods with matching namespace AND pod labels
func GetAllowEgressByNamespaceAndPod(name string, targetLabels map[string]string, peerNamespaceSelector *metav1.LabelSelector, peerPodSelector *metav1.LabelSelector) *networkingv1.NetworkPolicy {
protocolUDP := v1.ProtocolUDP
policy := &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{
MatchLabels: targetLabels,
},
PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeEgress},
Egress: []networkingv1.NetworkPolicyEgressRule{
{
To: []networkingv1.NetworkPolicyPeer{
{
NamespaceSelector: peerNamespaceSelector,
PodSelector: peerPodSelector,
},
},
},
{
Ports: []networkingv1.NetworkPolicyPort{
{
Protocol: &protocolUDP,
Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 53},
},
},
},
},
},
}
return policy
}
// GetAllowEgress allows all egress
func GetAllowEgress() *networkingv1.NetworkPolicy {
return &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "allow-egress",
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{
MatchLabels: map[string]string{},
},
PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeEgress},
Egress: []networkingv1.NetworkPolicyEgressRule{{}},
},
}
}
// GetAllowEgressForTarget allows all egress for a target
func GetAllowEgressForTarget(targetSelector metav1.LabelSelector) *networkingv1.NetworkPolicy {
return &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "allow-egress-for-target",
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: targetSelector,
PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeEgress},
Egress: []networkingv1.NetworkPolicyEgressRule{{}},
},
}
}
// GetAllowEgressByCIDR creates an egress netpol with an ipblock
func GetAllowEgressByCIDR(podname string, podserverCIDR string) *networkingv1.NetworkPolicy {
protocolUDP := v1.ProtocolUDP
return &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "allow-client-a-via-cidr-egress-rule",
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{
MatchLabels: map[string]string{
"pod": podname,
},
},
PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeEgress},
// Allow traffic to only one CIDR block.
Egress: []networkingv1.NetworkPolicyEgressRule{
{
To: []networkingv1.NetworkPolicyPeer{
{
IPBlock: &networkingv1.IPBlock{
CIDR: podserverCIDR,
},
},
},
},
{
Ports: []networkingv1.NetworkPolicyPort{
{
Protocol: &protocolUDP,
Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 53},
},
},
},
},
},
}
}
// GetAllowEgressByCIDRExcept creates an egress netpol with an ipblock and except
func GetAllowEgressByCIDRExcept(podname string, podserverCIDR string, except []string) *networkingv1.NetworkPolicy {
protocolUDP := v1.ProtocolUDP
return &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "allow-client-a-via-cidr-egress-rule",
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{
MatchLabels: map[string]string{
"pod": podname,
},
},
PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeEgress},
// Allow traffic to only one CIDR block.
Egress: []networkingv1.NetworkPolicyEgressRule{
{
To: []networkingv1.NetworkPolicyPeer{
{
IPBlock: &networkingv1.IPBlock{
CIDR: podserverCIDR,
Except: except,
},
},
},
},
{
Ports: []networkingv1.NetworkPolicyPort{
{
Protocol: &protocolUDP,
Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 53},
},
},
},
},
},
}
}
// GetAllowIngressOnProtocolByPort is a base network policy template which distinguishes between the types of v1.Protocol available in v1 core
func GetAllowIngressOnProtocolByPort(name string, protocol v1.Protocol, targetLabels map[string]string, portNum *intstr.IntOrString) *networkingv1.NetworkPolicy {
policy := &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{
MatchLabels: targetLabels,
},
Ingress: []networkingv1.NetworkPolicyIngressRule{{
Ports: []networkingv1.NetworkPolicyPort{{
Port: portNum,
Protocol: &protocol,
}},
}},
},
}
return policy
}