mirror of
https://github.com/optim-enterprises-bv/kubernetes.git
synced 2025-11-03 11:48:15 +00:00
Add IPBlock to NetworkPolicy
Signed-off-by: Christopher M. Luciano <cmluciano@us.ibm.com>
This commit is contained in:
@@ -60,6 +60,8 @@ func addConversionFuncs(scheme *runtime.Scheme) error {
|
|||||||
Convert_v1beta1_NetworkPolicySpec_To_networking_NetworkPolicySpec,
|
Convert_v1beta1_NetworkPolicySpec_To_networking_NetworkPolicySpec,
|
||||||
Convert_networking_NetworkPolicySpec_To_v1beta1_NetworkPolicySpec,
|
Convert_networking_NetworkPolicySpec_To_v1beta1_NetworkPolicySpec,
|
||||||
Convert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec,
|
Convert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec,
|
||||||
|
Convert_v1beta1_IPBlock_To_networking_IPBlock,
|
||||||
|
Convert_networking_IPBlock_To_v1beta1_IPBlock,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -364,6 +366,14 @@ func Convert_v1beta1_NetworkPolicyPeer_To_networking_NetworkPolicyPeer(in *exten
|
|||||||
} else {
|
} else {
|
||||||
out.NamespaceSelector = nil
|
out.NamespaceSelector = nil
|
||||||
}
|
}
|
||||||
|
if in.IPBlock != nil {
|
||||||
|
out.IPBlock = new(networking.IPBlock)
|
||||||
|
if err := s.Convert(in.IPBlock, out.IPBlock, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.IPBlock = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,6 +394,30 @@ func Convert_networking_NetworkPolicyPeer_To_v1beta1_NetworkPolicyPeer(in *netwo
|
|||||||
} else {
|
} else {
|
||||||
out.NamespaceSelector = nil
|
out.NamespaceSelector = nil
|
||||||
}
|
}
|
||||||
|
if in.IPBlock != nil {
|
||||||
|
out.IPBlock = new(extensionsv1beta1.IPBlock)
|
||||||
|
if err := s.Convert(in.IPBlock, out.IPBlock, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.IPBlock = nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Convert_v1beta1_IPBlock_To_networking_IPBlock(in *extensionsv1beta1.IPBlock, out *networking.IPBlock, s conversion.Scope) error {
|
||||||
|
out.CIDR = in.CIDR
|
||||||
|
|
||||||
|
out.Except = make([]string, len(in.Except))
|
||||||
|
copy(out.Except, in.Except)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Convert_networking_IPBlock_To_v1beta1_IPBlock(in *networking.IPBlock, out *extensionsv1beta1.IPBlock, s conversion.Scope) error {
|
||||||
|
out.CIDR = in.CIDR
|
||||||
|
|
||||||
|
out.Except = make([]string, len(in.Except))
|
||||||
|
copy(out.Except, in.Except)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,6 +90,20 @@ type NetworkPolicyPort struct {
|
|||||||
Port *intstr.IntOrString
|
Port *intstr.IntOrString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IPBlock describes a particular CIDR (Ex. "192.168.1.1/24") that is allowed to the pods
|
||||||
|
// matched by a NetworkPolicySpec's podSelector. The except entry describes CIDRs that should
|
||||||
|
// not be included within this rule.
|
||||||
|
type IPBlock struct {
|
||||||
|
// CIDR is a string representing the IP Block
|
||||||
|
// Valid examples are "192.168.1.1/24"
|
||||||
|
CIDR string
|
||||||
|
// Except is a slice of CIDRs that should not be included within an IP Block
|
||||||
|
// Valid examples are "192.168.1.1/24"
|
||||||
|
// Except values will be rejected if they are outside the CIDR range
|
||||||
|
// +optional
|
||||||
|
Except []string
|
||||||
|
}
|
||||||
|
|
||||||
// NetworkPolicyPeer describes a peer to allow traffic from. Exactly one of its fields
|
// NetworkPolicyPeer describes a peer to allow traffic from. Exactly one of its fields
|
||||||
// must be specified.
|
// must be specified.
|
||||||
type NetworkPolicyPeer struct {
|
type NetworkPolicyPeer struct {
|
||||||
@@ -104,6 +118,10 @@ type NetworkPolicyPeer struct {
|
|||||||
// selector semantics. If present but empty, this selector selects all namespaces.
|
// selector semantics. If present but empty, this selector selects all namespaces.
|
||||||
// +optional
|
// +optional
|
||||||
NamespaceSelector *metav1.LabelSelector
|
NamespaceSelector *metav1.LabelSelector
|
||||||
|
|
||||||
|
// IPBlock defines policy on a particular IPBlock
|
||||||
|
// +optional
|
||||||
|
IPBlock *IPBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ limitations under the License.
|
|||||||
package validation
|
package validation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
unversionedvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
|
unversionedvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
"k8s.io/apimachinery/pkg/util/validation"
|
"k8s.io/apimachinery/pkg/util/validation"
|
||||||
@@ -68,7 +70,10 @@ func ValidateNetworkPolicySpec(spec *networking.NetworkPolicySpec, fldPath *fiel
|
|||||||
numFroms++
|
numFroms++
|
||||||
allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(from.NamespaceSelector, fromPath.Child("namespaceSelector"))...)
|
allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(from.NamespaceSelector, fromPath.Child("namespaceSelector"))...)
|
||||||
}
|
}
|
||||||
|
if from.IPBlock != nil {
|
||||||
|
numFroms++
|
||||||
|
allErrs = append(allErrs, ValidateIPBlock(from.IPBlock, fromPath.Child("ipBlock"))...)
|
||||||
|
}
|
||||||
if numFroms == 0 {
|
if numFroms == 0 {
|
||||||
allErrs = append(allErrs, field.Required(fromPath, "must specify a from type"))
|
allErrs = append(allErrs, field.Required(fromPath, "must specify a from type"))
|
||||||
} else if numFroms > 1 {
|
} else if numFroms > 1 {
|
||||||
@@ -93,3 +98,39 @@ func ValidateNetworkPolicyUpdate(update, old *networking.NetworkPolicy) field.Er
|
|||||||
allErrs = append(allErrs, ValidateNetworkPolicySpec(&update.Spec, field.NewPath("spec"))...)
|
allErrs = append(allErrs, ValidateNetworkPolicySpec(&update.Spec, field.NewPath("spec"))...)
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateIPBlock validates a cidr and the except fields of an IpBlock NetworkPolicyPeer
|
||||||
|
func ValidateIPBlock(ipb *networking.IPBlock, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
if len(ipb.CIDR) == 0 || ipb.CIDR == "" {
|
||||||
|
allErrs = append(allErrs, field.Required(fldPath.Child("cidr"), ""))
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
cidrIPNet, err := validateCIDR(ipb.CIDR)
|
||||||
|
if err != nil {
|
||||||
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("cidr"), ipb.CIDR, "not a valid CIDR"))
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
exceptCIDR := ipb.Except
|
||||||
|
for i, exceptIP := range exceptCIDR {
|
||||||
|
exceptPath := fldPath.Child("except").Index(i)
|
||||||
|
exceptCIDR, err := validateCIDR(exceptIP)
|
||||||
|
if err != nil {
|
||||||
|
allErrs = append(allErrs, field.Invalid(exceptPath, exceptIP, "not a valid CIDR"))
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
if !cidrIPNet.Contains(exceptCIDR.IP) {
|
||||||
|
allErrs = append(allErrs, field.Invalid(exceptPath, exceptCIDR.IP, "not within CIDR range"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
// validateCIDR validates whether a CIDR matches the conventions expected by net.ParseCIDR
|
||||||
|
func validateCIDR(cidr string) (*net.IPNet, error) {
|
||||||
|
_, net, err := net.ParseCIDR(cidr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return net, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -122,6 +122,26 @@ func TestValidateNetworkPolicy(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"},
|
||||||
|
Spec: networking.NetworkPolicySpec{
|
||||||
|
PodSelector: metav1.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{"a": "b"},
|
||||||
|
},
|
||||||
|
Ingress: []networking.NetworkPolicyIngressRule{
|
||||||
|
{
|
||||||
|
From: []networking.NetworkPolicyPeer{
|
||||||
|
{
|
||||||
|
IPBlock: &networking.IPBlock{
|
||||||
|
CIDR: "192.168.0.0/16",
|
||||||
|
Except: []string{"192.168.3.0/24", "192.168.4.0/24"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Success cases are expected to pass validation.
|
// Success cases are expected to pass validation.
|
||||||
@@ -256,6 +276,83 @@ func TestValidateNetworkPolicy(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"missing cidr field": {
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"},
|
||||||
|
Spec: networking.NetworkPolicySpec{
|
||||||
|
PodSelector: metav1.LabelSelector{},
|
||||||
|
Ingress: []networking.NetworkPolicyIngressRule{
|
||||||
|
{
|
||||||
|
From: []networking.NetworkPolicyPeer{
|
||||||
|
{
|
||||||
|
IPBlock: &networking.IPBlock{
|
||||||
|
Except: []string{"192.168.8.0/24", "192.168.9.0/24"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"invalid cidr format": {
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"},
|
||||||
|
Spec: networking.NetworkPolicySpec{
|
||||||
|
PodSelector: metav1.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{"a": "b"},
|
||||||
|
},
|
||||||
|
Ingress: []networking.NetworkPolicyIngressRule{
|
||||||
|
{
|
||||||
|
From: []networking.NetworkPolicyPeer{
|
||||||
|
{
|
||||||
|
IPBlock: &networking.IPBlock{
|
||||||
|
CIDR: "192.168.5.6",
|
||||||
|
Except: []string{"192.168.1.0/24", "192.168.2.0/24"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"except field is an empty string": {
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"},
|
||||||
|
Spec: networking.NetworkPolicySpec{
|
||||||
|
PodSelector: metav1.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{"a": "b"},
|
||||||
|
},
|
||||||
|
Ingress: []networking.NetworkPolicyIngressRule{
|
||||||
|
{
|
||||||
|
From: []networking.NetworkPolicyPeer{
|
||||||
|
{
|
||||||
|
IPBlock: &networking.IPBlock{
|
||||||
|
CIDR: "192.168.8.0/24",
|
||||||
|
Except: []string{"", " "},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"except IP is outside of CIDR range": {
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"},
|
||||||
|
Spec: networking.NetworkPolicySpec{
|
||||||
|
PodSelector: metav1.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{"a": "b"},
|
||||||
|
},
|
||||||
|
Ingress: []networking.NetworkPolicyIngressRule{
|
||||||
|
{
|
||||||
|
From: []networking.NetworkPolicyPeer{
|
||||||
|
{
|
||||||
|
IPBlock: &networking.IPBlock{
|
||||||
|
CIDR: "192.168.8.0/24",
|
||||||
|
Except: []string{"192.168.9.1/24"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error cases are not expected to pass validation.
|
// Error cases are not expected to pass validation.
|
||||||
|
|||||||
@@ -1181,6 +1181,20 @@ type NetworkPolicyPort struct {
|
|||||||
Port *intstr.IntOrString `json:"port,omitempty" protobuf:"bytes,2,opt,name=port"`
|
Port *intstr.IntOrString `json:"port,omitempty" protobuf:"bytes,2,opt,name=port"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IPBlock describes a particular CIDR (Ex. "192.168.1.1/24") that is allowed to the pods
|
||||||
|
// matched by a NetworkPolicySpec's podSelector. The except entry describes CIDRs that should
|
||||||
|
// not be included within this rule.
|
||||||
|
type IPBlock struct {
|
||||||
|
// CIDR is a string representing the IP Block
|
||||||
|
// Valid examples are "192.168.1.1/24"
|
||||||
|
CIDR string `json:"cidr" protobuf:"bytes,1,name=cidr"`
|
||||||
|
// Except is a slice of CIDRs that should not be included within an IP Block
|
||||||
|
// Valid examples are "192.168.1.1/24"
|
||||||
|
// Except values will be rejected if they are outside the CIDR range
|
||||||
|
// +optional
|
||||||
|
Except []string `json:"except,omitempty" protobuf:"bytes,2,rep,name=except"`
|
||||||
|
}
|
||||||
|
|
||||||
type NetworkPolicyPeer struct {
|
type NetworkPolicyPeer struct {
|
||||||
// Exactly one of the following must be specified.
|
// Exactly one of the following must be specified.
|
||||||
|
|
||||||
@@ -1196,6 +1210,10 @@ type NetworkPolicyPeer struct {
|
|||||||
// If present but empty, this selector selects all namespaces.
|
// If present but empty, this selector selects all namespaces.
|
||||||
// +optional
|
// +optional
|
||||||
NamespaceSelector *metav1.LabelSelector `json:"namespaceSelector,omitempty" protobuf:"bytes,2,opt,name=namespaceSelector"`
|
NamespaceSelector *metav1.LabelSelector `json:"namespaceSelector,omitempty" protobuf:"bytes,2,opt,name=namespaceSelector"`
|
||||||
|
|
||||||
|
// IPBlock defines policy on a particular IPBlock
|
||||||
|
// +optional
|
||||||
|
IPBlock *IPBlock `json:"ipBlock,omitempty" protobuf:"bytes,3,rep,name=ipBlock"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|||||||
@@ -92,6 +92,20 @@ type NetworkPolicyPort struct {
|
|||||||
Port *intstr.IntOrString `json:"port,omitempty" protobuf:"bytes,2,opt,name=port"`
|
Port *intstr.IntOrString `json:"port,omitempty" protobuf:"bytes,2,opt,name=port"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IPBlock describes a particular CIDR (Ex. "192.168.1.1/24") that is allowed to the pods
|
||||||
|
// matched by a NetworkPolicySpec's podSelector. The except entry describes CIDRs that should
|
||||||
|
// not be included within this rule.
|
||||||
|
type IPBlock struct {
|
||||||
|
// CIDR is a string representing the IP Block
|
||||||
|
// Valid examples are "192.168.1.1/24"
|
||||||
|
CIDR string `json:"cidr" protobuf:"bytes,1,name=cidr"`
|
||||||
|
// Except is a slice of CIDRs that should not be included within an IP Block
|
||||||
|
// Valid examples are "192.168.1.1/24"
|
||||||
|
// Except values will be rejected if they are outside the CIDR range
|
||||||
|
// +optional
|
||||||
|
Except []string `json:"except,omitempty" protobuf:"bytes,2,rep,name=except"`
|
||||||
|
}
|
||||||
|
|
||||||
// NetworkPolicyPeer describes a peer to allow traffic from. Exactly one of its fields
|
// NetworkPolicyPeer describes a peer to allow traffic from. Exactly one of its fields
|
||||||
// must be specified.
|
// must be specified.
|
||||||
type NetworkPolicyPeer struct {
|
type NetworkPolicyPeer struct {
|
||||||
@@ -106,6 +120,10 @@ type NetworkPolicyPeer struct {
|
|||||||
// selector semantics. If present but empty, this selector selects all namespaces.
|
// selector semantics. If present but empty, this selector selects all namespaces.
|
||||||
// +optional
|
// +optional
|
||||||
NamespaceSelector *metav1.LabelSelector `json:"namespaceSelector,omitempty" protobuf:"bytes,2,opt,name=namespaceSelector"`
|
NamespaceSelector *metav1.LabelSelector `json:"namespaceSelector,omitempty" protobuf:"bytes,2,opt,name=namespaceSelector"`
|
||||||
|
|
||||||
|
// IPBlock defines policy on a particular IPBlock
|
||||||
|
// +optional
|
||||||
|
IPBlock *IPBlock `json:"ipBlock,omitempty" protobuf:"bytes,3,rep,name=ipBlock"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|||||||
Reference in New Issue
Block a user