Skip to content

Commit

Permalink
Implement inline CIDR egress peer
Browse files Browse the repository at this point in the history
This PR adds support for implementing inline CIDR
peer blocks.

Signed-off-by: Surya Seetharaman <[email protected]>
  • Loading branch information
tssurya committed Feb 28, 2024
1 parent dc00b36 commit 5658b95
Show file tree
Hide file tree
Showing 7 changed files with 234 additions and 0 deletions.
51 changes: 51 additions & 0 deletions apis/v1alpha1/shared_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,13 @@ type PortRange struct {
}

// AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from.
//
// Note that presence of a Service object with this policy subject as its backend
// has no impact on the behavior of the policy applied to the peer
// trying to talk to the Service. It will work in the same way as if the
// Service didn't exist since policy is applied after ServiceVIP (clusterIP,
// externalIP, loadBalancerIngressVIP) is rewritten to the backendIPs.
//
// Exactly one of the selector pointers must be set for a given peer. If a
// consumer observes none of its fields are set, they must assume an unknown
// option has been specified and fail closed.
Expand All @@ -145,6 +152,13 @@ type AdminNetworkPolicyIngressPeer struct {
}

// AdminNetworkPolicyEgressPeer defines a peer to allow traffic to.
//
// Note that presence of a Service object with this peer as its backend
// has no impact on the behavior of the policy applied to the subject
// trying to talk to the Service. It will work in the same way as if the
// Service didn't exist since policy is applied after ServiceVIP (clusterIP,
// externalIP, loadBalancerIngressVIP) is rewritten to the backendIPs.
//
// Exactly one of the selector pointers must be set for a given peer. If a
// consumer observes none of its fields are set, they must assume an unknown
// option has been specified and fail closed.
Expand Down Expand Up @@ -175,6 +189,33 @@ type AdminNetworkPolicyEgressPeer struct {
// <network-policy-api:experimental>
// +optional
Nodes *metav1.LabelSelector `json:"nodes,omitempty"`
// Networks defines a way to select peers via CIDR blocks (both v4 & v6).
// This is intended for representing entities that live outside the cluster,
// which can't be selected by pods, namespaces and nodes peers, but note
// that cluster-internal traffic will be checked against the rule as
// well. So if you Allow or Deny traffic to `"0.0.0.0/0"`, that will allow
// or deny all IPv4 pod-to-pod traffic as well. If you don't want that,
// add a rule that Passes all pod traffic before the Networks rule.
//
// Do not provide serviceCIDR range in `networks` peer. This is NOT supported.
// While 0.0.0.0/0 will match on the serviceVIP as well, it does not make much sense
// anyways in that case because policies are expected to be applied after the serviceVIP
// (clusterIP, externalIP, loadbalancer.Ingress.VIP) is rewritten to the actual backend IPs.
// So policy match finally gets applied on the endpointIPs not serviceVIPs.
//
// Each item in Networks should be provided in the CIDR format and should be
// IPv4 or IPv6, for example "10.0.0.0/8" or "fd00::/8". IPv4 address embedded
// in IPv6 addresses are not supported.
//
// Networks can have upto 25 CIDRs specified.
//
// Support: Extended
//
// <network-policy-api:experimental>
// +optional
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=25
Networks []CIDR `json:"networks,omitempty"`
}

// NamespacedPeer defines a flexible way to select Namespaces in a cluster.
Expand Down Expand Up @@ -237,3 +278,13 @@ type NamespacedPodPeer struct {
//
PodSelector metav1.LabelSelector `json:"podSelector"`
}

// CIDR is an IP address range in CIDR notation (for example, "10.0.0.0/8" or "fd00::/8").
// The regex for the IPv4 and IPv6 CIDR range was taken from
// https://blog.markhatton.co.uk/2011/03/15/regular-expressions-for-ip-addresses-cidr-ranges-and-hostnames/
// The resulting regex is an OR of both regexes. IPv4 address embedded in IPv6 addresses are not supported.
// TODO: Change the CIDR's validation regex to use CEL isCIDR() in Kube 1.31 when it is available.
// +kubebuilder:validation:Pattern=`(^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(3[0-2]|[1-2][0-9]|[0-9]))$)|(^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/(12[0-8]|1[0-1][0-9]|[1-9][0-9]|[0-9]))$)`
// +kubebuilder:validation:XValidation:rule="self.contains(':') != self.contains('.')",message="CIDR must be either an IPv4 or IPv6 address. IPv4 address embedded in IPv6 addresses are not supported"
// +kubebuilder:validation:MaxLength=43
type CIDR string
5 changes: 5 additions & 0 deletions apis/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,15 @@ spec:
items:
description: |-
AdminNetworkPolicyEgressPeer defines a peer to allow traffic to.
Note that presence of a Service object with this peer as its backend
has no impact on the behavior of the policy applied to the subject
trying to talk to the Service. It will work in the same way as if the
Service didn't exist since policy is applied after ServiceVIP (clusterIP,
externalIP, loadBalancerIngressVIP) is rewritten to the backendIPs.
Exactly one of the selector pointers must be set for a given peer. If a
consumer observes none of its fields are set, they must assume an unknown
option has been specified and fail closed.
Expand Down Expand Up @@ -310,6 +319,54 @@ spec:
maxItems: 100
type: array
type: object
networks:
description: |-
Networks defines a way to select peers via CIDR blocks (both v4 & v6).
This is intended for representing entities that live outside the cluster,
which can't be selected by pods, namespaces and nodes peers, but note
that cluster-internal traffic will be checked against the rule as
well. So if you Allow or Deny traffic to `"0.0.0.0/0"`, that will allow
or deny all IPv4 pod-to-pod traffic as well. If you don't want that,
add a rule that Passes all pod traffic before the Networks rule.
Do not provide serviceCIDR range in `networks` peer. This is NOT supported.
While 0.0.0.0/0 will match on the serviceVIP as well, it does not make much sense
anyways in that case because policies are expected to be applied after the serviceVIP
(clusterIP, externalIP, loadbalancer.Ingress.VIP) is rewritten to the actual backend IPs.
So policy match finally gets applied on the endpointIPs not serviceVIPs.
Each item in Networks should be provided in the CIDR format and should be
IPv4 or IPv6, for example "10.0.0.0/8" or "fd00::/8". IPv4 address embedded
in IPv6 addresses are not supported.
Networks can have upto 25 CIDRs specified.
Support: Extended
<network-policy-api:experimental>
items:
description: |-
CIDR is an IP address range in CIDR notation (for example, "10.0.0.0/8" or "fd00::/8").
The regex for the IPv4 and IPv6 CIDR range was taken from
https://blog.markhatton.co.uk/2011/03/15/regular-expressions-for-ip-addresses-cidr-ranges-and-hostnames/
The resulting regex is an OR of both regexes. IPv4 address embedded in IPv6 addresses are not supported.
TODO: Change the CIDR's validation regex to use CEL isCIDR() in Kube 1.31 when it is available.
maxLength: 43
pattern: (^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(3[0-2]|[1-2][0-9]|[0-9]))$)|(^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/(12[0-8]|1[0-1][0-9]|[1-9][0-9]|[0-9]))$)
type: string
x-kubernetes-validations:
- message: CIDR must be either an IPv4 or IPv6 address.
IPv4 address embedded in IPv6 addresses are not
supported
rule: self.contains(':') != self.contains('.')
maxItems: 25
minItems: 1
type: array
nodes:
description: |-
Nodes defines a way to select a set of nodes in
Expand Down Expand Up @@ -576,6 +633,15 @@ spec:
items:
description: |-
AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from.
Note that presence of a Service object with this policy subject as its backend
has no impact on the behavior of the policy applied to the peer
trying to talk to the Service. It will work in the same way as if the
Service didn't exist since policy is applied after ServiceVIP (clusterIP,
externalIP, loadBalancerIngressVIP) is rewritten to the backendIPs.
Exactly one of the selector pointers must be set for a given peer. If a
consumer observes none of its fields are set, they must assume an unknown
option has been specified and fail closed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,15 @@ spec:
items:
description: |-
AdminNetworkPolicyEgressPeer defines a peer to allow traffic to.
Note that presence of a Service object with this peer as its backend
has no impact on the behavior of the policy applied to the subject
trying to talk to the Service. It will work in the same way as if the
Service didn't exist since policy is applied after ServiceVIP (clusterIP,
externalIP, loadBalancerIngressVIP) is rewritten to the backendIPs.
Exactly one of the selector pointers must be set for a given peer. If a
consumer observes none of its fields are set, they must assume an unknown
option has been specified and fail closed.
Expand Down Expand Up @@ -301,6 +310,54 @@ spec:
maxItems: 100
type: array
type: object
networks:
description: |-
Networks defines a way to select peers via CIDR blocks (both v4 & v6).
This is intended for representing entities that live outside the cluster,
which can't be selected by pods, namespaces and nodes peers, but note
that cluster-internal traffic will be checked against the rule as
well. So if you Allow or Deny traffic to `"0.0.0.0/0"`, that will allow
or deny all IPv4 pod-to-pod traffic as well. If you don't want that,
add a rule that Passes all pod traffic before the Networks rule.
Do not provide serviceCIDR range in `networks` peer. This is NOT supported.
While 0.0.0.0/0 will match on the serviceVIP as well, it does not make much sense
anyways in that case because policies are expected to be applied after the serviceVIP
(clusterIP, externalIP, loadbalancer.Ingress.VIP) is rewritten to the actual backend IPs.
So policy match finally gets applied on the endpointIPs not serviceVIPs.
Each item in Networks should be provided in the CIDR format and should be
IPv4 or IPv6, for example "10.0.0.0/8" or "fd00::/8". IPv4 address embedded
in IPv6 addresses are not supported.
Networks can have upto 25 CIDRs specified.
Support: Extended
<network-policy-api:experimental>
items:
description: |-
CIDR is an IP address range in CIDR notation (for example, "10.0.0.0/8" or "fd00::/8").
The regex for the IPv4 and IPv6 CIDR range was taken from
https://blog.markhatton.co.uk/2011/03/15/regular-expressions-for-ip-addresses-cidr-ranges-and-hostnames/
The resulting regex is an OR of both regexes. IPv4 address embedded in IPv6 addresses are not supported.
TODO: Change the CIDR's validation regex to use CEL isCIDR() in Kube 1.31 when it is available.
maxLength: 43
pattern: (^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(3[0-2]|[1-2][0-9]|[0-9]))$)|(^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/(12[0-8]|1[0-1][0-9]|[1-9][0-9]|[0-9]))$)
type: string
x-kubernetes-validations:
- message: CIDR must be either an IPv4 or IPv6 address.
IPv4 address embedded in IPv6 addresses are not
supported
rule: self.contains(':') != self.contains('.')
maxItems: 25
minItems: 1
type: array
nodes:
description: |-
Nodes defines a way to select a set of nodes in
Expand Down Expand Up @@ -564,6 +621,15 @@ spec:
items:
description: |-
AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from.
Note that presence of a Service object with this policy subject as its backend
has no impact on the behavior of the policy applied to the peer
trying to talk to the Service. It will work in the same way as if the
Service didn't exist since policy is applied after ServiceVIP (clusterIP,
externalIP, loadBalancerIngressVIP) is rewritten to the backendIPs.
Exactly one of the selector pointers must be set for a given peer. If a
consumer observes none of its fields are set, they must assume an unknown
option has been specified and fail closed.
Expand Down
Loading

0 comments on commit 5658b95

Please sign in to comment.