diff --git a/pkg/apis/networking/validation/validation_test.go b/pkg/apis/networking/validation/validation_test.go index 696fa403ab7..046a10ea3ba 100644 --- a/pkg/apis/networking/validation/validation_test.go +++ b/pkg/apis/networking/validation/validation_test.go @@ -36,1022 +36,348 @@ import ( utilpointer "k8s.io/utils/pointer" ) +func makeValidNetworkPolicy() *networking.NetworkPolicy { + return &networking.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, + Spec: networking.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{"a": "b"}, + }, + }, + } +} + +type netpolTweak func(networkPolicy *networking.NetworkPolicy) + +func makeNetworkPolicyCustom(tweaks ...netpolTweak) *networking.NetworkPolicy { + networkPolicy := makeValidNetworkPolicy() + for _, fn := range tweaks { + fn(networkPolicy) + } + return networkPolicy +} + +func makePort(proto *api.Protocol, port intstr.IntOrString, endPort int32) networking.NetworkPolicyPort { + r := networking.NetworkPolicyPort{ + Protocol: proto, + Port: nil, + } + if port != intstr.FromInt(0) && port != intstr.FromString("") && port != intstr.FromString("0") { + r.Port = &port + } + if endPort != 0 { + r.EndPort = utilpointer.Int32Ptr(endPort) + } + return r +} + func TestValidateNetworkPolicy(t *testing.T) { protocolTCP := api.ProtocolTCP protocolUDP := api.ProtocolUDP protocolICMP := api.Protocol("ICMP") protocolSCTP := api.ProtocolSCTP - endPort := int32(32768) - successCases := []networking.NetworkPolicy{ - { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - }, - Ingress: []networking.NetworkPolicyIngressRule{}, - }, - }, - { - 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{}, - Ports: []networking.NetworkPolicyPort{}, - }, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - }, - Ingress: []networking.NetworkPolicyIngressRule{ - { - Ports: []networking.NetworkPolicyPort{ - { - Protocol: nil, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 80}, - }, - { - Protocol: &protocolTCP, - Port: nil, - }, - { - Protocol: &protocolTCP, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 443}, - }, - { - Protocol: &protocolUDP, - Port: &intstr.IntOrString{Type: intstr.String, StrVal: "dns"}, - }, - { - Protocol: &protocolSCTP, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 7777}, - }, - }, - }, - }, - }, - }, - { - 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{ - { - PodSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"c": "d"}, - }, - }, - }, - }, - }, - }, - }, - { - 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{ - { - NamespaceSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"c": "d"}, - }, - }, - }, - }, - }, - }, - }, - { - 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{ - { - NamespaceSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"c": "d"}, - }, - PodSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"e": "f"}, - }, - }, - }, - }, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - }, - Egress: []networking.NetworkPolicyEgressRule{ - { - To: []networking.NetworkPolicyPeer{ - { - NamespaceSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"c": "d"}, - }, - }, - }, - }, - }, - 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"}, - }, - }, - }, - }, - }, - }, - }, - { - 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"}, - }, - }, - }, - }, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - }, - Egress: []networking.NetworkPolicyEgressRule{ - { - To: []networking.NetworkPolicyPeer{ - { - IPBlock: &networking.IPBlock{ - CIDR: "192.168.0.0/16", - Except: []string{"192.168.3.0/24", "192.168.4.0/24"}, - }, - }, - }, - }, - }, - PolicyTypes: []networking.PolicyType{networking.PolicyTypeEgress}, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - }, - Egress: []networking.NetworkPolicyEgressRule{ - { - To: []networking.NetworkPolicyPeer{ - { - IPBlock: &networking.IPBlock{ - CIDR: "192.168.0.0/16", - Except: []string{"192.168.3.0/24", "192.168.4.0/24"}, - }, - }, - }, - }, - }, - PolicyTypes: []networking.PolicyType{networking.PolicyTypeIngress, networking.PolicyTypeEgress}, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - }, - Egress: []networking.NetworkPolicyEgressRule{ - { - Ports: []networking.NetworkPolicyPort{ - { - Protocol: nil, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 80}, - }, - { - Protocol: &protocolTCP, - Port: nil, - }, - { - Protocol: &protocolTCP, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 443}, - }, - { - Protocol: &protocolUDP, - Port: &intstr.IntOrString{Type: intstr.String, StrVal: "dns"}, - }, - { - Protocol: &protocolSCTP, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 7777}, - }, - }, - }, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - }, - Egress: []networking.NetworkPolicyEgressRule{ - { - To: []networking.NetworkPolicyPeer{ - { - NamespaceSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"c": "d"}, - }, - }, - }, - }, - }, - Ingress: []networking.NetworkPolicyIngressRule{ - { - From: []networking.NetworkPolicyPeer{ - { - IPBlock: &networking.IPBlock{ - CIDR: "fd00:192:168::/48", - Except: []string{"fd00:192:168:3::/64", "fd00:192:168:4::/64"}, - }, - }, - }, - }, - }, - }, - }, - { - 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: "fd00:192:168::/48", - Except: []string{"fd00:192:168:3::/64", "fd00:192:168:4::/64"}, - }, - }, - }, - }, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - }, - Egress: []networking.NetworkPolicyEgressRule{ - { - To: []networking.NetworkPolicyPeer{ - { - IPBlock: &networking.IPBlock{ - CIDR: "fd00:192:168::/48", - Except: []string{"fd00:192:168:3::/64", "fd00:192:168:4::/64"}, - }, - }, - }, - }, - }, - PolicyTypes: []networking.PolicyType{networking.PolicyTypeEgress}, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - }, - Egress: []networking.NetworkPolicyEgressRule{ - { - To: []networking.NetworkPolicyPeer{ - { - IPBlock: &networking.IPBlock{ - CIDR: "fd00:192:168::/48", - Except: []string{"fd00:192:168:3::/64", "fd00:192:168:4::/64"}, - }, - }, - }, - }, - }, - PolicyTypes: []networking.PolicyType{networking.PolicyTypeIngress, networking.PolicyTypeEgress}, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - }, - Egress: []networking.NetworkPolicyEgressRule{ - { - Ports: []networking.NetworkPolicyPort{ - { - Protocol: nil, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 32000}, - EndPort: &endPort, - }, - { - Protocol: &protocolUDP, - Port: &intstr.IntOrString{Type: intstr.String, StrVal: "dns"}, - }, - }, - }, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - }, - Egress: []networking.NetworkPolicyEgressRule{ - { - To: []networking.NetworkPolicyPeer{ - { - NamespaceSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"c": "d"}, - }, - }, - }, - Ports: []networking.NetworkPolicyPort{ - { - Protocol: nil, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 30000}, - EndPort: &endPort, - }, - { - Protocol: nil, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 32000}, - EndPort: &endPort, - }, - }, - }, - }, - Ingress: []networking.NetworkPolicyIngressRule{ - { - From: []networking.NetworkPolicyPeer{ - { - PodSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"e": "f"}, - }, - }, - }, - Ports: []networking.NetworkPolicyPort{ - { - Protocol: &protocolTCP, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 32768}, - EndPort: &endPort, - }, - }, - }, - }, - }, - }, + + // Tweaks used below. + setIngressEmptyFirstElement := func(networkPolicy *networking.NetworkPolicy) { + networkPolicy.Spec.Ingress = []networking.NetworkPolicyIngressRule{{}} + } + + setIngressFromEmptyFirstElement := func(networkPolicy *networking.NetworkPolicy) { + if networkPolicy.Spec.Ingress == nil { + setIngressEmptyFirstElement(networkPolicy) + } + networkPolicy.Spec.Ingress[0].From = []networking.NetworkPolicyPeer{{}} + } + + setIngressFromIfEmpty := func(networkPolicy *networking.NetworkPolicy) { + if networkPolicy.Spec.Ingress == nil { + setIngressEmptyFirstElement(networkPolicy) + } + if networkPolicy.Spec.Ingress[0].From == nil { + setIngressFromEmptyFirstElement(networkPolicy) + } + } + + setIngressEmptyPorts := func(networkPolicy *networking.NetworkPolicy) { + networkPolicy.Spec.Ingress = []networking.NetworkPolicyIngressRule{{ + Ports: []networking.NetworkPolicyPort{{}}, + }} + } + + setIngressPorts := func(ports ...networking.NetworkPolicyPort) netpolTweak { + return func(np *networking.NetworkPolicy) { + if np.Spec.Ingress == nil { + setIngressEmptyFirstElement(np) + } + np.Spec.Ingress[0].Ports = make([]networking.NetworkPolicyPort, len(ports)) + for i, p := range ports { + np.Spec.Ingress[0].Ports[i] = p + } + } + } + + setIngressFromPodSelector := func(k, v string) func(*networking.NetworkPolicy) { + return func(networkPolicy *networking.NetworkPolicy) { + setIngressFromIfEmpty(networkPolicy) + networkPolicy.Spec.Ingress[0].From[0].PodSelector = &metav1.LabelSelector{ + MatchLabels: map[string]string{k: v}, + } + } + } + + setIngressFromNamespaceSelector := func(networkPolicy *networking.NetworkPolicy) { + setIngressFromIfEmpty(networkPolicy) + networkPolicy.Spec.Ingress[0].From[0].NamespaceSelector = &metav1.LabelSelector{ + MatchLabels: map[string]string{"c": "d"}, + } + } + + setIngressFromIPBlockIPV4 := func(networkPolicy *networking.NetworkPolicy) { + setIngressFromIfEmpty(networkPolicy) + networkPolicy.Spec.Ingress[0].From[0].IPBlock = &networking.IPBlock{ + CIDR: "192.168.0.0/16", + Except: []string{"192.168.3.0/24", "192.168.4.0/24"}, + } + } + + setIngressFromIPBlockIPV6 := func(networkPolicy *networking.NetworkPolicy) { + setIngressFromIfEmpty(networkPolicy) + networkPolicy.Spec.Ingress[0].From[0].IPBlock = &networking.IPBlock{ + CIDR: "fd00:192:168::/48", + Except: []string{"fd00:192:168:3::/64", "fd00:192:168:4::/64"}, + } + } + + setEgressEmptyFirstElement := func(networkPolicy *networking.NetworkPolicy) { + networkPolicy.Spec.Egress = []networking.NetworkPolicyEgressRule{{}} + } + + setEgressToEmptyFirstElement := func(networkPolicy *networking.NetworkPolicy) { + if networkPolicy.Spec.Egress == nil { + setEgressEmptyFirstElement(networkPolicy) + } + networkPolicy.Spec.Egress[0].To = []networking.NetworkPolicyPeer{{}} + } + + setEgressToIfEmpty := func(networkPolicy *networking.NetworkPolicy) { + if networkPolicy.Spec.Egress == nil { + setEgressEmptyFirstElement(networkPolicy) + } + if networkPolicy.Spec.Egress[0].To == nil { + setEgressToEmptyFirstElement(networkPolicy) + } + } + + setEgressToNamespaceSelector := func(networkPolicy *networking.NetworkPolicy) { + setEgressToIfEmpty(networkPolicy) + networkPolicy.Spec.Egress[0].To[0].NamespaceSelector = &metav1.LabelSelector{ + MatchLabels: map[string]string{"c": "d"}, + } + } + + setEgressToPodSelector := func(networkPolicy *networking.NetworkPolicy) { + setEgressToIfEmpty(networkPolicy) + networkPolicy.Spec.Egress[0].To[0].PodSelector = &metav1.LabelSelector{ + MatchLabels: map[string]string{"c": "d"}, + } + } + + setEgressToIPBlockIPV4 := func(networkPolicy *networking.NetworkPolicy) { + setEgressToIfEmpty(networkPolicy) + networkPolicy.Spec.Egress[0].To[0].IPBlock = &networking.IPBlock{ + CIDR: "192.168.0.0/16", + Except: []string{"192.168.3.0/24", "192.168.4.0/24"}, + } + } + + setEgressToIPBlockIPV6 := func(networkPolicy *networking.NetworkPolicy) { + setEgressToIfEmpty(networkPolicy) + networkPolicy.Spec.Egress[0].To[0].IPBlock = &networking.IPBlock{ + CIDR: "fd00:192:168::/48", + Except: []string{"fd00:192:168:3::/64", "fd00:192:168:4::/64"}, + } + } + + setEgressPorts := func(ports ...networking.NetworkPolicyPort) netpolTweak { + return func(np *networking.NetworkPolicy) { + if np.Spec.Egress == nil { + setEgressEmptyFirstElement(np) + } + np.Spec.Egress[0].Ports = make([]networking.NetworkPolicyPort, len(ports)) + for i, p := range ports { + np.Spec.Egress[0].Ports[i] = p + } + } + } + + setPolicyTypesEgress := func(networkPolicy *networking.NetworkPolicy) { + networkPolicy.Spec.PolicyTypes = []networking.PolicyType{networking.PolicyTypeEgress} + } + + setPolicyTypesIngressEgress := func(networkPolicy *networking.NetworkPolicy) { + networkPolicy.Spec.PolicyTypes = []networking.PolicyType{networking.PolicyTypeIngress, networking.PolicyTypeEgress} + } + + successCases := []*networking.NetworkPolicy{ + makeNetworkPolicyCustom(setIngressEmptyFirstElement), + makeNetworkPolicyCustom(setIngressFromEmptyFirstElement, setIngressEmptyPorts), + makeNetworkPolicyCustom(setIngressPorts( + makePort(nil, intstr.FromInt(80), 0), + makePort(&protocolTCP, intstr.FromInt(0), 0), + makePort(&protocolTCP, intstr.FromInt(443), 0), + makePort(&protocolUDP, intstr.FromString("dns"), 0), + makePort(&protocolSCTP, intstr.FromInt(7777), 0), + )), + makeNetworkPolicyCustom(setIngressFromPodSelector("c", "d")), + makeNetworkPolicyCustom(setIngressFromNamespaceSelector), + makeNetworkPolicyCustom(setIngressFromPodSelector("e", "f"), setIngressFromNamespaceSelector), + makeNetworkPolicyCustom(setEgressToNamespaceSelector, setIngressFromIPBlockIPV4), + makeNetworkPolicyCustom(setIngressFromIPBlockIPV4), + makeNetworkPolicyCustom(setEgressToIPBlockIPV4, setPolicyTypesEgress), + makeNetworkPolicyCustom(setEgressToIPBlockIPV4, setPolicyTypesIngressEgress), + makeNetworkPolicyCustom(setEgressPorts( + makePort(nil, intstr.FromInt(80), 0), + makePort(&protocolTCP, intstr.FromInt(0), 0), + makePort(&protocolTCP, intstr.FromInt(443), 0), + makePort(&protocolUDP, intstr.FromString("dns"), 0), + makePort(&protocolSCTP, intstr.FromInt(7777), 0), + )), + makeNetworkPolicyCustom(setEgressToNamespaceSelector, setIngressFromIPBlockIPV6), + makeNetworkPolicyCustom(setIngressFromIPBlockIPV6), + makeNetworkPolicyCustom(setEgressToIPBlockIPV6, setPolicyTypesEgress), + makeNetworkPolicyCustom(setEgressToIPBlockIPV6, setPolicyTypesIngressEgress), + makeNetworkPolicyCustom(setEgressPorts(makePort(nil, intstr.FromInt(32000), 32768), makePort(&protocolUDP, intstr.FromString("dns"), 0))), + makeNetworkPolicyCustom( + setEgressToNamespaceSelector, + setEgressPorts( + makePort(nil, intstr.FromInt(30000), 32768), + makePort(nil, intstr.FromInt(32000), 32768), + ), + setIngressFromPodSelector("e", "f"), + setIngressPorts(makePort(&protocolTCP, intstr.FromInt(32768), 32768))), } // Success cases are expected to pass validation. for k, v := range successCases { - if errs := ValidateNetworkPolicy(&v); len(errs) != 0 { - t.Errorf("Expected success for %d, got %v", k, errs) + if errs := ValidateNetworkPolicy(v); len(errs) != 0 { + t.Errorf("Expected success for the success validation test number %d, got %v", k, errs) } } invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"} - errorCases := map[string]networking.NetworkPolicy{ - "namespaceSelector and ipBlock": { - 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{ - { - NamespaceSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"c": "d"}, - }, - IPBlock: &networking.IPBlock{ - CIDR: "192.168.0.0/16", - Except: []string{"192.168.3.0/24", "192.168.4.0/24"}, - }, - }, - }, - }, - }, - }, - }, - "podSelector and ipBlock": { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - }, - Egress: []networking.NetworkPolicyEgressRule{ - { - To: []networking.NetworkPolicyPeer{ - { - PodSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"c": "d"}, - }, - IPBlock: &networking.IPBlock{ - CIDR: "192.168.0.0/16", - Except: []string{"192.168.3.0/24", "192.168.4.0/24"}, - }, - }, - }, - }, - }, - }, - }, - "missing from and to type": { - 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{{}}, - }, - }, - Egress: []networking.NetworkPolicyEgressRule{ - { - To: []networking.NetworkPolicyPeer{{}}, - }, - }, - }, - }, - "invalid spec.podSelector": { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ + + errorCases := map[string]*networking.NetworkPolicy{ + "namespaceSelector and ipBlock": makeNetworkPolicyCustom(setIngressFromNamespaceSelector, setIngressFromIPBlockIPV4), + "podSelector and ipBlock": makeNetworkPolicyCustom(setEgressToPodSelector, setEgressToIPBlockIPV4), + "missing from and to type": makeNetworkPolicyCustom(setIngressFromEmptyFirstElement, setEgressToEmptyFirstElement), + "invalid spec.podSelector": makeNetworkPolicyCustom(setIngressFromNamespaceSelector, func(networkPolicy *networking.NetworkPolicy) { + networkPolicy.Spec = networking.NetworkPolicySpec{ PodSelector: metav1.LabelSelector{ MatchLabels: invalidSelector, }, - Ingress: []networking.NetworkPolicyIngressRule{ - { - From: []networking.NetworkPolicyPeer{ - { - NamespaceSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"c": "d"}, - }, - }, - }, - }, - }, - }, - }, - "invalid ingress.ports.protocol": { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{}, - Ingress: []networking.NetworkPolicyIngressRule{ - { - Ports: []networking.NetworkPolicyPort{ - { - Protocol: &protocolICMP, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 80}, - }, - }, - }, - }, - }, - }, - "invalid ingress.ports.port (int)": { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{}, - Ingress: []networking.NetworkPolicyIngressRule{ - { - Ports: []networking.NetworkPolicyPort{ - { - Protocol: &protocolTCP, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 123456789}, - }, - }, - }, - }, - }, - }, - "invalid ingress.ports.port (str)": { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{}, - Ingress: []networking.NetworkPolicyIngressRule{ - { - Ports: []networking.NetworkPolicyPort{ - { - Protocol: &protocolTCP, - Port: &intstr.IntOrString{Type: intstr.String, StrVal: "!@#$"}, - }, - }, - }, - }, - }, - }, - "invalid ingress.from.podSelector": { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{}, - Ingress: []networking.NetworkPolicyIngressRule{ - { - From: []networking.NetworkPolicyPeer{ - { - PodSelector: &metav1.LabelSelector{ - MatchLabels: invalidSelector, - }, - }, - }, - }, - }, - }, - }, - "invalid egress.to.podSelector": { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{}, - Egress: []networking.NetworkPolicyEgressRule{ - { - To: []networking.NetworkPolicyPeer{ - { - PodSelector: &metav1.LabelSelector{ - MatchLabels: invalidSelector, - }, - }, - }, - }, - }, - }, - }, - "invalid egress.ports.protocol": { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{}, - Egress: []networking.NetworkPolicyEgressRule{ - { - Ports: []networking.NetworkPolicyPort{ - { - Protocol: &protocolICMP, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 80}, - }, - }, - }, - }, - }, - }, - "invalid egress.ports.port (int)": { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{}, - Egress: []networking.NetworkPolicyEgressRule{ - { - Ports: []networking.NetworkPolicyPort{ - { - Protocol: &protocolTCP, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 123456789}, - }, - }, - }, - }, - }, - }, - "invalid egress.ports.port (str)": { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{}, - Egress: []networking.NetworkPolicyEgressRule{ - { - Ports: []networking.NetworkPolicyPort{ - { - Protocol: &protocolTCP, - Port: &intstr.IntOrString{Type: intstr.String, StrVal: "!@#$"}, - }, - }, - }, - }, - }, - }, - "invalid ingress.from.namespaceSelector": { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{}, - Ingress: []networking.NetworkPolicyIngressRule{ - { - From: []networking.NetworkPolicyPeer{ - { - NamespaceSelector: &metav1.LabelSelector{ - MatchLabels: invalidSelector, - }, - }, - }, - }, - }, - }, - }, - "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"}, - }, - }, - }, - }, - }, - }, - }, - "invalid ipv6 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: "fd00:192:168::", - Except: []string{"fd00:192:168:3::/64", "fd00:192:168:4::/64"}, - }, - }, - }, - }, - }, - }, - }, - "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"}, - }, - }, - }, - }, - }, - }, - }, - "except IP is not strictly within 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.0.0/24", - Except: []string{"192.168.0.0/24"}, - }, - }, - }, - }, - }, - }, - }, - "except IPv6 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: "fd00:192:168:1::/64", - Except: []string{"fd00:192:168:2::/64"}, - }, - }, - }, - }, - }, - }, - }, - "invalid policyTypes": { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - }, - Egress: []networking.NetworkPolicyEgressRule{ - { - To: []networking.NetworkPolicyPeer{ - { - IPBlock: &networking.IPBlock{ - CIDR: "192.168.0.0/16", - Except: []string{"192.168.3.0/24", "192.168.4.0/24"}, - }, - }, - }, - }, - }, - PolicyTypes: []networking.PolicyType{"foo", "bar"}, - }, - }, - "too many policyTypes": { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - }, - Egress: []networking.NetworkPolicyEgressRule{ - { - To: []networking.NetworkPolicyPeer{ - { - IPBlock: &networking.IPBlock{ - CIDR: "192.168.0.0/16", - Except: []string{"192.168.3.0/24", "192.168.4.0/24"}, - }, - }, - }, - }, - }, - PolicyTypes: []networking.PolicyType{"foo", "bar", "baz"}, - }, - }, - "multiple ports defined, one port range is invalid": { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - }, - Egress: []networking.NetworkPolicyEgressRule{ - { - To: []networking.NetworkPolicyPeer{ - { - NamespaceSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"c": "d"}, - }, - }, - }, - Ports: []networking.NetworkPolicyPort{ - { - Protocol: &protocolUDP, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 35000}, - EndPort: &endPort, - }, - { - Protocol: nil, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 32000}, - EndPort: &endPort, - }, - }, - }, - }, - }, - }, - "endPort defined with named/string port": { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - }, - Egress: []networking.NetworkPolicyEgressRule{ - { - To: []networking.NetworkPolicyPeer{ - { - NamespaceSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"c": "d"}, - }, - }, - }, - Ports: []networking.NetworkPolicyPort{ - { - Protocol: &protocolUDP, - Port: &intstr.IntOrString{Type: intstr.String, StrVal: "dns"}, - EndPort: &endPort, - }, - { - Protocol: nil, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 32000}, - EndPort: &endPort, - }, - }, - }, - }, - }, - }, - "endPort defined without port defined": { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - }, - Egress: []networking.NetworkPolicyEgressRule{ - { - To: []networking.NetworkPolicyPeer{ - { - NamespaceSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"c": "d"}, - }, - }, - }, - Ports: []networking.NetworkPolicyPort{ - { - Protocol: &protocolTCP, - EndPort: &endPort, - }, - }, - }, - }, - }, - }, - "port is greater than endPort": { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - }, - Egress: []networking.NetworkPolicyEgressRule{ - { - To: []networking.NetworkPolicyPeer{ - { - NamespaceSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"c": "d"}, - }, - }, - }, - Ports: []networking.NetworkPolicyPort{ - { - Protocol: &protocolSCTP, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 33000}, - EndPort: &endPort, - }, - }, - }, - }, - }, - }, - "multiple invalid port ranges defined": { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - }, - Egress: []networking.NetworkPolicyEgressRule{ - { - To: []networking.NetworkPolicyPeer{ - { - NamespaceSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"c": "d"}, - }, - }, - }, - Ports: []networking.NetworkPolicyPort{ - { - Protocol: &protocolUDP, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 35000}, - EndPort: &endPort, - }, - { - Protocol: &protocolTCP, - EndPort: &endPort, - }, - { - Protocol: &protocolTCP, - Port: &intstr.IntOrString{Type: intstr.String, StrVal: "https"}, - EndPort: &endPort, - }, - }, - }, - }, - }, - }, - "invalid endport range defined": { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - }, - Egress: []networking.NetworkPolicyEgressRule{ - { - To: []networking.NetworkPolicyPeer{ - { - NamespaceSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"c": "d"}, - }, - }, - }, - Ports: []networking.NetworkPolicyPort{ - { - Protocol: nil, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 30000}, - EndPort: utilpointer.Int32Ptr(65537), - }, - }, - }, - }, - }, - }, + } + }), + "invalid ingress.ports.protocol": makeNetworkPolicyCustom(setIngressPorts(makePort(&protocolICMP, intstr.FromInt(80), 0))), + "invalid ingress.ports.port (int)": makeNetworkPolicyCustom(setIngressPorts(makePort(&protocolTCP, intstr.FromInt(123456789), 0))), + "invalid ingress.ports.port (str)": makeNetworkPolicyCustom( + setIngressPorts(makePort(&protocolTCP, intstr.FromString("!@#$"), 0))), + "invalid ingress.from.podSelector": makeNetworkPolicyCustom(setIngressFromEmptyFirstElement, func(networkPolicy *networking.NetworkPolicy) { + networkPolicy.Spec.Ingress[0].From[0].PodSelector = &metav1.LabelSelector{ + MatchLabels: invalidSelector, + } + }), + "invalid egress.to.podSelector": makeNetworkPolicyCustom(setEgressToEmptyFirstElement, func(networkPolicy *networking.NetworkPolicy) { + networkPolicy.Spec.Egress[0].To[0].PodSelector = &metav1.LabelSelector{ + MatchLabels: invalidSelector, + } + }), + "invalid egress.ports.protocol": makeNetworkPolicyCustom(setEgressPorts(makePort(&protocolICMP, intstr.FromInt(80), 0))), + "invalid egress.ports.port (int)": makeNetworkPolicyCustom(setEgressPorts(makePort(&protocolTCP, intstr.FromInt(123456789), 0))), + "invalid egress.ports.port (str)": makeNetworkPolicyCustom(setEgressPorts(makePort(&protocolTCP, intstr.FromString("!@#$"), 0))), + "invalid ingress.from.namespaceSelector": makeNetworkPolicyCustom(setIngressFromEmptyFirstElement, func(networkPolicy *networking.NetworkPolicy) { + networkPolicy.Spec.Ingress[0].From[0].NamespaceSelector = &metav1.LabelSelector{ + MatchLabels: invalidSelector, + } + }), + "missing cidr field": makeNetworkPolicyCustom(setIngressFromIPBlockIPV4, func(networkPolicy *networking.NetworkPolicy) { + networkPolicy.Spec.Ingress[0].From[0].IPBlock.CIDR = "" + }), + "invalid cidr format": makeNetworkPolicyCustom(setIngressFromIPBlockIPV4, func(networkPolicy *networking.NetworkPolicy) { + networkPolicy.Spec.Ingress[0].From[0].IPBlock.CIDR = "192.168.5.6" + }), + "invalid ipv6 cidr format": makeNetworkPolicyCustom(setIngressFromIPBlockIPV6, func(networkPolicy *networking.NetworkPolicy) { + networkPolicy.Spec.Ingress[0].From[0].IPBlock.CIDR = "fd00:192:168::" + }), + "except field is an empty string": makeNetworkPolicyCustom(setIngressFromIPBlockIPV4, func(networkPolicy *networking.NetworkPolicy) { + networkPolicy.Spec.Ingress[0].From[0].IPBlock.Except = []string{""} + }), + "except field is an space string": makeNetworkPolicyCustom(setIngressFromIPBlockIPV4, func(networkPolicy *networking.NetworkPolicy) { + networkPolicy.Spec.Ingress[0].From[0].IPBlock.Except = []string{" "} + }), + "except field is an invalid ip": makeNetworkPolicyCustom(setIngressFromIPBlockIPV4, func(networkPolicy *networking.NetworkPolicy) { + networkPolicy.Spec.Ingress[0].From[0].IPBlock.Except = []string{"300.300.300.300"} + }), + "except IP is outside of CIDR range": makeNetworkPolicyCustom(setIngressFromEmptyFirstElement, func(networkPolicy *networking.NetworkPolicy) { + networkPolicy.Spec.Ingress[0].From[0].IPBlock = &networking.IPBlock{ + CIDR: "192.168.8.0/24", + Except: []string{"192.168.9.1/24"}, + } + }), + "except IP is not strictly within CIDR range": makeNetworkPolicyCustom(setIngressFromEmptyFirstElement, func(networkPolicy *networking.NetworkPolicy) { + networkPolicy.Spec.Ingress[0].From[0].IPBlock = &networking.IPBlock{ + CIDR: "192.168.0.0/24", + Except: []string{"192.168.0.0/24"}, + } + }), + "except IPv6 is outside of CIDR range": makeNetworkPolicyCustom(setIngressFromEmptyFirstElement, func(networkPolicy *networking.NetworkPolicy) { + networkPolicy.Spec.Ingress[0].From[0].IPBlock = &networking.IPBlock{ + CIDR: "fd00:192:168:1::/64", + Except: []string{"fd00:192:168:2::/64"}, + } + }), + "invalid policyTypes": makeNetworkPolicyCustom(setEgressToIPBlockIPV4, func(networkPolicy *networking.NetworkPolicy) { + networkPolicy.Spec.PolicyTypes = []networking.PolicyType{"foo", "bar"} + }), + "too many policyTypes": makeNetworkPolicyCustom(setEgressToIPBlockIPV4, func(networkPolicy *networking.NetworkPolicy) { + networkPolicy.Spec.PolicyTypes = []networking.PolicyType{"foo", "bar", "baz"} + }), + "multiple ports defined, one port range is invalid": makeNetworkPolicyCustom( + setEgressToNamespaceSelector, + setEgressPorts( + makePort(&protocolUDP, intstr.FromInt(35000), 32768), + makePort(nil, intstr.FromInt(32000), 32768), + ), + ), + "endPort defined with named/string port": makeNetworkPolicyCustom( + setEgressToNamespaceSelector, + setEgressPorts( + makePort(&protocolUDP, intstr.FromString("dns"), 32768), + makePort(nil, intstr.FromInt(32000), 32768), + ), + ), + "endPort defined without port defined": makeNetworkPolicyCustom( + setEgressToNamespaceSelector, + setEgressPorts(makePort(&protocolTCP, intstr.FromInt(0), 32768)), + ), + "port is greater than endPort": makeNetworkPolicyCustom( + setEgressToNamespaceSelector, + setEgressPorts(makePort(&protocolSCTP, intstr.FromInt(35000), 32768)), + ), + "multiple invalid port ranges defined": makeNetworkPolicyCustom( + setEgressToNamespaceSelector, + setEgressPorts( + makePort(&protocolUDP, intstr.FromInt(35000), 32768), + makePort(&protocolTCP, intstr.FromInt(0), 32768), + makePort(&protocolTCP, intstr.FromString("https"), 32768), + ), + ), + "invalid endport range defined": makeNetworkPolicyCustom(setEgressToNamespaceSelector, setEgressPorts(makePort(&protocolTCP, intstr.FromInt(30000), 65537))), } // Error cases are not expected to pass validation. for testName, networkPolicy := range errorCases { - if errs := ValidateNetworkPolicy(&networkPolicy); len(errs) == 0 { + if errs := ValidateNetworkPolicy(networkPolicy); len(errs) == 0 { t.Errorf("Expected failure for test: %s", testName) } }