From 36cb0273ff7162ac0d6554174c74e74bac66df26 Mon Sep 17 00:00:00 2001 From: Thomas Labarussias Date: Tue, 28 May 2024 18:27:57 +0200 Subject: [PATCH] add outputFieldFormat parameter Signed-off-by: Thomas Labarussias --- Makefile | 2 +- README.md | 1 + config.go | 1 + config_example.yaml | 1 + go.mod | 2 +- handlers.go | 30 +++++++++++++++++++++++++++--- main.go | 6 ++++-- types/types.go | 1 + 8 files changed, 37 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index b69e1c494..e51f1a844 100644 --- a/Makefile +++ b/Makefile @@ -100,7 +100,7 @@ lint-full: $(GOLANGCI_LINT) ## Run slower linters to detect possible issues .PHONY: goreleaser-snapshot goreleaser-snapshot: ## Release snapshot using goreleaser - LDFLAGS="$(LDFLAGS)" goreleaser --snapshot --skip-sign --clean + LDFLAGS="$(LDFLAGS)" goreleaser --snapshot --skip=sign --clean ## -------------------------------------- ## Tooling Binaries diff --git a/README.md b/README.md index 710bb3ea6..f6df8f911 100644 --- a/README.md +++ b/README.md @@ -326,6 +326,7 @@ customfields: # custom fields are added to falco events, if the value starts wit templatedfields: # templated fields are added to falco events and metrics, it uses Go template + output_fields values # Dkey: '{{ or (index . "k8s.ns.labels.foo") "bar" }}' # bracketreplacer: "_" # if not empty, replace the brackets in keys of Output Fields +outputFieldFormat: ": " # if not empty, allow to change the format of the output field. (default: ": ") mutualtlsfilespath: "/etc/certs" # folder which will used to store client.crt, client.key and ca.crt files for mutual tls for outputs, will be deprecated in the future (default: "/etc/certs") mutualtlsclient: # takes priority over mutualtlsfilespath if not emtpy certfile: "/etc/certs/client/client.crt" # client certification file diff --git a/config.go b/config.go index 204f0fa46..282968cc8 100644 --- a/config.go +++ b/config.go @@ -58,6 +58,7 @@ func getConfig() *types.Configuration { v.SetDefault("MutualTLSClient.KeyFile", "") v.SetDefault("MutualTLSClient.CaCertFile", "") v.SetDefault("TLSClient.CaCertFile", "") + v.SetDefault("OutputFieldFormat", "") v.SetDefault("TLSServer.Deploy", false) v.SetDefault("TLSServer.CertFile", "/etc/certs/server/server.crt") diff --git a/config_example.yaml b/config_example.yaml index 70dbb711d..15a0ecae4 100644 --- a/config_example.yaml +++ b/config_example.yaml @@ -8,6 +8,7 @@ customfields: # custom fields are added to falco events and metrics, if the valu templatedfields: # templated fields are added to falco events and metrics, it uses Go template + output_fields values # Dkey: '{{ or (index . "k8s.ns.labels.foo") "bar" }}' # bracketreplacer: "_" # if not empty, the brackets in keys of Output Fields are replaced +outputFieldFormat: ": " # if not empty, allow to change the format of the output field. (default: ": ") mutualtlsfilespath: "/etc/certs" # folder which will used to store client.crt, client.key and ca.crt files for mutual tls for outputs, will be deprecated in the future (default: "/etc/certs") mutualtlsclient: # takes priority over mutualtlsfilespath if not emtpy certfile: "/etc/certs/client/client.crt" # client certification file diff --git a/go.mod b/go.mod index 7f2759626..ed3da0fff 100644 --- a/go.mod +++ b/go.mod @@ -37,6 +37,7 @@ require ( go.opentelemetry.io/otel/sdk v1.27.0 go.opentelemetry.io/otel/trace v1.27.0 golang.org/x/oauth2 v0.20.0 + golang.org/x/text v0.15.0 google.golang.org/api v0.181.0 google.golang.org/genproto v0.0.0-20240415180920-8c6c420018be k8s.io/api v0.30.1 @@ -138,7 +139,6 @@ require ( golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.20.0 // indirect golang.org/x/term v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240506185236-b8a5c65736ae // indirect diff --git a/handlers.go b/handlers.go index e315c5a0f..383bf3cfb 100644 --- a/handlers.go +++ b/handlers.go @@ -16,11 +16,13 @@ import ( "github.com/falcosecurity/falcosidekick/types" "github.com/google/uuid" + "golang.org/x/text/cases" + "golang.org/x/text/language" ) const testRule string = "Test rule" -// mainHandler is Falco Sidekick main handler (default). +// mainHandler is Falcosidekick main handler (default). func mainHandler(w http.ResponseWriter, r *http.Request) { stats.Requests.Add("total", 1) nullClient.CountMetric("total", 1, []string{}) @@ -89,11 +91,13 @@ func newFalcoPayload(payload io.Reader) (types.FalcoPayload, error) { return types.FalcoPayload{}, err } + var customFields string if len(config.Customfields) > 0 { if falcopayload.OutputFields == nil { falcopayload.OutputFields = make(map[string]interface{}) } for key, value := range config.Customfields { + customFields += key + "=" + value + " " falcopayload.OutputFields[key] = value } } @@ -120,6 +124,7 @@ func newFalcoPayload(payload io.Reader) (types.FalcoPayload, error) { } } + var templatedFields string if len(config.Templatedfields) > 0 { if falcopayload.OutputFields == nil { falcopayload.OutputFields = make(map[string]interface{}) @@ -134,6 +139,7 @@ func newFalcoPayload(payload io.Reader) (types.FalcoPayload, error) { if err := tmpl.Execute(v, falcopayload.OutputFields); err != nil { log.Printf("[ERROR] : Parsing error for templated field '%v': %v\n", key, err) } + templatedFields += key + "=" + v.String() + " " falcopayload.OutputFields[key] = v.String() } } @@ -180,6 +186,26 @@ func newFalcoPayload(payload io.Reader) (types.FalcoPayload, error) { } } + if config.OutputFieldFormat != "" && regOutputFormat.MatchString(falcopayload.Output) { + outputElements := strings.Split(falcopayload.Output, " ") + if len(outputElements) >= 3 { + t := strings.TrimSuffix(outputElements[0], ":") + p := cases.Title(language.English).String(falcopayload.Priority.String()) + o := strings.Join(outputElements[2:], " ") + n := config.OutputFieldFormat + n = strings.ReplaceAll(n, "", t) + n = strings.ReplaceAll(n, "", p) + n = strings.ReplaceAll(n, "", o) + n = strings.ReplaceAll(n, "", strings.TrimSuffix(customFields, " ")) + n = strings.ReplaceAll(n, "", strings.TrimSuffix(templatedFields, " ")) + n = strings.TrimSuffix(n, " ") + n = strings.TrimSuffix(n, "( )") + n = strings.TrimSuffix(n, "()") + n = strings.TrimSuffix(n, " ") + falcopayload.Output = n + } + } + if len(falcopayload.String()) > 4096 { for i, j := range falcopayload.OutputFields { switch j.(type) { @@ -193,8 +219,6 @@ func newFalcoPayload(payload io.Reader) (types.FalcoPayload, error) { } } - fmt.Println(falcopayload.String()) - if config.Debug { log.Printf("[DEBUG] : Falco's payload : %v\n", falcopayload.String()) } diff --git a/main.go b/main.go index 953ac3cfd..f3405ccbb 100644 --- a/main.go +++ b/main.go @@ -84,8 +84,9 @@ var ( promStats *types.PromStatistics initClientArgs *types.InitClientArgs - regPromLabels *regexp.Regexp - shutDownFuncs []func() + regPromLabels *regexp.Regexp + regOutputFormat *regexp.Regexp + shutDownFuncs []func() ) func init() { @@ -98,6 +99,7 @@ func init() { } regPromLabels, _ = regexp.Compile("^[a-zA-Z_:][a-zA-Z0-9_:]*$") + regOutputFormat, _ = regexp.Compile(`(?i)[0-9:]+\.[0-9]+: (Debug|Informational|Notice|Warning|Error|Critical|Alert|Emergency) .*`) config = getConfig() stats = getInitStats() diff --git a/types/types.go b/types/types.go index 42cce2675..48c2df6fa 100644 --- a/types/types.go +++ b/types/types.go @@ -58,6 +58,7 @@ type Configuration struct { ListenAddress string ListenPort int BracketReplacer string + OutputFieldFormat string Customfields map[string]string Templatedfields map[string]string Prometheus prometheusOutputConfig