From 3fc81aa58ea1c3be92926b4344a7c5bedbed5cd0 Mon Sep 17 00:00:00 2001 From: Idriss Neumann Date: Fri, 29 Dec 2023 08:47:29 +0100 Subject: [PATCH] feat(quickwit_output): implement the quickwit output Signed-off-by: Idriss Neumann --- go.mod | 4 +++- handlers.go | 4 ++++ main.go | 21 +++++++++++++++++++ outputs/quickwit.go | 51 +++++++++++++++++++++++++++++++++++++++++++++ types/types.go | 12 +++++++++++ 5 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 outputs/quickwit.go diff --git a/go.mod b/go.mod index f9bd33fae7..e035ae26ed 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/falcosecurity/falcosidekick -go 1.20 +go 1.21 + +toolchain go1.21.4 require ( cloud.google.com/go/functions v1.15.4 diff --git a/handlers.go b/handlers.go index c0e445d8b1..a883846f13 100644 --- a/handlers.go +++ b/handlers.go @@ -235,6 +235,10 @@ func forwardEvent(falcopayload types.FalcoPayload) { go elasticsearchClient.ElasticsearchPost(falcopayload) } + if config.Quickwit.HostPort != "" && (falcopayload.Priority >= types.Priority(config.Webhook.MinimumPriority) || falcopayload.Rule == testRule) { + go quickwitClient.QuickwitPost(falcopayload) + } + if config.Influxdb.HostPort != "" && (falcopayload.Priority >= types.Priority(config.Influxdb.MinimumPriority) || falcopayload.Rule == testRule) { go influxdbClient.InfluxdbPost(falcopayload) } diff --git a/main.go b/main.go index 6353755a08..4a0ada68e1 100644 --- a/main.go +++ b/main.go @@ -50,6 +50,7 @@ var ( discordClient *outputs.Client alertmanagerClient *outputs.Client elasticsearchClient *outputs.Client + quickwitClient *outputs.Client influxdbClient *outputs.Client lokiClient *outputs.Client sumologicClient *outputs.Client @@ -235,6 +236,26 @@ func init() { } } + if config.Quickwit.HostPort != "" { + var err error + + if config.Quickwit.ApiEndpoint == "" { + config.Quickwit.ApiEndpoint = "/api/v1" + } + + if config.Quickwit.Index == "" { + config.Quickwit.Index = "falco" + } + + quickwitClient, err = outputs.NewClient("Quickwit", config.Quickwit.HostPort+"/"+config.Quickwit.ApiEndpoint+"/"+config.Quickwit.Index, config.Quickwit.MutualTLS, config.Quickwit.CheckCert, config, stats, promStats, statsdClient, dogstatsdClient) + + if err != nil { + config.Quickwit.HostPort = "" + } else { + outputs.EnabledOutputs = append(outputs.EnabledOutputs, "Quickwit") + } + } + if config.Loki.HostPort != "" { var err error lokiClient, err = outputs.NewClient("Loki", config.Loki.HostPort+config.Loki.Endpoint, config.Loki.MutualTLS, config.Loki.CheckCert, config, stats, promStats, statsdClient, dogstatsdClient) diff --git a/outputs/quickwit.go b/outputs/quickwit.go new file mode 100644 index 0000000000..831fbf13a8 --- /dev/null +++ b/outputs/quickwit.go @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: Apache-2.0 +/* +Copyright (C) 2023 The Falco Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package outputs + +import ( + "log" + + "github.com/falcosecurity/falcosidekick/types" +) + +func (c *Client) QuickwitPost(falcopayload types.FalcoPayload) { + c.Stats.Quickwit.Add(Total, 1) + + if len(c.Config.Quickwit.CustomHeaders) != 0 { + c.httpClientLock.Lock() + defer c.httpClientLock.Unlock() + for i, j := range c.Config.Quickwit.CustomHeaders { + c.AddHeader(i, j) + } + } + + err := c.Post(falcopayload) + + if err != nil { + go c.CountMetric(Outputs, 1, []string{"output:quickwit", "status:error"}) + c.Stats.Quickwit.Add(Error, 1) + c.PromStats.Outputs.With(map[string]string{"destination": "quickwit", "status": Error}).Inc() + log.Printf("[ERROR] : Quickwit - %v\n", err.Error()) + return + } + + // Setting the success status + go c.CountMetric(Outputs, 1, []string{"output:quickwit", "status:ok"}) + c.Stats.Quickwit.Add(OK, 1) + c.PromStats.Outputs.With(map[string]string{"destination": "quickwit", "status": OK}).Inc() +} diff --git a/types/types.go b/types/types.go index 75e6cbf8a0..e406632c5e 100644 --- a/types/types.go +++ b/types/types.go @@ -84,6 +84,7 @@ type Configuration struct { Discord DiscordOutputConfig Alertmanager AlertmanagerOutputConfig Elasticsearch ElasticsearchOutputConfig + Quickwit QuickwitOutputConfig Influxdb influxdbOutputConfig Loki LokiOutputConfig SumoLogic SumoLogicOutputConfig @@ -276,6 +277,16 @@ type ElasticsearchOutputConfig struct { CustomHeaders map[string]string } +type QuickwitOutputConfig struct { + HostPort string + ApiEndpoint string + Index string + CustomHeaders map[string]string + MinimumPriority string + CheckCert bool + MutualTLS bool +} + type influxdbOutputConfig struct { HostPort string Database string @@ -777,6 +788,7 @@ type Statistics struct { Discord *expvar.Map Alertmanager *expvar.Map Elasticsearch *expvar.Map + Quickwit *expvar.Map Loki *expvar.Map SumoLogic *expvar.Map Nats *expvar.Map