From ccb30b025a1425e5366eaad103c6df2dd6bd0c04 Mon Sep 17 00:00:00 2001 From: Thomas Labarussias Date: Tue, 1 Oct 2024 01:21:34 +0200 Subject: [PATCH] fix various panics + fix label with a / in the key (#457) * fix various panics because of nil maps and nil pointers + fix label with a / in the key Signed-off-by: Thomas Labarussias * fix Event formatting in Slack message Signed-off-by: Thomas Labarussias --------- Signed-off-by: Thomas Labarussias --- .../calico/networkpolicy/networkpolicy.go | 2 +- .../cilium/networkpolicy/networkpolicy.go | 2 +- actionners/kubernetes/label/label.go | 5 +- cmd/rules.go | 6 +- configuration/configuration.go | 26 +++---- internal/context/aws/aws.go | 4 +- internal/context/context.go | 4 +- internal/context/kubernetes/kubernetes.go | 4 +- internal/events/events.go | 24 +++--- internal/kubernetes/client/client.go | 4 +- internal/models/models.go | 2 +- internal/rules/rules.go | 73 ++++++++++--------- notifiers/elasticsearch/elasticsearch.go | 4 +- notifiers/http/client.go | 2 +- notifiers/k8sevents/k8sevents.go | 2 +- notifiers/loki/loki.go | 2 +- notifiers/notifiers.go | 2 +- notifiers/slack/slack.go | 4 +- notifiers/smtp/smtp.go | 2 +- notifiers/webhook/webhook.go | 2 +- utils/utils.go | 8 +- 21 files changed, 94 insertions(+), 90 deletions(-) diff --git a/actionners/calico/networkpolicy/networkpolicy.go b/actionners/calico/networkpolicy/networkpolicy.go index 8c55c5d5..892f6f60 100644 --- a/actionners/calico/networkpolicy/networkpolicy.go +++ b/actionners/calico/networkpolicy/networkpolicy.go @@ -108,7 +108,7 @@ func Register() *Actionner { } func (a Actionner) Init() error { - return k8s.Init() + return calico.Init() } func (a Actionner) Information() models.Information { diff --git a/actionners/cilium/networkpolicy/networkpolicy.go b/actionners/cilium/networkpolicy/networkpolicy.go index a0e7f300..536eb694 100644 --- a/actionners/cilium/networkpolicy/networkpolicy.go +++ b/actionners/cilium/networkpolicy/networkpolicy.go @@ -111,7 +111,7 @@ func Register() *Actionner { } func (a Actionner) Init() error { - return k8s.Init() + return cilium.Init() } func (a Actionner) Information() models.Information { diff --git a/actionners/kubernetes/label/label.go b/actionners/kubernetes/label/label.go index dd06a612..7aa41242 100644 --- a/actionners/kubernetes/label/label.go +++ b/actionners/kubernetes/label/label.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "strings" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -162,7 +163,7 @@ func (a Actionner) Run(event *events.Event, action *rules.Action) (utils.LogLine } payload = append(payload, patch{ Op: "replace", - Path: metadataLabels + i, + Path: metadataLabels + strings.ReplaceAll(i, "/", "~1"), Value: fmt.Sprintf("%v", j), }) } @@ -190,7 +191,7 @@ func (a Actionner) Run(event *events.Event, action *rules.Action) (utils.LogLine } payload = append(payload, patch{ Op: "remove", - Path: metadataLabels + i, + Path: metadataLabels + strings.ReplaceAll(i, "/", "~1"), }) } diff --git a/cmd/rules.go b/cmd/rules.go index d2b84e96..7ff98c9a 100644 --- a/cmd/rules.go +++ b/cmd/rules.go @@ -113,10 +113,10 @@ var rulesPrintCmd = &cobra.Command{ DryRun string `yaml:"dry_run,omitempty"` Notifiers []string `yaml:"notifiers,omitempty"` Actions []struct { - Parameters map[string]interface{} `yaml:"parameters,omitempty"` + Parameters map[string]any `yaml:"parameters,omitempty"` Output struct { - Parameters map[string]interface{} `yaml:"parameters"` - Target string `yaml:"target"` + Parameters map[string]any `yaml:"parameters"` + Target string `yaml:"target"` } `yaml:"output,omitempty"` Name string `yaml:"action"` Description string `yaml:"description,omitempty"` diff --git a/configuration/configuration.go b/configuration/configuration.go index 5afcee9a..63effc0c 100644 --- a/configuration/configuration.go +++ b/configuration/configuration.go @@ -35,19 +35,19 @@ type Otel struct { } type Configuration struct { - Notifiers map[string]map[string]interface{} `mapstructure:"notifiers"` - AwsConfig AwsConfig `mapstructure:"aws"` - LogFormat string `mapstructure:"log_format"` - KubeConfig string `mapstructure:"kubeconfig"` - ListenAddress string `mapstructure:"listen_address"` - MinioConfig MinioConfig `mapstructure:"minio"` - RulesFiles []string `mapstructure:"rules_files"` - DefaultNotifiers []string `mapstructure:"default_notifiers"` - Otel Otel `mapstructure:"otel"` - Deduplication deduplication `mapstructure:"deduplication"` - ListenPort int `mapstructure:"listen_port"` - WatchRules bool `mapstructure:"watch_rules"` - PrintAllEvents bool `mapstructure:"print_all_events"` + Notifiers map[string]map[string]any `mapstructure:"notifiers"` + AwsConfig AwsConfig `mapstructure:"aws"` + LogFormat string `mapstructure:"log_format"` + KubeConfig string `mapstructure:"kubeconfig"` + ListenAddress string `mapstructure:"listen_address"` + MinioConfig MinioConfig `mapstructure:"minio"` + RulesFiles []string `mapstructure:"rules_files"` + DefaultNotifiers []string `mapstructure:"default_notifiers"` + Otel Otel `mapstructure:"otel"` + Deduplication deduplication `mapstructure:"deduplication"` + ListenPort int `mapstructure:"listen_port"` + WatchRules bool `mapstructure:"watch_rules"` + PrintAllEvents bool `mapstructure:"print_all_events"` } type deduplication struct { diff --git a/internal/context/aws/aws.go b/internal/context/aws/aws.go index c298e45e..028c6928 100644 --- a/internal/context/aws/aws.go +++ b/internal/context/aws/aws.go @@ -7,7 +7,7 @@ import ( "github.com/falco-talon/falco-talon/internal/events" ) -func GetAwsContext(_ *events.Event) (map[string]interface{}, error) { +func GetAwsContext(_ *events.Event) (map[string]any, error) { imdsClient := aws.GetImdsClient() info, err := imdsClient.GetIAMInfo(context.Background(), nil) @@ -20,7 +20,7 @@ func GetAwsContext(_ *events.Event) (map[string]interface{}, error) { return nil, err } - elements := make(map[string]interface{}) + elements := make(map[string]any) elements["aws.instance_profile_arn"] = info.InstanceProfileArn elements["aws.instance_profile_id"] = info.InstanceProfileID elements["aws.region"] = region.Region diff --git a/internal/context/context.go b/internal/context/context.go index 83b6cafc..7a8ba7c9 100644 --- a/internal/context/context.go +++ b/internal/context/context.go @@ -16,7 +16,7 @@ import ( "github.com/falco-talon/falco-talon/internal/events" ) -func GetContext(actx context.Context, source string, event *events.Event) (map[string]interface{}, error) { +func GetContext(actx context.Context, source string, event *events.Event) (map[string]any, error) { tracer := traces.GetTracer() _, span := tracer.Start(actx, "context", @@ -24,7 +24,7 @@ func GetContext(actx context.Context, source string, event *events.Event) (map[s ) defer span.End() - context := make(map[string]interface{}) + context := make(map[string]any) var err error switch source { diff --git a/internal/context/kubernetes/kubernetes.go b/internal/context/kubernetes/kubernetes.go index 1c7fac9e..9981b980 100644 --- a/internal/context/kubernetes/kubernetes.go +++ b/internal/context/kubernetes/kubernetes.go @@ -5,7 +5,7 @@ import ( kubernetes "github.com/falco-talon/falco-talon/internal/kubernetes/client" ) -func GetNodeContext(event *events.Event) (map[string]interface{}, error) { +func GetNodeContext(event *events.Event) (map[string]any, error) { podName := event.GetPodName() namespace := event.GetNamespaceName() @@ -19,7 +19,7 @@ func GetNodeContext(event *events.Event) (map[string]interface{}, error) { return nil, err } - elements := make(map[string]interface{}) + elements := make(map[string]any) elements["node.hostname"] = node.Labels["kubernetes.io/hostname"] elements["node.instancetype"] = node.Labels["node.kubernetes.io/instance-type"] elements["node.role"] = node.Labels["kubernetes.io/role"] diff --git a/internal/events/events.go b/internal/events/events.go index 59030fa8..158690aa 100644 --- a/internal/events/events.go +++ b/internal/events/events.go @@ -11,16 +11,16 @@ import ( ) type Event struct { - TraceID string `json:"trace_id"` - Output string `json:"output"` - Priority string `json:"priority"` - Rule string `json:"rule"` - Hostname string `json:"hostname"` - Time time.Time `json:"time"` - Source string `json:"source"` - OutputFields map[string]interface{} `json:"output_fields"` - Context map[string]interface{} `json:"context"` - Tags []interface{} `json:"tags"` + TraceID string `json:"trace_id"` + Output string `json:"output"` + Priority string `json:"priority"` + Rule string `json:"rule"` + Hostname string `json:"hostname"` + Time time.Time `json:"time"` + Source string `json:"source"` + OutputFields map[string]any `json:"output_fields"` + Context map[string]any `json:"context"` + Tags []any `json:"tags"` } const ( @@ -123,9 +123,9 @@ func (event *Event) GetRemoteProtocol() string { return "" } -func (event *Event) AddContext(elements map[string]interface{}) { +func (event *Event) AddContext(elements map[string]any) { if event.Context == nil { - event.Context = make(map[string]interface{}) + event.Context = make(map[string]any) } if len(elements) == 0 { return diff --git a/internal/kubernetes/client/client.go b/internal/kubernetes/client/client.go index 496018b0..c49f8ade 100644 --- a/internal/kubernetes/client/client.go +++ b/internal/kubernetes/client/client.go @@ -58,7 +58,7 @@ type KubernetesClient interface { GetStatefulsetFromPod(pod *corev1.Pod) (*appsv1.StatefulSet, error) GetReplicasetFromPod(pod *corev1.Pod) (*appsv1.ReplicaSet, error) GetNodeFromPod(pod *corev1.Pod) (*corev1.Node, error) - GetTarget(resource, name, namespace string) (interface{}, error) + GetTarget(resource, name, namespace string) (any, error) GetNamespace(name string) (*corev1.Namespace, error) GetConfigMap(name, namespace string) (*corev1.ConfigMap, error) GetSecret(name, namespace string) (*corev1.Secret, error) @@ -259,7 +259,7 @@ func (client Client) GetNodeFromPod(pod *corev1.Pod) (*corev1.Node, error) { return r, nil } -func (client Client) GetTarget(resource, name, namespace string) (interface{}, error) { +func (client Client) GetTarget(resource, name, namespace string) (any, error) { switch resource { case "namespaces": return client.GetNamespace(name) diff --git a/internal/models/models.go b/internal/models/models.go index 9bda116d..72d2bc29 100644 --- a/internal/models/models.go +++ b/internal/models/models.go @@ -21,4 +21,4 @@ type Data struct { Bytes []byte } -type Parameters interface{} +type Parameters any diff --git a/internal/rules/rules.go b/internal/rules/rules.go index 62b3aa67..085e57c3 100644 --- a/internal/rules/rules.go +++ b/internal/rules/rules.go @@ -16,14 +16,14 @@ import ( ) type Action struct { - Output Output `yaml:"output,omitempty"` - Parameters map[string]interface{} `yaml:"parameters,omitempty"` - Name string `yaml:"action"` - Description string `yaml:"description"` - Actionner string `yaml:"actionner"` - Continue string `yaml:"continue,omitempty"` // can't be a bool because an omitted value == false by default - IgnoreErrors string `yaml:"ignore_errors,omitempty"` // can't be a bool because an omitted value == false by default - AdditionalContexts []string `yaml:"additional_contexts,omitempty"` + Output Output `yaml:"output,omitempty"` + Parameters map[string]any `yaml:"parameters,omitempty"` + Name string `yaml:"action"` + Description string `yaml:"description"` + Actionner string `yaml:"actionner"` + Continue string `yaml:"continue,omitempty"` // can't be a bool because an omitted value == false by default + IgnoreErrors string `yaml:"ignore_errors,omitempty"` // can't be a bool because an omitted value == false by default + AdditionalContexts []string `yaml:"additional_contexts,omitempty"` } type Rule struct { @@ -49,8 +49,8 @@ type Match struct { } type Output struct { - Parameters map[string]interface{} `yaml:"parameters"` - Target string `yaml:"target"` + Parameters map[string]any `yaml:"parameters"` + Target string `yaml:"target"` } type outputfield struct { @@ -113,7 +113,7 @@ func ParseRules(files []string) *[]*Rule { rule.Actions[n].AdditionalContexts = action.AdditionalContexts } if rule.Actions[n].Parameters == nil && len(action.Parameters) != 0 { - rule.Actions[n].Parameters = make(map[string]interface{}) + rule.Actions[n].Parameters = make(map[string]any) } for k, v := range action.Parameters { rt := reflect.TypeOf(v) @@ -129,17 +129,17 @@ func ParseRules(files []string) *[]*Rule { case reflect.Slice, reflect.Array: w := v if rule.Actions[n].Parameters[k] == nil { - rule.Actions[n].Parameters[k] = []interface{}{w} + rule.Actions[n].Parameters[k] = []any{w} } else { - w = append(w.([]interface{}), rule.Actions[n].Parameters[k].([]interface{})...) + w = append(w.([]any), rule.Actions[n].Parameters[k].([]any)...) } rule.Actions[n].Parameters[k] = w case reflect.Map: - for s, t := range v.(map[string]interface{}) { + for s, t := range v.(map[string]any) { if rule.Actions[n].Parameters[k] == nil { - rule.Actions[n].Parameters[k] = make(map[string]interface{}) + rule.Actions[n].Parameters[k] = make(map[string]any) } - rule.Actions[n].Parameters[k].(map[string]interface{})[s] = t + rule.Actions[n].Parameters[k].(map[string]any)[s] = t } default: if rule.Actions[n].Parameters[k] == nil { @@ -164,20 +164,23 @@ func ParseRules(files []string) *[]*Rule { case reflect.Slice, reflect.Array: w := v if rule.Actions[n].Output.Parameters[k] == nil { - rule.Actions[n].Output.Parameters[k] = []interface{}{w} + rule.Actions[n].Output.Parameters[k] = []any{w} } else { - w = append(w.([]interface{}), rule.Actions[n].Output.Parameters[k].([]interface{})...) + w = append(w.([]any), rule.Actions[n].Output.Parameters[k].([]any)...) } rule.Actions[n].Output.Parameters[k] = w case reflect.Map: - for s, t := range v.(map[string]interface{}) { + for s, t := range v.(map[string]any) { if rule.Actions[n].Output.Parameters[k] == nil { - rule.Actions[n].Output.Parameters[k] = make(map[string]interface{}) + rule.Actions[n].Output.Parameters[k] = make(map[string]any) } - rule.Actions[n].Output.Parameters[k].(map[string]interface{})[s] = t + rule.Actions[n].Output.Parameters[k].(map[string]any)[s] = t } default: if rule.Actions[n].Output.Parameters[k] == nil { + if rule.Actions[n].Output.Parameters == nil { + rule.Actions[n].Output.Parameters = make(map[string]any) + } rule.Actions[n].Output.Parameters[k] = v } } @@ -275,7 +278,7 @@ func extractActionsRules(files []string) (*[]*Action, *[]*Rule, error) { i.IgnoreErrors = l.IgnoreErrors } if i.Parameters == nil && len(l.Parameters) != 0 { - i.Parameters = make(map[string]interface{}) + i.Parameters = make(map[string]any) } i.AdditionalContexts = append(i.AdditionalContexts, l.AdditionalContexts...) for k, v := range l.Parameters { @@ -290,16 +293,16 @@ func extractActionsRules(files []string) (*[]*Action, *[]*Rule, error) { switch rt.Kind() { case reflect.Slice, reflect.Array: if i.Parameters[k] == nil { - i.Parameters[k] = []interface{}{v} + i.Parameters[k] = []any{v} } else { - i.Parameters[k] = append(i.Parameters[k].([]interface{}), v.([]interface{})...) + i.Parameters[k] = append(i.Parameters[k].([]any), v.([]any)...) } case reflect.Map: - for s, t := range v.(map[string]interface{}) { + for s, t := range v.(map[string]any) { if i.Parameters[k] == nil { - i.Parameters[k] = make(map[string]interface{}) + i.Parameters[k] = make(map[string]any) } - i.Parameters[k].(map[string]interface{})[s] = t + i.Parameters[k].(map[string]any)[s] = t } default: i.Parameters[k] = v @@ -317,16 +320,16 @@ func extractActionsRules(files []string) (*[]*Action, *[]*Rule, error) { switch rt.Kind() { case reflect.Slice, reflect.Array: if i.Output.Parameters[k] == nil { - i.Output.Parameters[k] = []interface{}{v} + i.Output.Parameters[k] = []any{v} } else { - i.Output.Parameters[k] = append(i.Output.Parameters[k].([]interface{}), v.([]interface{})...) + i.Output.Parameters[k] = append(i.Output.Parameters[k].([]any), v.([]any)...) } case reflect.Map: - for s, t := range v.(map[string]interface{}) { + for s, t := range v.(map[string]any) { if i.Output.Parameters[k] == nil { - i.Output.Parameters[k] = make(map[string]interface{}) + i.Output.Parameters[k] = make(map[string]any) } - i.Output.Parameters[k].(map[string]interface{})[s] = t + i.Output.Parameters[k].(map[string]any)[s] = t } default: i.Output.Parameters[k] = v @@ -507,7 +510,7 @@ func (action *Action) GetActionnerName() string { return strings.Split(action.Actionner, ":")[1] } -func (action *Action) GetParameters() map[string]interface{} { +func (action *Action) GetParameters() map[string]any { return action.Parameters } @@ -526,7 +529,7 @@ func (output *Output) GetTarget() string { return output.Target } -func (output *Output) GetParameters() map[string]interface{} { +func (output *Output) GetParameters() map[string]any { return output.Parameters } @@ -646,7 +649,7 @@ func (rule *Rule) comparePriority(event *events.Event) bool { } func (rule *Rule) AddFalcoTalonContext(event *events.Event, action *Action) { - elements := make(map[string]interface{}) + elements := make(map[string]any) elements[falcoTalonContextPrefix+"rule"] = rule.Name if rule.Continue != "" { elements[falcoTalonContextPrefix+"rule.continue"] = rule.Continue diff --git a/notifiers/elasticsearch/elasticsearch.go b/notifiers/elasticsearch/elasticsearch.go index fb1d58e8..198266d9 100644 --- a/notifiers/elasticsearch/elasticsearch.go +++ b/notifiers/elasticsearch/elasticsearch.go @@ -55,7 +55,7 @@ func Register() *Notifier { return new(Notifier) } -func (n Notifier) Init(fields map[string]interface{}) error { +func (n Notifier) Init(fields map[string]any) error { parameters = new(Parameters) parameters = utils.SetFields(parameters, fields).(*Parameters) if err := checkParameters(parameters); err != nil { @@ -71,7 +71,7 @@ func (n Notifier) Init(fields map[string]interface{}) error { client.SetHTTPMethod("PUT") m := strings.ReplaceAll(mapping, "${SHARDS}", fmt.Sprintf("%v", parameters.NumberOfShards)) m = strings.ReplaceAll(m, "${REPLICAS}", fmt.Sprintf("%v", parameters.NumberOfReplicas)) - j := make(map[string]interface{}) + j := make(map[string]any) if err := json.Unmarshal([]byte(m), &j); err != nil { return err } diff --git a/notifiers/http/client.go b/notifiers/http/client.go index b8725a52..0d3f01d5 100644 --- a/notifiers/http/client.go +++ b/notifiers/http/client.go @@ -109,7 +109,7 @@ func NewClient(httpMethod, contentType, userAgent string, headers map[string]str } } -func (c *Client) Request(u string, payload interface{}) error { +func (c *Client) Request(u string, payload any) error { // defer + recover to catch panic if output doesn't respond defer func() { if err := recover(); err != nil { diff --git a/notifiers/k8sevents/k8sevents.go b/notifiers/k8sevents/k8sevents.go index 596053b3..7a2b664c 100644 --- a/notifiers/k8sevents/k8sevents.go +++ b/notifiers/k8sevents/k8sevents.go @@ -77,7 +77,7 @@ func Register() *Notifier { return new(Notifier) } -func (n Notifier) Init(_ map[string]interface{}) error { return nil } +func (n Notifier) Init(_ map[string]any) error { return nil } func (n Notifier) Information() models.Information { return models.Information{ diff --git a/notifiers/loki/loki.go b/notifiers/loki/loki.go index b79c25f7..93e230dd 100644 --- a/notifiers/loki/loki.go +++ b/notifiers/loki/loki.go @@ -52,7 +52,7 @@ func Register() *Notifier { return new(Notifier) } -func (n Notifier) Init(fields map[string]interface{}) error { +func (n Notifier) Init(fields map[string]any) error { parameters = new(Parameters) parameters = utils.SetFields(parameters, fields).(*Parameters) if err := checkParameters(parameters); err != nil { diff --git a/notifiers/notifiers.go b/notifiers/notifiers.go index 56e0d52b..c0dab0ba 100644 --- a/notifiers/notifiers.go +++ b/notifiers/notifiers.go @@ -26,7 +26,7 @@ import ( ) type Notifier interface { - Init(fields map[string]interface{}) error + Init(fields map[string]any) error Run(log utils.LogLine) error Information() models.Information Parameters() models.Parameters diff --git a/notifiers/slack/slack.go b/notifiers/slack/slack.go index 410a7971..f99a045d 100644 --- a/notifiers/slack/slack.go +++ b/notifiers/slack/slack.go @@ -71,7 +71,7 @@ func Register() *Notifier { return new(Notifier) } -func (n Notifier) Init(fields map[string]interface{}) error { +func (n Notifier) Init(fields map[string]any) error { parameters = new(Parameters) parameters = utils.SetFields(parameters, fields).(*Parameters) if err := checkParameters(parameters); err != nil { @@ -190,7 +190,7 @@ func newPayload(log utils.LogLine) Payload { } if log.Event != "" { field.Title = "Event" - field.Value = "`" + log.Event + "`" + field.Value = "```" + log.Event + "```" field.Short = false fields = append(fields, field) } diff --git a/notifiers/smtp/smtp.go b/notifiers/smtp/smtp.go index 349745a1..2c2af376 100644 --- a/notifiers/smtp/smtp.go +++ b/notifiers/smtp/smtp.go @@ -70,7 +70,7 @@ func Register() *Notifier { return new(Notifier) } -func (n Notifier) Init(fields map[string]interface{}) error { +func (n Notifier) Init(fields map[string]any) error { parameters = new(Parameters) parameters = utils.SetFields(parameters, fields).(*Parameters) if err := checkParameters(parameters); err != nil { diff --git a/notifiers/webhook/webhook.go b/notifiers/webhook/webhook.go index fd92b504..6f04eded 100644 --- a/notifiers/webhook/webhook.go +++ b/notifiers/webhook/webhook.go @@ -39,7 +39,7 @@ func Register() *Notifier { return new(Notifier) } -func (n Notifier) Init(fields map[string]interface{}) error { +func (n Notifier) Init(fields map[string]any) error { parameters = new(Parameters) parameters = utils.SetFields(parameters, fields).(*Parameters) if err := checkParameters(parameters); err != nil { diff --git a/utils/utils.go b/utils/utils.go index 9c8e0f15..f792d051 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -95,7 +95,7 @@ func PrintLog(level string, line LogLine) { if *logFormat != colorStr { output.NoColor = true } - output.FormatFieldValue = func(i interface{}) string { + output.FormatFieldValue = func(i any) string { return fmt.Sprintf("%s", i) } log = zerolog.New(output).With().Timestamp().Logger() @@ -172,7 +172,7 @@ func PrintLog(level string, line LogLine) { } } -func SetFields(structure interface{}, fields map[string]interface{}) interface{} { +func SetFields(structure any, fields map[string]any) any { valueOf := reflect.ValueOf(structure) if valueOf.Kind() == reflect.Ptr { valueOf = valueOf.Elem() @@ -233,7 +233,7 @@ func SetFields(structure interface{}, fields map[string]interface{}) interface{} return structure } -func ValidateStruct(s interface{}) error { +func ValidateStruct(s any) error { err := validate.Struct(s) if err != nil { return err @@ -249,7 +249,7 @@ func AddCustomValidation(tag string, fn validator.Func) error { return nil } -func DecodeParams(params map[string]interface{}, result interface{}) error { +func DecodeParams(params map[string]any, result any) error { // Decode parameters into the struct decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ TagName: "mapstructure",