From 7c3d644b245795526710f9db9435b523aec3e99f Mon Sep 17 00:00:00 2001 From: Igor Eulalio <41654187+IgorEulalio@users.noreply.github.com> Date: Tue, 8 Oct 2024 14:22:12 -0300 Subject: [PATCH] change workflow to allow actionner to also delete standalone pods (#459) + refactor GetOwnerKind method --- actionners/kubernetes/drain/drain.go | 8 +---- actionners/kubernetes/terminate/terminate.go | 38 ++++++++++---------- internal/kubernetes/client/client.go | 8 +++-- rules.yaml | 5 ++- utils/utils.go | 7 ++-- 5 files changed, 34 insertions(+), 32 deletions(-) diff --git a/actionners/kubernetes/drain/drain.go b/actionners/kubernetes/drain/drain.go index f5d5bc94..f7a1d063 100644 --- a/actionners/kubernetes/drain/drain.go +++ b/actionners/kubernetes/drain/drain.go @@ -220,13 +220,7 @@ func (a Actionner) RunWithClient(client k8s.DrainClient, event *events.Event, ac go func(pod corev1.Pod) { defer wg.Done() - ownerKind, err := k8s.GetOwnerKind(p) - if err != nil { - utils.PrintLog("warning", utils.LogLine{Message: fmt.Sprintf("error getting pod '%v' owner kind: %v", p.Name, err)}) - atomic.AddInt32(&otherErrorsCount, 1) - return - } - + ownerKind := k8s.PodKind(p) switch ownerKind { case utils.DaemonSetStr: if parameters.IgnoreDaemonsets { diff --git a/actionners/kubernetes/terminate/terminate.go b/actionners/kubernetes/terminate/terminate.go index c4def71e..9a394d32 100644 --- a/actionners/kubernetes/terminate/terminate.go +++ b/actionners/kubernetes/terminate/terminate.go @@ -50,6 +50,7 @@ rules: grace_period_seconds: 5 ignore_daemonsets: true ignore_statefulsets: true + ignore_standalone_pods: true min_healthy_replicas: 33% ` ) @@ -59,10 +60,11 @@ var ( ) type Parameters struct { - MinHealthyReplicas string `mapstructure:"min_healthy_replicas" validate:"omitempty,is_absolut_or_percent"` - IgnoreDaemonsets bool `mapstructure:"ignore_daemonsets" validate:"omitempty"` - IgnoreStatefulSets bool `mapstructure:"ignore_statefulsets" validate:"omitempty"` - GracePeriodSeconds int `mapstructure:"grace_period_seconds" validate:"omitempty"` + MinHealthyReplicas string `mapstructure:"min_healthy_replicas" validate:"omitempty,is_absolut_or_percent"` + IgnoreDaemonsets bool `mapstructure:"ignore_daemonsets" validate:"omitempty"` + IgnoreStatefulSets bool `mapstructure:"ignore_statefulsets" validate:"omitempty"` + IgnoreStandalonePods bool `mapstructure:"ignore_standalone_pods" validate:"omitempty"` + GracePeriodSeconds int `mapstructure:"grace_period_seconds" validate:"omitempty"` } type Actionner struct{} @@ -92,10 +94,11 @@ func (a Actionner) Information() models.Information { } func (a Actionner) Parameters() models.Parameters { return Parameters{ - MinHealthyReplicas: "", - IgnoreDaemonsets: false, - IgnoreStatefulSets: false, - GracePeriodSeconds: 0, + MinHealthyReplicas: "", + IgnoreDaemonsets: false, + IgnoreStatefulSets: false, + IgnoreStandalonePods: true, + GracePeriodSeconds: 0, } } @@ -137,16 +140,7 @@ func (a Actionner) Run(event *events.Event, action *rules.Action) (utils.LogLine err } - ownerKind, err := k8s.GetOwnerKind(*pod) - if err != nil { - return utils.LogLine{ - Objects: objects, - Error: err.Error(), - Status: utils.FailureStr, - }, - nil, - err - } + ownerKind := k8s.PodKind(*pod) switch ownerKind { case utils.DaemonSetStr: @@ -226,6 +220,14 @@ func (a Actionner) Run(event *events.Event, action *rules.Action) (utils.LogLine } } } + case utils.StandalonePodStr: + if parameters.IgnoreStandalonePods { + return utils.LogLine{ + Objects: objects, + Status: "ignored", + Result: fmt.Sprintf("the pod '%v' in the namespace '%v' is a standalone pod and will be ignored.", podName, namespace), + }, nil, nil + } } err = client.Clientset.CoreV1().Pods(namespace).Delete(context.Background(), podName, metav1.DeleteOptions{GracePeriodSeconds: gracePeriodSeconds}) diff --git a/internal/kubernetes/client/client.go b/internal/kubernetes/client/client.go index c49f8ade..4f82ea8d 100644 --- a/internal/kubernetes/client/client.go +++ b/internal/kubernetes/client/client.go @@ -541,11 +541,13 @@ func (client Client) EvictPod(pod corev1.Pod) error { return nil } -func GetOwnerKind(pod corev1.Pod) (string, error) { +// PodKind returns the type of the pod +// if no owner reference is found, the pod is considered as a standalone pod +func PodKind(pod corev1.Pod) string { if len(pod.OwnerReferences) == 0 { - return "", fmt.Errorf("no owner reference found") + return utils.StandalonePodStr } - return pod.OwnerReferences[0].Kind, nil + return pod.OwnerReferences[0].Kind } func GetOwnerName(pod corev1.Pod) (string, error) { diff --git a/rules.yaml b/rules.yaml index 2df9d78b..c7f7443f 100644 --- a/rules.yaml +++ b/rules.yaml @@ -1,5 +1,8 @@ - action: Terminate Pod actionner: kubernetes:terminate + parameters: + grace_period_seconds: 5 + ignore_standalone_pods: true - action: Disable outbound connections actionner: kubernetes:networkpolicy @@ -50,7 +53,7 @@ output_fields: - k8s.ns.name!=kube-system, k8s.ns.name!=falco actions: - - action: Label Pod as Suspicious + - action: Terminate Pod - rule: Test invoke lambda match: diff --git a/utils/utils.go b/utils/utils.go index f792d051..184ff789 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -42,9 +42,10 @@ const ( ansiChars string = "[\u001B\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))" - DaemonSetStr = "DaemonSet" - StatefulSetStr = "StatefulSet" - ReplicaSetStr = "ReplicaSet" + DaemonSetStr = "DaemonSet" + StatefulSetStr = "StatefulSet" + ReplicaSetStr = "ReplicaSet" + StandalonePodStr = "StandalonePod" ) type LogLine struct {