diff --git a/apis/flowcollector/v1beta1/flowcollector_types.go b/apis/flowcollector/v1beta1/flowcollector_types.go index e413ccbd0..bdbf76a6f 100644 --- a/apis/flowcollector/v1beta1/flowcollector_types.go +++ b/apis/flowcollector/v1beta1/flowcollector_types.go @@ -19,6 +19,7 @@ import ( ascv2 "k8s.io/api/autoscaling/v2" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" ) // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. @@ -166,6 +167,60 @@ type EBPFMetrics struct { Enable *bool `json:"enable,omitempty"` } +// `EBPFFlowFilter` defines the desired eBPF agent configuration regarding flow filtering +type EBPFFlowFilter struct { + // Set `enable` to `true` to enable eBPF flow filtering feature. + Enable *bool `json:"enable,omitempty"` + + // CIDR defines the IP CIDR to filter flows by. + // Example: 10.10.10.0/24 or 100:100:100:100::/64 + CIDR string `json:"cidr,omitempty"` + + // Action defines the action to perform on the flows that match the filter. + // +kubebuilder:validation:Enum:="Accept";"Reject" + Action string `json:"action,omitempty"` + + // Protocol defines the protocol to filter flows by. + // +kubebuilder:validation:Enum:="TCP";"UDP";"ICMP";"ICMPv6";"SCTP" + // +optional + Protocol string `json:"protocol,omitempty"` + + // Direction defines the direction to filter flows by. + // +kubebuilder:validation:Enum:="Ingress";"Egress" + // +optional + Direction string `json:"direction,omitempty"` + + // SourcePorts defines the source ports to filter flows by. + // To filter a single port, set a single port as an integer value. For example sourcePorts: 80. + // To filter a range of ports, use a "start-end" range, string format. For example sourcePorts: "80-100". + // +optional + SourcePorts intstr.IntOrString `json:"sourcePorts,omitempty"` + + // DestPorts defines the destination ports to filter flows by. + // To filter a single port, set a single port as an integer value. For example destPorts: 80. + // To filter a range of ports, use a "start-end" range, string format. For example destPorts: "80-100". + // +optional + DestPorts intstr.IntOrString `json:"destPorts,omitempty"` + + // Ports defines the ports to filter flows by. it can be user for either source or destination ports. + // To filter a single port, set a single port as an integer value. For example ports: 80. + // To filter a range of ports, use a "start-end" range, string format. For example ports: "80-10 + Ports intstr.IntOrString `json:"ports,omitempty"` + + // PeerIP defines the IP address to filter flows by. + // Example: 10.10.10.10 + // +optional + PeerIP string `json:"peerIP,omitempty"` + + // ICMPType defines the ICMP type to filter flows by. + // +optional + ICMPType *int `json:"icmpType,omitempty"` + + // ICMPCode defines the ICMP code to filter flows by. + // +optional + ICMPCode *int `json:"icmpCode,omitempty"` +} + // `FlowCollectorEBPF` defines a FlowCollector that uses eBPF to collect the flows information type FlowCollectorEBPF struct { // Important: Run "make generate" to regenerate code after modifying this file @@ -251,6 +306,10 @@ type FlowCollectorEBPF struct { // `metrics` defines the eBPF agent configuration regarding metrics // +optional Metrics EBPFMetrics `json:"metrics,omitempty"` + + // `flowFilter` defines the eBPF agent configuration regarding flow filtering + // +optional + FlowFilter *EBPFFlowFilter `json:"flowFilter,omitempty"` } // `FlowCollectorKafka` defines the desired Kafka config of FlowCollector diff --git a/apis/flowcollector/v1beta1/zz_generated.conversion.go b/apis/flowcollector/v1beta1/zz_generated.conversion.go index ea755fbda..c83793e95 100644 --- a/apis/flowcollector/v1beta1/zz_generated.conversion.go +++ b/apis/flowcollector/v1beta1/zz_generated.conversion.go @@ -78,6 +78,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddGeneratedConversionFunc((*EBPFFlowFilter)(nil), (*v1beta2.EBPFFlowFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_EBPFFlowFilter_To_v1beta2_EBPFFlowFilter(a.(*EBPFFlowFilter), b.(*v1beta2.EBPFFlowFilter), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.EBPFFlowFilter)(nil), (*EBPFFlowFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_EBPFFlowFilter_To_v1beta1_EBPFFlowFilter(a.(*v1beta2.EBPFFlowFilter), b.(*EBPFFlowFilter), scope) + }); err != nil { + return err + } if err := s.AddGeneratedConversionFunc((*EBPFMetrics)(nil), (*v1beta2.EBPFMetrics)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta1_EBPFMetrics_To_v1beta2_EBPFMetrics(a.(*EBPFMetrics), b.(*v1beta2.EBPFMetrics), scope) }); err != nil { @@ -445,6 +455,46 @@ func Convert_v1beta2_ConsolePluginPortConfig_To_v1beta1_ConsolePluginPortConfig( return autoConvert_v1beta2_ConsolePluginPortConfig_To_v1beta1_ConsolePluginPortConfig(in, out, s) } +func autoConvert_v1beta1_EBPFFlowFilter_To_v1beta2_EBPFFlowFilter(in *EBPFFlowFilter, out *v1beta2.EBPFFlowFilter, s conversion.Scope) error { + out.Enable = (*bool)(unsafe.Pointer(in.Enable)) + out.CIDR = in.CIDR + out.Action = in.Action + out.Protocol = in.Protocol + out.Direction = in.Direction + out.SourcePorts = in.SourcePorts + out.DestPorts = in.DestPorts + out.Ports = in.Ports + out.PeerIP = in.PeerIP + out.ICMPType = (*int)(unsafe.Pointer(in.ICMPType)) + out.ICMPCode = (*int)(unsafe.Pointer(in.ICMPCode)) + return nil +} + +// Convert_v1beta1_EBPFFlowFilter_To_v1beta2_EBPFFlowFilter is an autogenerated conversion function. +func Convert_v1beta1_EBPFFlowFilter_To_v1beta2_EBPFFlowFilter(in *EBPFFlowFilter, out *v1beta2.EBPFFlowFilter, s conversion.Scope) error { + return autoConvert_v1beta1_EBPFFlowFilter_To_v1beta2_EBPFFlowFilter(in, out, s) +} + +func autoConvert_v1beta2_EBPFFlowFilter_To_v1beta1_EBPFFlowFilter(in *v1beta2.EBPFFlowFilter, out *EBPFFlowFilter, s conversion.Scope) error { + out.Enable = (*bool)(unsafe.Pointer(in.Enable)) + out.CIDR = in.CIDR + out.Action = in.Action + out.Protocol = in.Protocol + out.Direction = in.Direction + out.SourcePorts = in.SourcePorts + out.DestPorts = in.DestPorts + out.Ports = in.Ports + out.PeerIP = in.PeerIP + out.ICMPType = (*int)(unsafe.Pointer(in.ICMPType)) + out.ICMPCode = (*int)(unsafe.Pointer(in.ICMPCode)) + return nil +} + +// Convert_v1beta2_EBPFFlowFilter_To_v1beta1_EBPFFlowFilter is an autogenerated conversion function. +func Convert_v1beta2_EBPFFlowFilter_To_v1beta1_EBPFFlowFilter(in *v1beta2.EBPFFlowFilter, out *EBPFFlowFilter, s conversion.Scope) error { + return autoConvert_v1beta2_EBPFFlowFilter_To_v1beta1_EBPFFlowFilter(in, out, s) +} + func autoConvert_v1beta1_EBPFMetrics_To_v1beta2_EBPFMetrics(in *EBPFMetrics, out *v1beta2.EBPFMetrics, s conversion.Scope) error { if err := Convert_v1beta1_MetricsServerConfig_To_v1beta2_MetricsServerConfig(&in.Server, &out.Server, s); err != nil { return err @@ -611,6 +661,7 @@ func autoConvert_v1beta1_FlowCollectorEBPF_To_v1beta2_FlowCollectorEBPF(in *Flow if err := Convert_v1beta1_EBPFMetrics_To_v1beta2_EBPFMetrics(&in.Metrics, &out.Metrics, s); err != nil { return err } + out.FlowFilter = (*v1beta2.EBPFFlowFilter)(unsafe.Pointer(in.FlowFilter)) return nil } @@ -630,6 +681,7 @@ func autoConvert_v1beta2_FlowCollectorEBPF_To_v1beta1_FlowCollectorEBPF(in *v1be if err := Convert_v1beta2_EBPFMetrics_To_v1beta1_EBPFMetrics(&in.Metrics, &out.Metrics, s); err != nil { return err } + out.FlowFilter = (*EBPFFlowFilter)(unsafe.Pointer(in.FlowFilter)) return nil } diff --git a/apis/flowcollector/v1beta1/zz_generated.deepcopy.go b/apis/flowcollector/v1beta1/zz_generated.deepcopy.go index c60245ce8..6a431d32d 100644 --- a/apis/flowcollector/v1beta1/zz_generated.deepcopy.go +++ b/apis/flowcollector/v1beta1/zz_generated.deepcopy.go @@ -122,6 +122,39 @@ func (in *DebugConfig) DeepCopy() *DebugConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EBPFFlowFilter) DeepCopyInto(out *EBPFFlowFilter) { + *out = *in + if in.Enable != nil { + in, out := &in.Enable, &out.Enable + *out = new(bool) + **out = **in + } + out.SourcePorts = in.SourcePorts + out.DestPorts = in.DestPorts + out.Ports = in.Ports + if in.ICMPType != nil { + in, out := &in.ICMPType, &out.ICMPType + *out = new(int) + **out = **in + } + if in.ICMPCode != nil { + in, out := &in.ICMPCode, &out.ICMPCode + *out = new(int) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EBPFFlowFilter. +func (in *EBPFFlowFilter) DeepCopy() *EBPFFlowFilter { + if in == nil { + return nil + } + out := new(EBPFFlowFilter) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EBPFMetrics) DeepCopyInto(out *EBPFMetrics) { *out = *in @@ -303,6 +336,11 @@ func (in *FlowCollectorEBPF) DeepCopyInto(out *FlowCollectorEBPF) { copy(*out, *in) } in.Metrics.DeepCopyInto(&out.Metrics) + if in.FlowFilter != nil { + in, out := &in.FlowFilter, &out.FlowFilter + *out = new(EBPFFlowFilter) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlowCollectorEBPF. diff --git a/apis/flowcollector/v1beta2/flowcollector_types.go b/apis/flowcollector/v1beta2/flowcollector_types.go index 9cc6c5b4a..8d62ac3d6 100644 --- a/apis/flowcollector/v1beta2/flowcollector_types.go +++ b/apis/flowcollector/v1beta2/flowcollector_types.go @@ -19,6 +19,7 @@ import ( ascv2 "k8s.io/api/autoscaling/v2" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" ) // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. @@ -173,6 +174,60 @@ type EBPFMetrics struct { Enable *bool `json:"enable,omitempty"` } +// `EBPFFlowFilter` defines the desired eBPF agent configuration regarding flow filtering +type EBPFFlowFilter struct { + // Set `enable` to `true` to enable eBPF flow filtering feature. + Enable *bool `json:"enable,omitempty"` + + // CIDR defines the IP CIDR to filter flows by. + // Example: 10.10.10.0/24 or 100:100:100:100::/64 + CIDR string `json:"cidr,omitempty"` + + // Action defines the action to perform on the flows that match the filter. + // +kubebuilder:validation:Enum:="Accept";"Reject" + Action string `json:"action,omitempty"` + + // Protocol defines the protocol to filter flows by. + // +kubebuilder:validation:Enum:="TCP";"UDP";"ICMP";"ICMPv6";"SCTP" + // +optional + Protocol string `json:"protocol,omitempty"` + + // Direction defines the direction to filter flows by. + // +kubebuilder:validation:Enum:="Ingress";"Egress" + // +optional + Direction string `json:"direction,omitempty"` + + // SourcePorts defines the source ports to filter flows by. + // To filter a single port, set a single port as an integer value. For example sourcePorts: 80. + // To filter a range of ports, use a "start-end" range, string format. For example sourcePorts: "80-100". + // +optional + SourcePorts intstr.IntOrString `json:"sourcePorts,omitempty"` + + // DestPorts defines the destination ports to filter flows by. + // To filter a single port, set a single port as an integer value. For example destPorts: 80. + // To filter a range of ports, use a "start-end" range, string format. For example destPorts: "80-100". + // +optional + DestPorts intstr.IntOrString `json:"destPorts,omitempty"` + + // Ports defines the ports to filter flows by. it can be user for either source or destination ports. + // To filter a single port, set a single port as an integer value. For example ports: 80. + // To filter a range of ports, use a "start-end" range, string format. For example ports: "80-10 + Ports intstr.IntOrString `json:"ports,omitempty"` + + // PeerIP defines the IP address to filter flows by. + // Example: 10.10.10.10 + // +optional + PeerIP string `json:"peerIP,omitempty"` + + // ICMPType defines the ICMP type to filter flows by. + // +optional + ICMPType *int `json:"icmpType,omitempty"` + + // ICMPCode defines the ICMP code to filter flows by. + // +optional + ICMPCode *int `json:"icmpCode,omitempty"` +} + // `FlowCollectorEBPF` defines a FlowCollector that uses eBPF to collect the flows information type FlowCollectorEBPF struct { // Important: Run "make generate" to regenerate code after modifying this file @@ -258,6 +313,10 @@ type FlowCollectorEBPF struct { // `metrics` defines the eBPF agent configuration regarding metrics // +optional Metrics EBPFMetrics `json:"metrics,omitempty"` + + // `flowFilter` defines the eBPF agent configuration regarding flow filtering + // +optional + FlowFilter *EBPFFlowFilter `json:"flowFilter,omitempty"` } // `FlowCollectorKafka` defines the desired Kafka config of FlowCollector diff --git a/apis/flowcollector/v1beta2/zz_generated.deepcopy.go b/apis/flowcollector/v1beta2/zz_generated.deepcopy.go index 01d31f194..604a97823 100644 --- a/apis/flowcollector/v1beta2/zz_generated.deepcopy.go +++ b/apis/flowcollector/v1beta2/zz_generated.deepcopy.go @@ -295,6 +295,39 @@ func (in *ConsolePluginPortConfig) DeepCopy() *ConsolePluginPortConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EBPFFlowFilter) DeepCopyInto(out *EBPFFlowFilter) { + *out = *in + if in.Enable != nil { + in, out := &in.Enable, &out.Enable + *out = new(bool) + **out = **in + } + out.SourcePorts = in.SourcePorts + out.DestPorts = in.DestPorts + out.Ports = in.Ports + if in.ICMPType != nil { + in, out := &in.ICMPType, &out.ICMPType + *out = new(int) + **out = **in + } + if in.ICMPCode != nil { + in, out := &in.ICMPCode, &out.ICMPCode + *out = new(int) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EBPFFlowFilter. +func (in *EBPFFlowFilter) DeepCopy() *EBPFFlowFilter { + if in == nil { + return nil + } + out := new(EBPFFlowFilter) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EBPFMetrics) DeepCopyInto(out *EBPFMetrics) { *out = *in @@ -475,6 +508,11 @@ func (in *FlowCollectorEBPF) DeepCopyInto(out *FlowCollectorEBPF) { copy(*out, *in) } in.Metrics.DeepCopyInto(&out.Metrics) + if in.FlowFilter != nil { + in, out := &in.FlowFilter, &out.FlowFilter + *out = new(EBPFFlowFilter) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlowCollectorEBPF. diff --git a/bundle/manifests/flows.netobserv.io_flowcollectors.yaml b/bundle/manifests/flows.netobserv.io_flowcollectors.yaml index 8aeb17d06..c81daa64d 100644 --- a/bundle/manifests/flows.netobserv.io_flowcollectors.yaml +++ b/bundle/manifests/flows.netobserv.io_flowcollectors.yaml @@ -146,6 +146,84 @@ spec: - FlowRTT type: string type: array + flowFilter: + description: '`flowFilter` defines the eBPF agent configuration + regarding flow filtering' + properties: + action: + description: Action defines the action to perform on the + flows that match the filter. + enum: + - Accept + - Reject + type: string + cidr: + description: |- + CIDR defines the IP CIDR to filter flows by. + Example: 10.10.10.0/24 or 100:100:100:100::/64 + type: string + destPorts: + anyOf: + - type: integer + - type: string + description: |- + DestPorts defines the destination ports to filter flows by. + To filter a single port, set a single port as an integer value. For example destPorts: 80. + To filter a range of ports, use a "start-end" range, string format. For example destPorts: "80-100". + x-kubernetes-int-or-string: true + direction: + description: Direction defines the direction to filter + flows by. + enum: + - Ingress + - Egress + type: string + enable: + description: Set `enable` to `true` to enable eBPF flow + filtering feature. + type: boolean + icmpCode: + description: ICMPCode defines the ICMP code to filter + flows by. + type: integer + icmpType: + description: ICMPType defines the ICMP type to filter + flows by. + type: integer + peerIP: + description: |- + PeerIP defines the IP address to filter flows by. + Example: 10.10.10.10 + type: string + ports: + anyOf: + - type: integer + - type: string + description: |- + Ports defines the ports to filter flows by. it can be user for either source or destination ports. + To filter a single port, set a single port as an integer value. For example ports: 80. + To filter a range of ports, use a "start-end" range, string format. For example ports: "80-10 + x-kubernetes-int-or-string: true + protocol: + description: Protocol defines the protocol to filter flows + by. + enum: + - TCP + - UDP + - ICMP + - ICMPv6 + - SCTP + type: string + sourcePorts: + anyOf: + - type: integer + - type: string + description: |- + SourcePorts defines the source ports to filter flows by. + To filter a single port, set a single port as an integer value. For example sourcePorts: 80. + To filter a range of ports, use a "start-end" range, string format. For example sourcePorts: "80-100". + x-kubernetes-int-or-string: true + type: object imagePullPolicy: default: IfNotPresent description: '`imagePullPolicy` is the Kubernetes pull policy @@ -2889,6 +2967,84 @@ spec: - FlowRTT type: string type: array + flowFilter: + description: '`flowFilter` defines the eBPF agent configuration + regarding flow filtering' + properties: + action: + description: Action defines the action to perform on the + flows that match the filter. + enum: + - Accept + - Reject + type: string + cidr: + description: |- + CIDR defines the IP CIDR to filter flows by. + Example: 10.10.10.0/24 or 100:100:100:100::/64 + type: string + destPorts: + anyOf: + - type: integer + - type: string + description: |- + DestPorts defines the destination ports to filter flows by. + To filter a single port, set a single port as an integer value. For example destPorts: 80. + To filter a range of ports, use a "start-end" range, string format. For example destPorts: "80-100". + x-kubernetes-int-or-string: true + direction: + description: Direction defines the direction to filter + flows by. + enum: + - Ingress + - Egress + type: string + enable: + description: Set `enable` to `true` to enable eBPF flow + filtering feature. + type: boolean + icmpCode: + description: ICMPCode defines the ICMP code to filter + flows by. + type: integer + icmpType: + description: ICMPType defines the ICMP type to filter + flows by. + type: integer + peerIP: + description: |- + PeerIP defines the IP address to filter flows by. + Example: 10.10.10.10 + type: string + ports: + anyOf: + - type: integer + - type: string + description: |- + Ports defines the ports to filter flows by. it can be user for either source or destination ports. + To filter a single port, set a single port as an integer value. For example ports: 80. + To filter a range of ports, use a "start-end" range, string format. For example ports: "80-10 + x-kubernetes-int-or-string: true + protocol: + description: Protocol defines the protocol to filter flows + by. + enum: + - TCP + - UDP + - ICMP + - ICMPv6 + - SCTP + type: string + sourcePorts: + anyOf: + - type: integer + - type: string + description: |- + SourcePorts defines the source ports to filter flows by. + To filter a single port, set a single port as an integer value. For example sourcePorts: 80. + To filter a range of ports, use a "start-end" range, string format. For example sourcePorts: "80-100". + x-kubernetes-int-or-string: true + type: object imagePullPolicy: default: IfNotPresent description: '`imagePullPolicy` is the Kubernetes pull policy diff --git a/bundle/manifests/netobserv-operator.clusterserviceversion.yaml b/bundle/manifests/netobserv-operator.clusterserviceversion.yaml index 44d285a55..75ad03082 100644 --- a/bundle/manifests/netobserv-operator.clusterserviceversion.yaml +++ b/bundle/manifests/netobserv-operator.clusterserviceversion.yaml @@ -487,6 +487,9 @@ spec: - path: agent.ebpf.advanced x-descriptors: - urn:alm:descriptor:com.tectonic.ui:hidden + - path: agent.ebpf.flowFilter + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:hidden - description: to use Kafka as a broker as part of the flow collection pipeline. displayName: Kafka configuration path: kafka diff --git a/config/crd/bases/flows.netobserv.io_flowcollectors.yaml b/config/crd/bases/flows.netobserv.io_flowcollectors.yaml index 0d4432e15..f3863088b 100644 --- a/config/crd/bases/flows.netobserv.io_flowcollectors.yaml +++ b/config/crd/bases/flows.netobserv.io_flowcollectors.yaml @@ -130,6 +130,77 @@ spec: - FlowRTT type: string type: array + flowFilter: + description: '`flowFilter` defines the eBPF agent configuration regarding flow filtering' + properties: + action: + description: Action defines the action to perform on the flows that match the filter. + enum: + - Accept + - Reject + type: string + cidr: + description: |- + CIDR defines the IP CIDR to filter flows by. + Example: 10.10.10.0/24 or 100:100:100:100::/64 + type: string + destPorts: + anyOf: + - type: integer + - type: string + description: |- + DestPorts defines the destination ports to filter flows by. + To filter a single port, set a single port as an integer value. For example destPorts: 80. + To filter a range of ports, use a "start-end" range, string format. For example destPorts: "80-100". + x-kubernetes-int-or-string: true + direction: + description: Direction defines the direction to filter flows by. + enum: + - Ingress + - Egress + type: string + enable: + description: Set `enable` to `true` to enable eBPF flow filtering feature. + type: boolean + icmpCode: + description: ICMPCode defines the ICMP code to filter flows by. + type: integer + icmpType: + description: ICMPType defines the ICMP type to filter flows by. + type: integer + peerIP: + description: |- + PeerIP defines the IP address to filter flows by. + Example: 10.10.10.10 + type: string + ports: + anyOf: + - type: integer + - type: string + description: |- + Ports defines the ports to filter flows by. it can be user for either source or destination ports. + To filter a single port, set a single port as an integer value. For example ports: 80. + To filter a range of ports, use a "start-end" range, string format. For example ports: "80-10 + x-kubernetes-int-or-string: true + protocol: + description: Protocol defines the protocol to filter flows by. + enum: + - TCP + - UDP + - ICMP + - ICMPv6 + - SCTP + type: string + sourcePorts: + anyOf: + - type: integer + - type: string + description: |- + SourcePorts defines the source ports to filter flows by. + To filter a single port, set a single port as an integer value. For example sourcePorts: 80. + To filter a range of ports, use a "start-end" range, string format. For example sourcePorts: "80-100". + x-kubernetes-int-or-string: true + type: object imagePullPolicy: default: IfNotPresent description: '`imagePullPolicy` is the Kubernetes pull policy for the image defined above' @@ -2686,6 +2757,77 @@ spec: - FlowRTT type: string type: array + flowFilter: + description: '`flowFilter` defines the eBPF agent configuration regarding flow filtering' + properties: + action: + description: Action defines the action to perform on the flows that match the filter. + enum: + - Accept + - Reject + type: string + cidr: + description: |- + CIDR defines the IP CIDR to filter flows by. + Example: 10.10.10.0/24 or 100:100:100:100::/64 + type: string + destPorts: + anyOf: + - type: integer + - type: string + description: |- + DestPorts defines the destination ports to filter flows by. + To filter a single port, set a single port as an integer value. For example destPorts: 80. + To filter a range of ports, use a "start-end" range, string format. For example destPorts: "80-100". + x-kubernetes-int-or-string: true + direction: + description: Direction defines the direction to filter flows by. + enum: + - Ingress + - Egress + type: string + enable: + description: Set `enable` to `true` to enable eBPF flow filtering feature. + type: boolean + icmpCode: + description: ICMPCode defines the ICMP code to filter flows by. + type: integer + icmpType: + description: ICMPType defines the ICMP type to filter flows by. + type: integer + peerIP: + description: |- + PeerIP defines the IP address to filter flows by. + Example: 10.10.10.10 + type: string + ports: + anyOf: + - type: integer + - type: string + description: |- + Ports defines the ports to filter flows by. it can be user for either source or destination ports. + To filter a single port, set a single port as an integer value. For example ports: 80. + To filter a range of ports, use a "start-end" range, string format. For example ports: "80-10 + x-kubernetes-int-or-string: true + protocol: + description: Protocol defines the protocol to filter flows by. + enum: + - TCP + - UDP + - ICMP + - ICMPv6 + - SCTP + type: string + sourcePorts: + anyOf: + - type: integer + - type: string + description: |- + SourcePorts defines the source ports to filter flows by. + To filter a single port, set a single port as an integer value. For example sourcePorts: 80. + To filter a range of ports, use a "start-end" range, string format. For example sourcePorts: "80-100". + x-kubernetes-int-or-string: true + type: object imagePullPolicy: default: IfNotPresent description: '`imagePullPolicy` is the Kubernetes pull policy for the image defined above' diff --git a/config/csv/bases/netobserv-operator.clusterserviceversion.yaml b/config/csv/bases/netobserv-operator.clusterserviceversion.yaml index 6d02689fa..d7adffeed 100644 --- a/config/csv/bases/netobserv-operator.clusterserviceversion.yaml +++ b/config/csv/bases/netobserv-operator.clusterserviceversion.yaml @@ -85,6 +85,9 @@ spec: - path: agent.ebpf.advanced x-descriptors: - urn:alm:descriptor:com.tectonic.ui:hidden + - path: agent.ebpf.flowFilter + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:hidden # KAFKA - description: to use Kafka as a broker as part of the flow collection pipeline. displayName: Kafka configuration diff --git a/config/samples/flows_v1beta2_flowcollector.yaml b/config/samples/flows_v1beta2_flowcollector.yaml index abe9f7bb3..5921d3486 100644 --- a/config/samples/flows_v1beta2_flowcollector.yaml +++ b/config/samples/flows_v1beta2_flowcollector.yaml @@ -22,6 +22,12 @@ spec: interfaces: [] excludeInterfaces: ["lo"] kafkaBatchSize: 1048576 + #flowFilter: + # action: Accept + # cidr: 0.0.0.0/0 + # protocol: UDP + # sourcePorts: 53 + # enable: true metrics: enable: false server: diff --git a/controllers/ebpf/agent_controller.go b/controllers/ebpf/agent_controller.go index 51d70f07f..7d364356a 100644 --- a/controllers/ebpf/agent_controller.go +++ b/controllers/ebpf/agent_controller.go @@ -21,6 +21,7 @@ import ( "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/log" ) @@ -60,6 +61,20 @@ const ( envMetricPrefix = "METRICS_PREFIX" envMetricsTLSCertPath = "METRICS_TLS_CERT_PATH" envMetricsTLSKeyPath = "METRICS_TLS_KEY_PATH" + envEnableFlowFilter = "ENABLE_FLOW_FILTER" + envFlowFilterIPCIDR = "FLOW_FILTER_IP_CIDR" + envFlowFilterAction = "FLOW_FILTER_ACTION" + envFlowFilterDirection = "FLOW_FILTER_DIRECTION" + envFlowFilterProtocol = "FLOW_FILTER_PROTOCOL" + envFlowFilterSourcePort = "FLOW_FILTER_SOURCE_PORT" + envFlowFilterDestPort = "FLOW_FILTER_DESTINATION_PORT" + envFlowFilterPort = "FLOW_FILTER_PORT" + envFlowFilterSourcePortRange = "FLOW_FILTER_SOURCE_PORT_RANGE" + envFlowFilterDestPortRange = "FLOW_FILTER_DESTINATION_PORT_RANGE" + envFlowFilterPortRange = "FLOW_FILTER_PORT_RANGE" + envFlowFilterICMPType = "FLOW_FILTER_ICMP_TYPE" + envFlowFilterICMPCode = "FLOW_FILTER_ICMP_CODE" + envFlowFilterPeerIPAddress = "FLOW_FILTER_PEER_IP" envListSeparator = "," ) @@ -394,9 +409,89 @@ func (c *AgentController) envConfig(ctx context.Context, coll *flowslatest.FlowC Value: strconv.Itoa(int(*advancedConfig.Port)), }) } + + if helper.IsEBFPFlowFilterEnabled(&coll.Spec.Agent.EBPF) { + config = append(config, corev1.EnvVar{Name: envEnableFlowFilter, Value: "true"}) + + config = append(config, c.configureFlowFilter(coll.Spec.Agent.EBPF.FlowFilter, config)...) + } + return config, nil } +func (c *AgentController) configureFlowFilter(filter *flowslatest.EBPFFlowFilter, config []corev1.EnvVar) []corev1.EnvVar { + if filter.CIDR != "" { + config = append(config, corev1.EnvVar{Name: envFlowFilterIPCIDR, + Value: filter.CIDR, + }) + } + if filter.Action != "" { + config = append(config, corev1.EnvVar{Name: envFlowFilterAction, + Value: filter.Action, + }) + } + if filter.Direction != "" { + config = append(config, corev1.EnvVar{Name: envFlowFilterDirection, + Value: filter.Direction, + }) + } + if filter.Protocol != "" { + config = append(config, corev1.EnvVar{Name: envFlowFilterProtocol, + Value: filter.Protocol, + }) + switch filter.Protocol { + case "TCP", "UDP", "SCTP": + if filter.SourcePorts.Type == intstr.String { + config = append(config, corev1.EnvVar{Name: envFlowFilterSourcePortRange, + Value: filter.SourcePorts.String(), + }) + } + if filter.SourcePorts.Type == intstr.Int { + config = append(config, corev1.EnvVar{Name: envFlowFilterSourcePort, + Value: strconv.Itoa(filter.SourcePorts.IntValue()), + }) + } + if filter.DestPorts.Type == intstr.String { + config = append(config, corev1.EnvVar{Name: envFlowFilterDestPortRange, + Value: filter.DestPorts.String(), + }) + } + if filter.DestPorts.Type == intstr.Int { + config = append(config, corev1.EnvVar{Name: envFlowFilterDestPort, + Value: strconv.Itoa(filter.DestPorts.IntValue()), + }) + } + if filter.Ports.Type == intstr.String { + config = append(config, corev1.EnvVar{Name: envFlowFilterPortRange, + Value: filter.Ports.String(), + }) + } + if filter.Ports.Type == intstr.Int { + config = append(config, corev1.EnvVar{Name: envFlowFilterPort, + Value: strconv.Itoa(filter.Ports.IntValue()), + }) + } + + case "ICMP", "ICMPv6": + if *filter.ICMPType != 0 { + config = append(config, corev1.EnvVar{Name: envFlowFilterICMPType, + Value: strconv.Itoa(*filter.ICMPType), + }) + } + if *filter.ICMPCode != 0 { + config = append(config, corev1.EnvVar{Name: envFlowFilterICMPCode, + Value: strconv.Itoa(*filter.ICMPCode)}) + } + } + } + + if filter.PeerIP != "" { + config = append(config, corev1.EnvVar{Name: envFlowFilterPeerIPAddress, + Value: filter.PeerIP}) + } + return config +} + func (c *AgentController) securityContext(coll *flowslatest.FlowCollector) *corev1.SecurityContext { if coll.Spec.Agent.EBPF.Privileged { return &corev1.SecurityContext{ diff --git a/docs/FlowCollector.md b/docs/FlowCollector.md index de4a394f6..4088230fd 100644 --- a/docs/FlowCollector.md +++ b/docs/FlowCollector.md @@ -285,6 +285,13 @@ If the `spec.agent.ebpf.privileged` parameter is not set, an error is reported.< - `FlowRTT` [unsupported (*)]: enable flow latency (RTT) calculations in the eBPF agent during TCP handshakes. This feature better works with `sampling` set to 1.

false + + flowFilter + object + + `flowFilter` defines the eBPF agent configuration regarding flow filtering
+ + false imagePullPolicy enum @@ -399,6 +406,117 @@ in edge debug or support scenarios.
+### FlowCollector.spec.agent.ebpf.flowFilter +[↩ Parent](#flowcollectorspecagentebpf) + + + +`flowFilter` defines the eBPF agent configuration regarding flow filtering + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
actionenum + Action defines the action to perform on the flows that match the filter.
+
+ Enum: Accept, Reject
+
false
cidrstring + CIDR defines the IP CIDR to filter flows by. +Example: 10.10.10.0/24 or 100:100:100:100::/64
+
false
destPortsint or string + DestPorts defines the destination ports to filter flows by. +To filter a single port, set a single port as an integer value. For example destPorts: 80. +To filter a range of ports, use a "start-end" range, string format. For example destPorts: "80-100".
+
false
directionenum + Direction defines the direction to filter flows by.
+
+ Enum: Ingress, Egress
+
false
enableboolean + Set `enable` to `true` to enable eBPF flow filtering feature.
+
false
icmpCodeinteger + ICMPCode defines the ICMP code to filter flows by.
+
false
icmpTypeinteger + ICMPType defines the ICMP type to filter flows by.
+
false
peerIPstring + PeerIP defines the IP address to filter flows by. +Example: 10.10.10.10
+
false
portsint or string + Ports defines the ports to filter flows by. it can be user for either source or destination ports. +To filter a single port, set a single port as an integer value. For example ports: 80. +To filter a range of ports, use a "start-end" range, string format. For example ports: "80-10
+
false
protocolenum + Protocol defines the protocol to filter flows by.
+
+ Enum: TCP, UDP, ICMP, ICMPv6, SCTP
+
false
sourcePortsint or string + SourcePorts defines the source ports to filter flows by. +To filter a single port, set a single port as an integer value. For example sourcePorts: 80. +To filter a range of ports, use a "start-end" range, string format. For example sourcePorts: "80-100".
+
false
+ + ### FlowCollector.spec.agent.ebpf.metrics [↩ Parent](#flowcollectorspecagentebpf) @@ -5480,6 +5598,13 @@ If the `spec.agent.ebpf.privileged` parameter is not set, an error is reported.< - `FlowRTT`: enable flow latency (RTT) calculations in the eBPF agent during TCP handshakes. This feature better works with `sampling` set to 1.

false + + flowFilter + object + + `flowFilter` defines the eBPF agent configuration regarding flow filtering
+ + false imagePullPolicy enum @@ -6980,6 +7105,117 @@ If specified, the pod's scheduling constraints. For documentation, refer to http +### FlowCollector.spec.agent.ebpf.flowFilter +[↩ Parent](#flowcollectorspecagentebpf-1) + + + +`flowFilter` defines the eBPF agent configuration regarding flow filtering + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
actionenum + Action defines the action to perform on the flows that match the filter.
+
+ Enum: Accept, Reject
+
false
cidrstring + CIDR defines the IP CIDR to filter flows by. +Example: 10.10.10.0/24 or 100:100:100:100::/64
+
false
destPortsint or string + DestPorts defines the destination ports to filter flows by. +To filter a single port, set a single port as an integer value. For example destPorts: 80. +To filter a range of ports, use a "start-end" range, string format. For example destPorts: "80-100".
+
false
directionenum + Direction defines the direction to filter flows by.
+
+ Enum: Ingress, Egress
+
false
enableboolean + Set `enable` to `true` to enable eBPF flow filtering feature.
+
false
icmpCodeinteger + ICMPCode defines the ICMP code to filter flows by.
+
false
icmpTypeinteger + ICMPType defines the ICMP type to filter flows by.
+
false
peerIPstring + PeerIP defines the IP address to filter flows by. +Example: 10.10.10.10
+
false
portsint or string + Ports defines the ports to filter flows by. it can be user for either source or destination ports. +To filter a single port, set a single port as an integer value. For example ports: 80. +To filter a range of ports, use a "start-end" range, string format. For example ports: "80-10
+
false
protocolenum + Protocol defines the protocol to filter flows by.
+
+ Enum: TCP, UDP, ICMP, ICMPv6, SCTP
+
false
sourcePortsint or string + SourcePorts defines the source ports to filter flows by. +To filter a single port, set a single port as an integer value. For example sourcePorts: 80. +To filter a range of ports, use a "start-end" range, string format. For example sourcePorts: "80-100".
+
false
+ + ### FlowCollector.spec.agent.ebpf.metrics [↩ Parent](#flowcollectorspecagentebpf-1) diff --git a/pkg/helper/flowcollector.go b/pkg/helper/flowcollector.go index 7eaa8d67d..7dd78ca7e 100644 --- a/pkg/helper/flowcollector.go +++ b/pkg/helper/flowcollector.go @@ -118,6 +118,10 @@ func IsSubnetLabelsEnabled(spec *flowslatest.FlowCollectorFLP) bool { return AutoDetectOpenShiftNetworks(spec) || len(spec.SubnetLabels.CustomLabels) > 0 } +func IsEBFPFlowFilterEnabled(spec *flowslatest.FlowCollectorEBPF) bool { + return spec.FlowFilter != nil && spec.FlowFilter.Enable != nil && *spec.FlowFilter.Enable +} + func PtrBool(b *bool) bool { if b == nil { return false