Skip to content

Commit 7c08fb6

Browse files
committed
Implement inline CIDR egress peer
This PR adds support for implementing inline CIDR peer blocks. Signed-off-by: Surya Seetharaman <[email protected]>
1 parent dc00b36 commit 7c08fb6

11 files changed

+236
-8
lines changed

apis/v1alpha1/shared_types.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,13 @@ type PortRange struct {
121121
}
122122

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

147154
// AdminNetworkPolicyEgressPeer defines a peer to allow traffic to.
155+
//
156+
// Note that presence of a Service object with this peer as its backend
157+
// has no impact on the behavior of the policy applied to the subject
158+
// trying to talk to the Service. It will work in the same way as if the
159+
// Service didn't exist since policy is applied after ServiceVIP (clusterIP,
160+
// externalIP, loadBalancerIngressIP) is rewritten to the backendIPs.
161+
//
148162
// Exactly one of the selector pointers must be set for a given peer. If a
149163
// consumer observes none of its fields are set, they must assume an unknown
150164
// option has been specified and fail closed.
@@ -175,6 +189,31 @@ type AdminNetworkPolicyEgressPeer struct {
175189
// <network-policy-api:experimental>
176190
// +optional
177191
Nodes *metav1.LabelSelector `json:"nodes,omitempty"`
192+
// Networks defines a way to select peers via CIDR blocks.
193+
// This is intended for representing entities that live outside the cluster,
194+
// which can't be selected by pods, namespaces and nodes peers, but note
195+
// that cluster-internal traffic will be checked against the rule as
196+
// well. So if you Allow or Deny traffic to `"0.0.0.0/0"`, that will allow
197+
// or deny all IPv4 pod-to-pod traffic as well. If you don't want that,
198+
// add a rule that Passes all pod traffic before the Networks rule.
199+
//
200+
// Note that because policies are applied after Service VIPs (clusterIPs, externalIPs,
201+
// load balancer IPs) are rewritten to endpoint IPs, a Networks selector cannot match
202+
// such a VIP. For example, a Networks selector that denies traffic to the entire
203+
// service CIDR will not actually block any service traffic.
204+
//
205+
// Each item in Networks should be provided in the CIDR format and should be
206+
// IPv4 or IPv6, for example "10.0.0.0/8" or "fd00::/8".
207+
//
208+
// Networks can have upto 25 CIDRs specified.
209+
//
210+
// Support: Extended
211+
//
212+
// <network-policy-api:experimental>
213+
// +optional
214+
// +kubebuilder:validation:MinItems=1
215+
// +kubebuilder:validation:MaxItems=25
216+
Networks []CIDR `json:"networks,omitempty"`
178217
}
179218

180219
// NamespacedPeer defines a flexible way to select Namespaces in a cluster.
@@ -237,3 +276,13 @@ type NamespacedPodPeer struct {
237276
//
238277
PodSelector metav1.LabelSelector `json:"podSelector"`
239278
}
279+
280+
// CIDR is an IP address range in CIDR notation (for example, "10.0.0.0/8" or "fd00::/8").
281+
// The regex for the IPv4 and IPv6 CIDR range was taken from
282+
// https://blog.markhatton.co.uk/2011/03/15/regular-expressions-for-ip-addresses-cidr-ranges-and-hostnames/
283+
// The resulting regex is an OR of both regexes. IPv4 address embedded in IPv6 addresses are not supported.
284+
// TODO: Change the CIDR's validation regex to use CEL isCIDR() in Kube 1.31 when it is available.
285+
// +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]))$)`
286+
// +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"
287+
// +kubebuilder:validation:MaxLength=43
288+
type CIDR string

apis/v1alpha1/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/experimental/policy.networking.k8s.io_adminnetworkpolicies.yaml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,15 @@ spec:
208208
items:
209209
description: |-
210210
AdminNetworkPolicyEgressPeer defines a peer to allow traffic to.
211+
212+
213+
Note that presence of a Service object with this peer as its backend
214+
has no impact on the behavior of the policy applied to the subject
215+
trying to talk to the Service. It will work in the same way as if the
216+
Service didn't exist since policy is applied after ServiceVIP (clusterIP,
217+
externalIP, loadBalancerIngressIP) is rewritten to the backendIPs.
218+
219+
211220
Exactly one of the selector pointers must be set for a given peer. If a
212221
consumer observes none of its fields are set, they must assume an unknown
213222
option has been specified and fail closed.
@@ -310,6 +319,52 @@ spec:
310319
maxItems: 100
311320
type: array
312321
type: object
322+
networks:
323+
description: |-
324+
Networks defines a way to select peers via CIDR blocks.
325+
This is intended for representing entities that live outside the cluster,
326+
which can't be selected by pods, namespaces and nodes peers, but note
327+
that cluster-internal traffic will be checked against the rule as
328+
well. So if you Allow or Deny traffic to `"0.0.0.0/0"`, that will allow
329+
or deny all IPv4 pod-to-pod traffic as well. If you don't want that,
330+
add a rule that Passes all pod traffic before the Networks rule.
331+
332+
333+
Note that because policies are applied after Service VIPs (clusterIPs, externalIPs,
334+
load balancer IPs) are rewritten to endpoint IPs, a Networks selector cannot match
335+
such a VIP. For example, a Networks selector that denies traffic to the entire
336+
service CIDR will not actually block any service traffic.
337+
338+
339+
Each item in Networks should be provided in the CIDR format and should be
340+
IPv4 or IPv6, for example "10.0.0.0/8" or "fd00::/8".
341+
342+
343+
Networks can have upto 25 CIDRs specified.
344+
345+
346+
Support: Extended
347+
348+
349+
<network-policy-api:experimental>
350+
items:
351+
description: |-
352+
CIDR is an IP address range in CIDR notation (for example, "10.0.0.0/8" or "fd00::/8").
353+
The regex for the IPv4 and IPv6 CIDR range was taken from
354+
https://blog.markhatton.co.uk/2011/03/15/regular-expressions-for-ip-addresses-cidr-ranges-and-hostnames/
355+
The resulting regex is an OR of both regexes. IPv4 address embedded in IPv6 addresses are not supported.
356+
TODO: Change the CIDR's validation regex to use CEL isCIDR() in Kube 1.31 when it is available.
357+
maxLength: 43
358+
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]))$)
359+
type: string
360+
x-kubernetes-validations:
361+
- message: CIDR must be either an IPv4 or IPv6 address.
362+
IPv4 address embedded in IPv6 addresses are not
363+
supported
364+
rule: self.contains(':') != self.contains('.')
365+
maxItems: 25
366+
minItems: 1
367+
type: array
313368
nodes:
314369
description: |-
315370
Nodes defines a way to select a set of nodes in
@@ -576,6 +631,15 @@ spec:
576631
items:
577632
description: |-
578633
AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from.
634+
635+
636+
Note that presence of a Service object with this policy subject as its backend
637+
has no impact on the behavior of the policy applied to the peer
638+
trying to talk to the Service. It will work in the same way as if the
639+
Service didn't exist since policy is applied after ServiceVIP (clusterIP,
640+
externalIP, loadBalancerIngressIP) is rewritten to the backendIPs.
641+
642+
579643
Exactly one of the selector pointers must be set for a given peer. If a
580644
consumer observes none of its fields are set, they must assume an unknown
581645
option has been specified and fail closed.

config/crd/experimental/policy.networking.k8s.io_baselineadminnetworkpolicies.yaml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,15 @@ spec:
199199
items:
200200
description: |-
201201
AdminNetworkPolicyEgressPeer defines a peer to allow traffic to.
202+
203+
204+
Note that presence of a Service object with this peer as its backend
205+
has no impact on the behavior of the policy applied to the subject
206+
trying to talk to the Service. It will work in the same way as if the
207+
Service didn't exist since policy is applied after ServiceVIP (clusterIP,
208+
externalIP, loadBalancerIngressIP) is rewritten to the backendIPs.
209+
210+
202211
Exactly one of the selector pointers must be set for a given peer. If a
203212
consumer observes none of its fields are set, they must assume an unknown
204213
option has been specified and fail closed.
@@ -301,6 +310,52 @@ spec:
301310
maxItems: 100
302311
type: array
303312
type: object
313+
networks:
314+
description: |-
315+
Networks defines a way to select peers via CIDR blocks.
316+
This is intended for representing entities that live outside the cluster,
317+
which can't be selected by pods, namespaces and nodes peers, but note
318+
that cluster-internal traffic will be checked against the rule as
319+
well. So if you Allow or Deny traffic to `"0.0.0.0/0"`, that will allow
320+
or deny all IPv4 pod-to-pod traffic as well. If you don't want that,
321+
add a rule that Passes all pod traffic before the Networks rule.
322+
323+
324+
Note that because policies are applied after Service VIPs (clusterIPs, externalIPs,
325+
load balancer IPs) are rewritten to endpoint IPs, a Networks selector cannot match
326+
such a VIP. For example, a Networks selector that denies traffic to the entire
327+
service CIDR will not actually block any service traffic.
328+
329+
330+
Each item in Networks should be provided in the CIDR format and should be
331+
IPv4 or IPv6, for example "10.0.0.0/8" or "fd00::/8".
332+
333+
334+
Networks can have upto 25 CIDRs specified.
335+
336+
337+
Support: Extended
338+
339+
340+
<network-policy-api:experimental>
341+
items:
342+
description: |-
343+
CIDR is an IP address range in CIDR notation (for example, "10.0.0.0/8" or "fd00::/8").
344+
The regex for the IPv4 and IPv6 CIDR range was taken from
345+
https://blog.markhatton.co.uk/2011/03/15/regular-expressions-for-ip-addresses-cidr-ranges-and-hostnames/
346+
The resulting regex is an OR of both regexes. IPv4 address embedded in IPv6 addresses are not supported.
347+
TODO: Change the CIDR's validation regex to use CEL isCIDR() in Kube 1.31 when it is available.
348+
maxLength: 43
349+
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]))$)
350+
type: string
351+
x-kubernetes-validations:
352+
- message: CIDR must be either an IPv4 or IPv6 address.
353+
IPv4 address embedded in IPv6 addresses are not
354+
supported
355+
rule: self.contains(':') != self.contains('.')
356+
maxItems: 25
357+
minItems: 1
358+
type: array
304359
nodes:
305360
description: |-
306361
Nodes defines a way to select a set of nodes in
@@ -564,6 +619,15 @@ spec:
564619
items:
565620
description: |-
566621
AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from.
622+
623+
624+
Note that presence of a Service object with this policy subject as its backend
625+
has no impact on the behavior of the policy applied to the peer
626+
trying to talk to the Service. It will work in the same way as if the
627+
Service didn't exist since policy is applied after ServiceVIP (clusterIP,
628+
externalIP, loadBalancerIngressIP) is rewritten to the backendIPs.
629+
630+
567631
Exactly one of the selector pointers must be set for a given peer. If a
568632
consumer observes none of its fields are set, they must assume an unknown
569633
option has been specified and fail closed.

config/crd/standard/policy.networking.k8s.io_adminnetworkpolicies.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,15 @@ spec:
198198
items:
199199
description: |-
200200
AdminNetworkPolicyEgressPeer defines a peer to allow traffic to.
201+
202+
203+
Note that presence of a Service object with this peer as its backend
204+
has no impact on the behavior of the policy applied to the subject
205+
trying to talk to the Service. It will work in the same way as if the
206+
Service didn't exist since policy is applied after ServiceVIP (clusterIP,
207+
externalIP, loadBalancerIngressIP) is rewritten to the backendIPs.
208+
209+
201210
Exactly one of the selector pointers must be set for a given peer. If a
202211
consumer observes none of its fields are set, they must assume an unknown
203212
option has been specified and fail closed.
@@ -445,6 +454,15 @@ spec:
445454
items:
446455
description: |-
447456
AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from.
457+
458+
459+
Note that presence of a Service object with this policy subject as its backend
460+
has no impact on the behavior of the policy applied to the peer
461+
trying to talk to the Service. It will work in the same way as if the
462+
Service didn't exist since policy is applied after ServiceVIP (clusterIP,
463+
externalIP, loadBalancerIngressIP) is rewritten to the backendIPs.
464+
465+
448466
Exactly one of the selector pointers must be set for a given peer. If a
449467
consumer observes none of its fields are set, they must assume an unknown
450468
option has been specified and fail closed.

0 commit comments

Comments
 (0)