diff --git a/config.go b/config.go
index 772fb02afe..9322581667 100644
--- a/config.go
+++ b/config.go
@@ -125,6 +125,7 @@ func getConfig() *types.Configuration {
log.Printf("[ERROR] : Error when reading config file : %v\n", err)
}
}
+
v.GetStringMapString("customfields")
v.GetStringMapString("Webhook.CustomHeaders")
v.Unmarshal(c)
@@ -138,6 +139,7 @@ func getConfig() *types.Configuration {
}
}
}
+
if value, present := os.LookupEnv("WEBHOOK_CUSTOMHEADERS"); present {
customfields := strings.Split(value, ",")
for _, label := range customfields {
@@ -182,6 +184,7 @@ func checkPriority(prio string) string {
if match {
return prio
}
+
return ""
}
@@ -192,7 +195,9 @@ func getMessageFormatTemplate(output, temp string) *template.Template {
if err != nil {
log.Fatalf("[ERROR] : Error compiling %v message template : %v\n", output, err)
}
+
return t
}
+
return nil
}
diff --git a/handlers.go b/handlers.go
index c947f903ee..f001372c3b 100644
--- a/handlers.go
+++ b/handlers.go
@@ -13,6 +13,8 @@ import (
"github.com/falcosecurity/falcosidekick/types"
)
+const TestRule string = "Test rule"
+
func getPriorityMap() map[string]int {
return map[string]int{
"emergency": 8,
@@ -37,6 +39,7 @@ func mainHandler(w http.ResponseWriter, r *http.Request) {
stats.Requests.Add("rejected", 1)
promStats.Inputs.With(map[string]string{"source": "requests", "status": "rejected"}).Inc()
nullClient.CountMetric("inputs.requests.rejected", 1, []string{"error:nobody"})
+
return
}
@@ -46,6 +49,7 @@ func mainHandler(w http.ResponseWriter, r *http.Request) {
stats.Requests.Add("rejected", 1)
promStats.Inputs.With(map[string]string{"source": "requests", "status": "rejected"}).Inc()
nullClient.CountMetric("inputs.requests.rejected", 1, []string{"error:invalidjson"})
+
return
}
@@ -125,61 +129,78 @@ func newFalcoPayload(payload io.Reader) (types.FalcoPayload, error) {
}
func forwardEvent(falcopayload types.FalcoPayload) {
- if config.Slack.WebhookURL != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Slack.MinimumPriority)] || falcopayload.Rule == "Test rule") {
+ if config.Slack.WebhookURL != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Slack.MinimumPriority)] || falcopayload.Rule == TestRule) {
go slackClient.SlackPost(falcopayload)
}
- if config.Rocketchat.WebhookURL != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Rocketchat.MinimumPriority)] || falcopayload.Rule == "Test rule") {
+
+ if config.Rocketchat.WebhookURL != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Rocketchat.MinimumPriority)] || falcopayload.Rule == TestRule) {
go rocketchatClient.RocketchatPost(falcopayload)
}
- if config.Mattermost.WebhookURL != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Mattermost.MinimumPriority)] || falcopayload.Rule == "Test rule") {
+
+ if config.Mattermost.WebhookURL != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Mattermost.MinimumPriority)] || falcopayload.Rule == TestRule) {
go mattermostClient.MattermostPost(falcopayload)
}
- if config.Teams.WebhookURL != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Teams.MinimumPriority)] || falcopayload.Rule == "Test rule") {
+
+ if config.Teams.WebhookURL != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Teams.MinimumPriority)] || falcopayload.Rule == TestRule) {
go teamsClient.TeamsPost(falcopayload)
}
- if config.Datadog.APIKey != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Datadog.MinimumPriority)] || falcopayload.Rule == "Test rule") {
+
+ if config.Datadog.APIKey != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Datadog.MinimumPriority)] || falcopayload.Rule == TestRule) {
go datadogClient.DatadogPost(falcopayload)
}
- if config.Discord.WebhookURL != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Discord.MinimumPriority)] || falcopayload.Rule == "Test rule") {
+
+ if config.Discord.WebhookURL != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Discord.MinimumPriority)] || falcopayload.Rule == TestRule) {
go discordClient.DiscordPost(falcopayload)
}
- if config.Alertmanager.HostPort != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Alertmanager.MinimumPriority)] || falcopayload.Rule == "Test rule") {
+
+ if config.Alertmanager.HostPort != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Alertmanager.MinimumPriority)] || falcopayload.Rule == TestRule) {
go alertmanagerClient.AlertmanagerPost(falcopayload)
}
- if config.Elasticsearch.HostPort != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Elasticsearch.MinimumPriority)] || falcopayload.Rule == "Test rule") {
+
+ if config.Elasticsearch.HostPort != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Elasticsearch.MinimumPriority)] || falcopayload.Rule == TestRule) {
go elasticsearchClient.ElasticsearchPost(falcopayload)
}
- if config.Influxdb.HostPort != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Influxdb.MinimumPriority)] || falcopayload.Rule == "Test rule") {
+
+ if config.Influxdb.HostPort != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Influxdb.MinimumPriority)] || falcopayload.Rule == TestRule) {
go influxdbClient.InfluxdbPost(falcopayload)
}
- if config.Loki.HostPort != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Loki.MinimumPriority)] || falcopayload.Rule == "Test rule") {
+
+ if config.Loki.HostPort != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Loki.MinimumPriority)] || falcopayload.Rule == TestRule) {
go lokiClient.LokiPost(falcopayload)
}
- if config.Nats.HostPort != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Nats.MinimumPriority)] || falcopayload.Rule == "Test rule") {
+
+ if config.Nats.HostPort != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Nats.MinimumPriority)] || falcopayload.Rule == TestRule) {
go natsClient.NatsPublish(falcopayload)
}
- if config.AWS.Lambda.FunctionName != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.AWS.Lambda.MinimumPriority)] || falcopayload.Rule == "Test rule") {
+
+ if config.AWS.Lambda.FunctionName != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.AWS.Lambda.MinimumPriority)] || falcopayload.Rule == TestRule) {
go awsClient.InvokeLambda(falcopayload)
}
- if config.AWS.SQS.URL != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.AWS.SQS.MinimumPriority)] || falcopayload.Rule == "Test rule") {
+
+ if config.AWS.SQS.URL != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.AWS.SQS.MinimumPriority)] || falcopayload.Rule == TestRule) {
go awsClient.SendMessage(falcopayload)
}
- if config.AWS.SNS.TopicArn != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.AWS.SNS.MinimumPriority)] || falcopayload.Rule == "Test rule") {
+
+ if config.AWS.SNS.TopicArn != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.AWS.SNS.MinimumPriority)] || falcopayload.Rule == TestRule) {
go awsClient.PublishTopic(falcopayload)
}
- if config.SMTP.HostPort != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.SMTP.MinimumPriority)] || falcopayload.Rule == "Test rule") {
+
+ if config.SMTP.HostPort != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.SMTP.MinimumPriority)] || falcopayload.Rule == TestRule) {
go smtpClient.SendMail(falcopayload)
}
- if config.Opsgenie.APIKey != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Opsgenie.MinimumPriority)] || falcopayload.Rule == "Test rule") {
+
+ if config.Opsgenie.APIKey != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Opsgenie.MinimumPriority)] || falcopayload.Rule == TestRule) {
go opsgenieClient.OpsgeniePost(falcopayload)
}
- if config.Webhook.Address != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Webhook.MinimumPriority)] || falcopayload.Rule == "Test rule") {
+ if config.Webhook.Address != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Webhook.MinimumPriority)] || falcopayload.Rule == TestRule) {
go webhookClient.WebhookPost(falcopayload)
}
- if config.Azure.EventHub.Name != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Azure.EventHub.MinimumPriority)] || falcopayload.Rule == "Test rule") {
+
+ if config.Azure.EventHub.Name != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.Azure.EventHub.MinimumPriority)] || falcopayload.Rule == TestRule) {
go azureClient.EventHubPost(falcopayload)
}
- if config.GCP.PubSub.Topic != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.GCP.PubSub.MinimumPriority)] || falcopayload.Rule == "Test rule") {
- go gcpClient.GCPPublishTopic(falcopayload)
+
+ if config.GCP.PubSub.Topic != "" && (priorityMap[strings.ToLower(falcopayload.Priority)] >= priorityMap[strings.ToLower(config.GCP.PubSub.MinimumPriority)] || falcopayload.Rule == TestRule) {
+ go gcpClient.GCPPublishTopic(falcopayload)
}
}
diff --git a/main.go b/main.go
index 1ecc2b269a..ba3eba5499 100644
--- a/main.go
+++ b/main.go
@@ -56,6 +56,7 @@ func init() {
enabledOutputsText += "StatsD "
}
}
+
if config.Dogstatsd.Forwarder != "" {
var err error
dogstatsdClient, err = outputs.NewStatsdClient("DogStatsD", config, stats)
@@ -85,6 +86,7 @@ func init() {
enabledOutputsText += "Slack "
}
}
+
if config.Rocketchat.WebhookURL != "" {
var err error
rocketchatClient, err = outputs.NewClient("Rocketchat", config.Rocketchat.WebhookURL, config, stats, promStats, statsdClient, dogstatsdClient)
@@ -94,6 +96,7 @@ func init() {
enabledOutputsText += "Rocketchat "
}
}
+
if config.Mattermost.WebhookURL != "" {
var err error
mattermostClient, err = outputs.NewClient("Mattermost", config.Mattermost.WebhookURL, config, stats, promStats, statsdClient, dogstatsdClient)
@@ -103,6 +106,7 @@ func init() {
enabledOutputsText += "Mattermost "
}
}
+
if config.Teams.WebhookURL != "" {
var err error
teamsClient, err = outputs.NewClient("Teams", config.Teams.WebhookURL, config, stats, promStats, statsdClient, dogstatsdClient)
@@ -112,6 +116,7 @@ func init() {
enabledOutputsText += "Teams "
}
}
+
if config.Datadog.APIKey != "" {
var err error
datadogClient, err = outputs.NewClient("Datadog", config.Datadog.Host+outputs.DatadogPath+"?api_key="+config.Datadog.APIKey, config, stats, promStats, statsdClient, dogstatsdClient)
@@ -121,6 +126,7 @@ func init() {
enabledOutputsText += "Datadog "
}
}
+
if config.Discord.WebhookURL != "" {
var err error
discordClient, err = outputs.NewClient("Discord", config.Discord.WebhookURL, config, stats, promStats, statsdClient, dogstatsdClient)
@@ -130,6 +136,7 @@ func init() {
enabledOutputsText += "Discord "
}
}
+
if config.Alertmanager.HostPort != "" {
var err error
alertmanagerClient, err = outputs.NewClient("AlertManager", config.Alertmanager.HostPort+outputs.AlertmanagerURI, config, stats, promStats, statsdClient, dogstatsdClient)
@@ -139,6 +146,7 @@ func init() {
enabledOutputsText += "AlertManager "
}
}
+
if config.Elasticsearch.HostPort != "" {
var err error
elasticsearchClient, err = outputs.NewClient("Elasticsearch", config.Elasticsearch.HostPort+"/"+config.Elasticsearch.Index+"/"+config.Elasticsearch.Type, config, stats, promStats, statsdClient, dogstatsdClient)
@@ -148,6 +156,7 @@ func init() {
enabledOutputsText += "Elasticsearch "
}
}
+
if config.Loki.HostPort != "" {
var err error
lokiClient, err = outputs.NewClient("Loki", config.Loki.HostPort+"/api/prom/push", config, stats, promStats, statsdClient, dogstatsdClient)
@@ -157,6 +166,7 @@ func init() {
enabledOutputsText += "Loki "
}
}
+
if config.Nats.HostPort != "" {
var err error
natsClient, err = outputs.NewClient("NATS", config.Nats.HostPort, config, stats, promStats, statsdClient, dogstatsdClient)
@@ -166,11 +176,13 @@ func init() {
enabledOutputsText += "NATS "
}
}
+
if config.Influxdb.HostPort != "" {
var credentials string
if config.Influxdb.User != "" && config.Influxdb.Password != "" {
credentials = "&u=" + config.Influxdb.User + "&p=" + config.Influxdb.Password
}
+
var err error
influxdbClient, err = outputs.NewClient("Influxdb", config.Influxdb.HostPort+"/write?db="+config.Influxdb.Database+credentials, config, stats, promStats, statsdClient, dogstatsdClient)
if err != nil {
@@ -179,6 +191,7 @@ func init() {
enabledOutputsText += "Influxdb "
}
}
+
if config.AWS.Lambda.FunctionName != "" || config.AWS.SQS.URL != "" || config.AWS.SNS.TopicArn != "" {
var err error
awsClient, err = outputs.NewAWSClient(config, stats, promStats, statsdClient, dogstatsdClient)
@@ -201,6 +214,7 @@ func init() {
}
}
}
+
if config.SMTP.HostPort != "" && config.SMTP.From != "" && config.SMTP.To != "" {
var err error
smtpClient, err = outputs.NewSMTPClient(config, stats, promStats, statsdClient, dogstatsdClient)
@@ -210,6 +224,7 @@ func init() {
enabledOutputsText += "SMTP "
}
}
+
if config.Opsgenie.APIKey != "" {
var err error
url := "https://api.opsgenie.com/v2/alerts"
@@ -223,6 +238,7 @@ func init() {
enabledOutputsText += "Opsgenie "
}
}
+
if config.Webhook.Address != "" {
var err error
webhookClient, err = outputs.NewClient("Webhook", config.Webhook.Address, config, stats, promStats, statsdClient, dogstatsdClient)
@@ -232,6 +248,7 @@ func init() {
enabledOutputsText += "Webhook "
}
}
+
if config.Azure.EventHub.Name != "" {
var err error
azureClient, err = outputs.NewEventHubClient(config, stats, promStats, statsdClient, dogstatsdClient)
@@ -244,6 +261,7 @@ func init() {
}
}
}
+
if config.GCP.PubSub.ProjectID != "" && config.GCP.PubSub.Topic != "" && config.GCP.Credentials != "" {
var err error
gcpClient, err = outputs.NewGCPClient(config, stats, promStats, statsdClient, dogstatsdClient)
@@ -267,6 +285,7 @@ func main() {
if config.Debug {
log.Printf("[INFO] : Debug mode : %v\n", config.Debug)
}
+
if err := http.ListenAndServe(":"+strconv.Itoa(config.ListenPort), nil); err != nil {
log.Fatalf("[ERROR] : %v\n", err.Error())
}
diff --git a/outputs/alertmanager.go b/outputs/alertmanager.go
index 5c97496602..6f62405f4d 100644
--- a/outputs/alertmanager.go
+++ b/outputs/alertmanager.go
@@ -35,25 +35,25 @@ func newAlertmanagerPayload(falcopayload types.FalcoPayload) []alertmanagerPaylo
switch {
case d == 0:
jj = "0"
- falcopayload.Priority = "warning"
+ falcopayload.Priority = Warning
case d < 10:
jj = "<10"
- falcopayload.Priority = "warning"
+ falcopayload.Priority = Warning
case d > 10000:
jj = ">10000"
- falcopayload.Priority = "critical"
+ falcopayload.Priority = Critical
case d > 1000:
jj = ">1000"
- falcopayload.Priority = "critical"
+ falcopayload.Priority = Critical
case d > 100:
jj = ">100"
- falcopayload.Priority = "critical"
+ falcopayload.Priority = Critical
case d > 10:
jj = ">10"
- falcopayload.Priority = "warning"
+ falcopayload.Priority = Warning
default:
jj = j.(string)
- falcopayload.Priority = "critical"
+ falcopayload.Priority = Critical
}
amPayload.Labels[i] = jj
@@ -86,11 +86,11 @@ func newAlertmanagerPayload(falcopayload types.FalcoPayload) []alertmanagerPaylo
func (c *Client) AlertmanagerPost(falcopayload types.FalcoPayload) {
err := c.Post(newAlertmanagerPayload(falcopayload))
if err != nil {
- c.Stats.Alertmanager.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "alertmanager", "status": "error"}).Inc()
+ c.Stats.Alertmanager.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "alertmanager", "status": Error}).Inc()
} else {
- c.Stats.Alertmanager.Add("ok", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "alertmanager", "status": "ok"}).Inc()
+ c.Stats.Alertmanager.Add(OK, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "alertmanager", "status": OK}).Inc()
}
- c.Stats.Alertmanager.Add("total", 1)
+ c.Stats.Alertmanager.Add(Total, 1)
}
diff --git a/outputs/alertmanager_test.go b/outputs/alertmanager_test.go
index db7ae4c6f5..1e1f6eb809 100644
--- a/outputs/alertmanager_test.go
+++ b/outputs/alertmanager_test.go
@@ -17,7 +17,7 @@ func TestNewAlertmanagerPayload(t *testing.T) {
var o1, o2 alertmanagerPayload
json.Unmarshal([]byte(expectedOutput), &o1)
- json.Unmarshal([]byte(s), &o2)
+ json.Unmarshal(s, &o2)
if !reflect.DeepEqual(o1, o2) {
// t.Fatalf("\nexpected payload: \n%v\ngot: \n%v\n", o1, o2)
diff --git a/outputs/aws.go b/outputs/aws.go
index 1a6eb19f93..fbfb40a590 100644
--- a/outputs/aws.go
+++ b/outputs/aws.go
@@ -1,190 +1,191 @@
-package outputs
-
-import (
- "encoding/base64"
- "encoding/json"
- "errors"
- "log"
- "net/url"
- "os"
-
- "github.com/DataDog/datadog-go/statsd"
- "github.com/aws/aws-sdk-go/aws"
- "github.com/aws/aws-sdk-go/aws/session"
- "github.com/aws/aws-sdk-go/service/lambda"
- "github.com/aws/aws-sdk-go/service/sns"
- "github.com/aws/aws-sdk-go/service/sqs"
- "github.com/aws/aws-sdk-go/service/sts"
- "github.com/falcosecurity/falcosidekick/types"
-)
-
-// NewAWSClient returns a new output.Client for accessing the AWS API.
-func NewAWSClient(config *types.Configuration, stats *types.Statistics, promStats *types.PromStatistics, statsdClient, dogstatsdClient *statsd.Client) (*Client, error) {
-
- if config.AWS.AccessKeyID != "" && config.AWS.SecretAccessKey != "" && config.AWS.Region != "" {
- os.Setenv("AWS_ACCESS_KEY_ID", config.AWS.AccessKeyID)
- os.Setenv("AWS_SECRET_ACCESS_KEY", config.AWS.SecretAccessKey)
- os.Setenv("AWS_DEFAULT_REGION", config.AWS.Region)
- }
-
- sess, err := session.NewSession(&aws.Config{
- Region: aws.String(config.AWS.Region)},
- )
- if err != nil {
- log.Printf("[ERROR] : AWS - %v\n", "Error while creating AWS Session")
- return nil, errors.New("Error while creating AWS Session")
- }
-
- _, err = sts.New(session.New()).GetCallerIdentity(&sts.GetCallerIdentityInput{})
- if err != nil {
- log.Printf("[ERROR] : AWS - %v\n", "Error while getting AWS Token")
- return nil, errors.New("Error while getting AWS Token")
- }
-
- var endpointURL *url.URL
- endpointURL, err = url.Parse(config.AWS.SQS.URL)
- if err != nil {
- log.Printf("[ERROR] : AWS SQS - %v\n", err.Error())
- return nil, ErrClientCreation
- }
-
- return &Client{
- OutputType: "AWS",
- EndpointURL: endpointURL,
- Config: config,
- AWSSession: sess,
- Stats: stats,
- PromStats: promStats,
- StatsdClient: statsdClient,
- DogstatsdClient: dogstatsdClient,
- }, nil
-}
-
-// InvokeLambda invokes a lambda function
-func (c *Client) InvokeLambda(falcopayload types.FalcoPayload) {
- svc := lambda.New(c.AWSSession)
-
- f, _ := json.Marshal(falcopayload)
-
- input := &lambda.InvokeInput{
- FunctionName: aws.String(c.Config.AWS.Lambda.FunctionName),
- InvocationType: aws.String(c.Config.AWS.Lambda.InvocationType),
- LogType: aws.String(c.Config.AWS.Lambda.LogType),
- Payload: f,
- }
-
- c.Stats.AWSLambda.Add("total", 1)
-
- resp, err := svc.Invoke(input)
- if err != nil {
- go c.CountMetric("outputs", 1, []string{"output:awslambda", "status:error"})
- c.Stats.AWSLambda.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "awslambda", "status": "error"}).Inc()
- log.Printf("[ERROR] : %v Lambda - %v\n", c.OutputType, err.Error())
- return
- }
-
- if c.Config.Debug == true {
- r, _ := base64.StdEncoding.DecodeString(*resp.LogResult)
- log.Printf("[DEBUG] : %v Lambda result : %v\n", c.OutputType, string(r))
- }
-
- log.Printf("[INFO] : %v Lambda - Invoke OK (%v)\n", c.OutputType, *resp.StatusCode)
- go c.CountMetric("outputs", 1, []string{"output:awslambda", "status:ok"})
- c.Stats.AWSLambda.Add("ok", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "awslambda", "status": "ok"}).Inc()
-}
-
-// SendMessage sends a message to SQS Queue
-func (c *Client) SendMessage(falcopayload types.FalcoPayload) {
- svc := sqs.New(c.AWSSession)
-
- f, _ := json.Marshal(falcopayload)
-
- input := &sqs.SendMessageInput{
- MessageBody: aws.String(string(f)),
- QueueUrl: aws.String(c.Config.AWS.SQS.URL),
- }
-
- c.Stats.AWSSQS.Add("total", 1)
-
- resp, err := svc.SendMessage(input)
- if err != nil {
- go c.CountMetric("outputs", 1, []string{"output:awssqs", "status:error"})
- c.Stats.AWSSQS.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "awssqs", "status": "error"}).Inc()
- log.Printf("[ERROR] : %v SQS - %v\n", c.OutputType, err.Error())
- return
- }
-
- if c.Config.Debug == true {
- log.Printf("[DEBUG] : %v SQS - MD5OfMessageBody : %v\n", c.OutputType, *resp.MD5OfMessageBody)
- }
-
- log.Printf("[INFO] : %v SQS - Send Message OK (%v)\n", c.OutputType, *resp.MessageId)
- go c.CountMetric("outputs", 1, []string{"output:awssqs", "status:ok"})
- c.Stats.AWSSQS.Add("ok", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "awssqs", "status": "ok"}).Inc()
-}
-
-// PublishTopic sends a message to a SNS Topic
-func (c *Client) PublishTopic(falcopayload types.FalcoPayload) {
- svc := sns.New(c.AWSSession)
-
- var msg *sns.PublishInput
-
- if c.Config.AWS.SNS.RawJSON == true {
- f, _ := json.Marshal(falcopayload)
- msg = &sns.PublishInput{
- Message: aws.String(string(f)),
- TopicArn: aws.String(c.Config.AWS.SNS.TopicArn),
- }
- } else {
- msg = &sns.PublishInput{
- Message: aws.String(string(falcopayload.Output)),
- MessageAttributes: map[string]*sns.MessageAttributeValue{
- "priority": &sns.MessageAttributeValue{
- DataType: aws.String("String"),
- StringValue: aws.String(falcopayload.Priority),
- },
- "rule": &sns.MessageAttributeValue{
- DataType: aws.String("String"),
- StringValue: aws.String(falcopayload.Rule),
- },
- },
- TopicArn: aws.String(c.Config.AWS.SNS.TopicArn),
- }
-
- for i, j := range falcopayload.OutputFields {
- switch j.(type) {
- case string:
- msg.MessageAttributes[i] = &sns.MessageAttributeValue{
- DataType: aws.String("String"),
- StringValue: aws.String(j.(string)),
- }
- default:
- continue
- }
- }
- }
-
- if c.Config.Debug == true {
- p, _ := json.Marshal(msg)
- log.Printf("[DEBUG] : %v SNS - Message : %v\n", c.OutputType, string(p))
- }
-
- c.Stats.AWSSNS.Add("total", 1)
- resp, err := svc.Publish(msg)
- if err != nil {
- go c.CountMetric("outputs", 1, []string{"output:awssns", "status:error"})
- c.Stats.AWSSNS.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "awssns", "status": "error"}).Inc()
- log.Printf("[ERROR] : %v - %v\n", c.OutputType, err.Error())
- return
- }
-
- log.Printf("[INFO] : %v SNS - Send to topic OK (%v)\n", c.OutputType, *resp.MessageId)
- go c.CountMetric("outputs", 1, []string{"output:awssns", "status:ok"})
- c.Stats.AWSSNS.Add("ok", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "awssns", "status": "ok"}).Inc()
-}
+package outputs
+
+import (
+ "encoding/base64"
+ "encoding/json"
+ "errors"
+ "log"
+ "net/url"
+ "os"
+
+ "github.com/falcosecurity/falcosidekick/types"
+
+ "github.com/DataDog/datadog-go/statsd"
+ "github.com/aws/aws-sdk-go/aws"
+ "github.com/aws/aws-sdk-go/aws/session"
+ "github.com/aws/aws-sdk-go/service/lambda"
+ "github.com/aws/aws-sdk-go/service/sns"
+ "github.com/aws/aws-sdk-go/service/sqs"
+ "github.com/aws/aws-sdk-go/service/sts"
+)
+
+// NewAWSClient returns a new output.Client for accessing the AWS API.
+func NewAWSClient(config *types.Configuration, stats *types.Statistics, promStats *types.PromStatistics, statsdClient, dogstatsdClient *statsd.Client) (*Client, error) {
+
+ if config.AWS.AccessKeyID != "" && config.AWS.SecretAccessKey != "" && config.AWS.Region != "" {
+ os.Setenv("AWS_ACCESS_KEY_ID", config.AWS.AccessKeyID)
+ os.Setenv("AWS_SECRET_ACCESS_KEY", config.AWS.SecretAccessKey)
+ os.Setenv("AWS_DEFAULT_REGION", config.AWS.Region)
+ }
+
+ sess, err := session.NewSession(&aws.Config{
+ Region: aws.String(config.AWS.Region)},
+ )
+ if err != nil {
+ log.Printf("[ERROR] : AWS - %v\n", "Error while creating AWS Session")
+ return nil, errors.New("Error while creating AWS Session")
+ }
+
+ _, err = sts.New(session.New()).GetCallerIdentity(&sts.GetCallerIdentityInput{})
+ if err != nil {
+ log.Printf("[ERROR] : AWS - %v\n", "Error while getting AWS Token")
+ return nil, errors.New("Error while getting AWS Token")
+ }
+
+ var endpointURL *url.URL
+ endpointURL, err = url.Parse(config.AWS.SQS.URL)
+ if err != nil {
+ log.Printf("[ERROR] : AWS SQS - %v\n", err.Error())
+ return nil, ErrClientCreation
+ }
+
+ return &Client{
+ OutputType: "AWS",
+ EndpointURL: endpointURL,
+ Config: config,
+ AWSSession: sess,
+ Stats: stats,
+ PromStats: promStats,
+ StatsdClient: statsdClient,
+ DogstatsdClient: dogstatsdClient,
+ }, nil
+}
+
+// InvokeLambda invokes a lambda function
+func (c *Client) InvokeLambda(falcopayload types.FalcoPayload) {
+ svc := lambda.New(c.AWSSession)
+
+ f, _ := json.Marshal(falcopayload)
+
+ input := &lambda.InvokeInput{
+ FunctionName: aws.String(c.Config.AWS.Lambda.FunctionName),
+ InvocationType: aws.String(c.Config.AWS.Lambda.InvocationType),
+ LogType: aws.String(c.Config.AWS.Lambda.LogType),
+ Payload: f,
+ }
+
+ c.Stats.AWSLambda.Add("total", 1)
+
+ resp, err := svc.Invoke(input)
+ if err != nil {
+ go c.CountMetric("outputs", 1, []string{"output:awslambda", "status:error"})
+ c.Stats.AWSLambda.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "awslambda", "status": Error}).Inc()
+ log.Printf("[ERROR] : %v Lambda - %v\n", c.OutputType, err.Error())
+ return
+ }
+
+ if c.Config.Debug == true {
+ r, _ := base64.StdEncoding.DecodeString(*resp.LogResult)
+ log.Printf("[DEBUG] : %v Lambda result : %v\n", c.OutputType, string(r))
+ }
+
+ log.Printf("[INFO] : %v Lambda - Invoke OK (%v)\n", c.OutputType, *resp.StatusCode)
+ go c.CountMetric("outputs", 1, []string{"output:awslambda", "status:ok"})
+ c.Stats.AWSLambda.Add("ok", 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "awslambda", "status": "ok"}).Inc()
+}
+
+// SendMessage sends a message to SQS Queue
+func (c *Client) SendMessage(falcopayload types.FalcoPayload) {
+ svc := sqs.New(c.AWSSession)
+
+ f, _ := json.Marshal(falcopayload)
+
+ input := &sqs.SendMessageInput{
+ MessageBody: aws.String(string(f)),
+ QueueUrl: aws.String(c.Config.AWS.SQS.URL),
+ }
+
+ c.Stats.AWSSQS.Add("total", 1)
+
+ resp, err := svc.SendMessage(input)
+ if err != nil {
+ go c.CountMetric("outputs", 1, []string{"output:awssqs", "status:error"})
+ c.Stats.AWSSQS.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "awssqs", "status": Error}).Inc()
+ log.Printf("[ERROR] : %v SQS - %v\n", c.OutputType, err.Error())
+ return
+ }
+
+ if c.Config.Debug == true {
+ log.Printf("[DEBUG] : %v SQS - MD5OfMessageBody : %v\n", c.OutputType, *resp.MD5OfMessageBody)
+ }
+
+ log.Printf("[INFO] : %v SQS - Send Message OK (%v)\n", c.OutputType, *resp.MessageId)
+ go c.CountMetric("outputs", 1, []string{"output:awssqs", "status:ok"})
+ c.Stats.AWSSQS.Add("ok", 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "awssqs", "status": "ok"}).Inc()
+}
+
+// PublishTopic sends a message to a SNS Topic
+func (c *Client) PublishTopic(falcopayload types.FalcoPayload) {
+ svc := sns.New(c.AWSSession)
+
+ var msg *sns.PublishInput
+
+ if c.Config.AWS.SNS.RawJSON == true {
+ f, _ := json.Marshal(falcopayload)
+ msg = &sns.PublishInput{
+ Message: aws.String(string(f)),
+ TopicArn: aws.String(c.Config.AWS.SNS.TopicArn),
+ }
+ } else {
+ msg = &sns.PublishInput{
+ Message: aws.String(falcopayload.Output),
+ MessageAttributes: map[string]*sns.MessageAttributeValue{
+ "priority": {
+ DataType: aws.String("String"),
+ StringValue: aws.String(falcopayload.Priority),
+ },
+ "rule": {
+ DataType: aws.String("String"),
+ StringValue: aws.String(falcopayload.Rule),
+ },
+ },
+ TopicArn: aws.String(c.Config.AWS.SNS.TopicArn),
+ }
+
+ for i, j := range falcopayload.OutputFields {
+ switch j.(type) {
+ case string:
+ msg.MessageAttributes[i] = &sns.MessageAttributeValue{
+ DataType: aws.String("String"),
+ StringValue: aws.String(j.(string)),
+ }
+ default:
+ continue
+ }
+ }
+ }
+
+ if c.Config.Debug == true {
+ p, _ := json.Marshal(msg)
+ log.Printf("[DEBUG] : %v SNS - Message : %v\n", c.OutputType, string(p))
+ }
+
+ c.Stats.AWSSNS.Add("total", 1)
+ resp, err := svc.Publish(msg)
+ if err != nil {
+ go c.CountMetric("outputs", 1, []string{"output:awssns", "status:error"})
+ c.Stats.AWSSNS.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "awssns", "status": Error}).Inc()
+ log.Printf("[ERROR] : %v - %v\n", c.OutputType, err.Error())
+ return
+ }
+
+ log.Printf("[INFO] : %v SNS - Send to topic OK (%v)\n", c.OutputType, *resp.MessageId)
+ go c.CountMetric("outputs", 1, []string{"output:awssns", "status:ok"})
+ c.Stats.AWSSNS.Add(OK, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "awssns", "status": OK}).Inc()
+}
diff --git a/outputs/azure.go b/outputs/azure.go
index 1dd9b5147e..588c50a4d7 100644
--- a/outputs/azure.go
+++ b/outputs/azure.go
@@ -28,8 +28,8 @@ func (c *Client) EventHubPost(falcopayload types.FalcoPayload) {
log.Printf("[INFO] : Try sending event")
hub, err := eventhub.NewHubWithNamespaceNameAndEnvironment(c.Config.Azure.EventHub.Namespace, c.Config.Azure.EventHub.Name)
if err != nil {
- c.Stats.AzureEventHub.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "azureeventhub", "status": "error"}).Inc()
+ c.Stats.AzureEventHub.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "azureeventhub", "status": Error}).Inc()
log.Printf("[ERROR] : %v EventHub - %v\n", c.OutputType, err.Error())
return
}
@@ -39,21 +39,21 @@ func (c *Client) EventHubPost(falcopayload types.FalcoPayload) {
defer cancel()
data, err := json.Marshal(falcopayload)
if err != nil {
- c.Stats.AzureEventHub.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "azureeventhub", "status": "error"}).Inc()
+ c.Stats.AzureEventHub.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "azureeventhub", "status": Error}).Inc()
log.Printf("[ERROR] : Cannot marshal payload: %v", err.Error())
return
}
err = hub.Send(ctx, eventhub.NewEvent(data))
if err != nil {
- c.Stats.AzureEventHub.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "azureeventhub", "status": "error"}).Inc()
+ c.Stats.AzureEventHub.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "azureeventhub", "status": Error}).Inc()
log.Printf("[ERROR] : %v EventHub - %v\n", c.OutputType, err.Error())
return
}
- c.Stats.AzureEventHub.Add("ok", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "azureeventhub", "status": "ok"}).Inc()
- log.Printf("[INFO] : Succesfully sent event")
+ c.Stats.AzureEventHub.Add(OK, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "azureeventhub", "status": OK}).Inc()
+ log.Printf("[INFO] : Successfully sent event")
- c.Stats.AzureEventHub.Add("total", 1)
+ c.Stats.AzureEventHub.Add(Total, 1)
}
diff --git a/outputs/client.go b/outputs/client.go
index dc636f91ff..a5fb9dab3f 100644
--- a/outputs/client.go
+++ b/outputs/client.go
@@ -12,9 +12,9 @@ import (
"regexp"
"strings"
+ "cloud.google.com/go/pubsub"
"github.com/DataDog/datadog-go/statsd"
"github.com/aws/aws-sdk-go/aws/session"
- "cloud.google.com/go/pubsub"
"github.com/falcosecurity/falcosidekick/types"
)
@@ -94,7 +94,10 @@ func (c *Client) Post(payload interface{}) error {
customTransport := http.DefaultTransport.(*http.Transport).Clone()
if c.Config.CheckCert == false {
- customTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
+ customTransport.TLSClientConfig = &tls.Config{
+ // nolint: gosec
+ InsecureSkipVerify: true,
+ }
}
client := &http.Client{
diff --git a/outputs/client_test.go b/outputs/client_test.go
index 1a0ffa37b9..55b42a325d 100644
--- a/outputs/client_test.go
+++ b/outputs/client_test.go
@@ -15,14 +15,17 @@ var falcoTestInput = `{"output":"This is a test from falcosidekick","priority":"
func TestNewClient(t *testing.T) {
u, _ := url.Parse("http://localhost")
+
config := &types.Configuration{}
stats := &types.Statistics{}
promStats := &types.PromStatistics{}
+
testClientOutput := Client{OutputType: "test", EndpointURL: u, Config: config, Stats: stats, PromStats: promStats}
_, err := NewClient("test", "localhost/%*$ยจ^!/:;", config, stats, promStats, nil, nil)
if err == nil {
t.Fatalf("error while creating client object : %v\n", err)
}
+
nc, _ := NewClient("test", "http://localhost", config, stats, promStats, nil, nil)
if !reflect.DeepEqual(&testClientOutput, nc) {
t.Fatalf("expected: %v, got: %v\n", testClientOutput, nc)
@@ -56,7 +59,15 @@ func TestPost(t *testing.T) {
nc, _ := NewClient("", "", &types.Configuration{}, &types.Statistics{}, &types.PromStatistics{}, nil, nil)
- for i, j := range map[string]error{"/200": nil, "/400": ErrHeaderMissing, "/401": ErrClientAuthenticationError, "/403": ErrForbidden, "/404": ErrNotFound, "/422": ErrUnprocessableEntityError, "/429": ErrTooManyRequest, "/502": errors.New("502 Bad Gateway")} {
+ for i, j := range map[string]error{
+ "/200": nil, "/400": ErrHeaderMissing,
+ "/401": ErrClientAuthenticationError,
+ "/403": ErrForbidden,
+ "/404": ErrNotFound,
+ "/422": ErrUnprocessableEntityError,
+ "/429": ErrTooManyRequest,
+ "/502": errors.New("502 Bad Gateway"),
+ } {
nc, _ = NewClient("", ts.URL+i, &types.Configuration{}, &types.Statistics{}, &types.PromStatistics{}, nil, nil)
err := nc.Post("")
if !reflect.DeepEqual(err, j) {
diff --git a/outputs/constants.go b/outputs/constants.go
new file mode 100644
index 0000000000..4550ea0634
--- /dev/null
+++ b/outputs/constants.go
@@ -0,0 +1,35 @@
+package outputs
+
+const (
+ OK string = "ok"
+ Warning string = "warning"
+ Alert string = "alert"
+ Error string = "error"
+ Critical string = "critical"
+ Emergency string = "emergency"
+ Notice string = "notice"
+ Informational string = "informational"
+ Debug string = "debug"
+ Info string = "info"
+ None string = "none"
+
+ All string = "all"
+ Fields string = "fields"
+ Total string = "total"
+
+ Rule string = "rule"
+ Priority string = "priority"
+ Time string = "time"
+ Text string = "text"
+
+ DefaultFooter string = "https://github.com/falcosecurity/falcosidekick"
+ DefaultIconURL string = "https://raw.githubusercontent.com/falcosecurity/falcosidekick/master/imgs/falcosidekick.png"
+
+ // Colors
+ PaleCyan string = "#ccfff2"
+ Yellow string = "#ffc700"
+ Red string = "#e20b0b"
+ LigthBlue string = "#68c2ff"
+ Lightcyan string = "#5bffb5"
+ Orange string = "#ff5400"
+)
diff --git a/outputs/datadog.go b/outputs/datadog.go
index bbafa08be4..485fbef561 100644
--- a/outputs/datadog.go
+++ b/outputs/datadog.go
@@ -39,12 +39,12 @@ func newDatadogPayload(falcopayload types.FalcoPayload) datadogPayload {
var status string
switch strings.ToLower(falcopayload.Priority) {
- case "emergency", "alert", "critical", "error":
- status = "error"
- case "warning":
- status = "warning"
+ case Emergency, Alert, Critical, Error:
+ status = Error
+ case Warning:
+ status = Warning
default:
- status = "info"
+ status = Info
}
d.AlertType = status
@@ -55,11 +55,11 @@ func newDatadogPayload(falcopayload types.FalcoPayload) datadogPayload {
func (c *Client) DatadogPost(falcopayload types.FalcoPayload) {
err := c.Post(newDatadogPayload(falcopayload))
if err != nil {
- c.Stats.Datadog.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "datadog", "status": "error"}).Inc()
+ c.Stats.Datadog.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "datadog", "status": Error}).Inc()
} else {
- c.Stats.Datadog.Add("ok", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "datadog", "status": "ok"}).Inc()
+ c.Stats.Datadog.Add(OK, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "datadog", "status": OK}).Inc()
}
- c.Stats.Datadog.Add("total", 1)
+ c.Stats.Datadog.Add(Total, 1)
}
diff --git a/outputs/datadog_test.go b/outputs/datadog_test.go
index 7af24310fc..ee5f167d27 100644
--- a/outputs/datadog_test.go
+++ b/outputs/datadog_test.go
@@ -17,10 +17,9 @@ func TestNewDatadogPayload(t *testing.T) {
var o1, o2 datadogPayload
json.Unmarshal([]byte(expectedOutput), &o1)
- json.Unmarshal([]byte(s), &o2)
+ json.Unmarshal(s, &o2)
if !reflect.DeepEqual(o1, o2) {
- // t.Fatalf("\nexpected payload: \n%v\ngot: \n%v\n", o1, o2)
t.Fatalf("\nexpected payload: \n%v\ngot: \n%v\n", expectedOutput, string(s))
}
}
diff --git a/outputs/discord.go b/outputs/discord.go
index 1d946bf7a6..d9a7096ea3 100644
--- a/outputs/discord.go
+++ b/outputs/discord.go
@@ -31,26 +31,26 @@ func newDiscordPayload(falcopayload types.FalcoPayload, config *types.Configurat
if config.Discord.Icon != "" {
iconURL = config.Discord.Icon
} else {
- iconURL = "https://raw.githubusercontent.com/falcosecurity/falcosidekick/master/imgs/falcosidekick.png"
+ iconURL = DefaultIconURL
}
var color string
switch strings.ToLower(falcopayload.Priority) {
- case "emergency":
+ case Emergency:
color = "15158332" // red
- case "alert":
+ case Alert:
color = "11027200" // dark orange
- case "critical":
+ case Critical:
color = "15105570" // orange
- case "error":
+ case Error:
color = "15844367" // gold
- case "warning":
+ case Warning:
color = "12745742" // dark gold
- case "notice":
+ case Notice:
color = "3066993" // teal
- case "informational":
+ case Informational:
color = "3447003" // blue
- case "debug":
+ case Debug:
color = "12370112" // light grey
}
@@ -70,15 +70,15 @@ func newDiscordPayload(falcopayload types.FalcoPayload, config *types.Configurat
}
embedFields = append(embedFields, embedField)
}
- embedField.Name = "rule"
+ embedField.Name = Rule
embedField.Value = falcopayload.Rule
embedField.Inline = true
embedFields = append(embedFields, embedField)
- embedField.Name = "priority"
+ embedField.Name = Priority
embedField.Value = falcopayload.Priority
embedField.Inline = true
embedFields = append(embedFields, embedField)
- embedField.Name = "time"
+ embedField.Name = Time
embedField.Value = falcopayload.Time.String()
embedField.Inline = true
embedFields = append(embedFields, embedField)
@@ -103,11 +103,11 @@ func newDiscordPayload(falcopayload types.FalcoPayload, config *types.Configurat
func (c *Client) DiscordPost(falcopayload types.FalcoPayload) {
err := c.Post(newDiscordPayload(falcopayload, c.Config))
if err != nil {
- c.Stats.Discord.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "discord", "status": "error"}).Inc()
+ c.Stats.Discord.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "discord", "status": Error}).Inc()
} else {
- c.Stats.Discord.Add("ok", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "azureeventhub", "status": "ok"}).Inc()
+ c.Stats.Discord.Add(OK, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "azureeventhub", "status": OK}).Inc()
}
- c.Stats.Discord.Add("total", 1)
+ c.Stats.Discord.Add(Total, 1)
}
diff --git a/outputs/elasticsearch.go b/outputs/elasticsearch.go
index 2dfc50f3c5..7b14d18608 100644
--- a/outputs/elasticsearch.go
+++ b/outputs/elasticsearch.go
@@ -22,18 +22,21 @@ func (c *Client) ElasticsearchPost(falcopayload types.FalcoPayload) {
default:
eURL = c.Config.Elasticsearch.HostPort + "/" + c.Config.Elasticsearch.Index + "-" + current.Format("2006.01.02") + "/" + c.Config.Elasticsearch.Type
}
+
endpointURL, err := url.Parse(eURL)
if err != nil {
log.Printf("[ERROR] : %v - %v\n", c.OutputType, err.Error())
}
+
c.EndpointURL = endpointURL
err = c.Post(falcopayload)
if err != nil {
- c.Stats.Elasticsearch.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "elasticsearch", "status": "error"}).Inc()
+ c.Stats.Elasticsearch.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "elasticsearch", "status": Error}).Inc()
} else {
- c.Stats.Elasticsearch.Add("ok", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "elasticsearch", "status": "ok"}).Inc()
+ c.Stats.Elasticsearch.Add(OK, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "elasticsearch", "status": OK}).Inc()
}
- c.Stats.Elasticsearch.Add("total", 1)
+
+ c.Stats.Elasticsearch.Add(Total, 1)
}
diff --git a/outputs/gcp.go b/outputs/gcp.go
index 088d60b3fc..ceb86ee86f 100644
--- a/outputs/gcp.go
+++ b/outputs/gcp.go
@@ -1,16 +1,17 @@
package outputs
import (
- "cloud.google.com/go/pubsub"
"context"
"encoding/base64"
"encoding/json"
"errors"
+ "log"
+
+ "cloud.google.com/go/pubsub"
"github.com/DataDog/datadog-go/statsd"
"github.com/falcosecurity/falcosidekick/types"
"golang.org/x/oauth2/google"
"google.golang.org/api/option"
- "log"
)
// NewGCPClient returns a new output.Client for accessing the GCP API.
@@ -20,6 +21,7 @@ func NewGCPClient(config *types.Configuration, stats *types.Statistics, promStat
log.Printf("[ERROR] : GCP - %v\n", "Error while base64-decoding GCP Credentials")
return nil, errors.New("Error while base64-decoding GCP Credentials")
}
+
googleCredentialsData := string(base64decodedCredentialsData)
var topicClient *pubsub.Topic
@@ -36,6 +38,7 @@ func NewGCPClient(config *types.Configuration, stats *types.Statistics, promStat
}
topicClient = pubSubClient.Topic(config.GCP.PubSub.Topic)
}
+
return &Client{
OutputType: "GCP",
Config: config,
@@ -49,23 +52,26 @@ func NewGCPClient(config *types.Configuration, stats *types.Statistics, promStat
// GCPPublishTopic sends a message to a GCP PubSub Topic
func (c *Client) GCPPublishTopic(falcopayload types.FalcoPayload) {
- c.Stats.GCPPubSub.Add("total", 1)
+ c.Stats.GCPPubSub.Add(Total, 1)
payload, _ := json.Marshal(falcopayload)
message := &pubsub.Message{
Data: payload,
}
+
result := c.GCPTopicClient.Publish(context.Background(), message)
id, err := result.Get(context.Background())
if err != nil {
log.Printf("[ERROR] : GCPPubSub - %v - %v\n", "Error while publishing message", err.Error())
- c.Stats.GCPPubSub.Add("error", 1)
+ c.Stats.GCPPubSub.Add(Error, 1)
go c.CountMetric("outputs", 1, []string{"output:gcppubsub", "status:error"})
- c.PromStats.Outputs.With(map[string]string{"destination": "gcppubsub", "status": "error"}).Inc()
+ c.PromStats.Outputs.With(map[string]string{"destination": "gcppubsub", "status": Error}).Inc()
+
return
}
+
log.Printf("[INFO] : GCPPubSub - Send to topic OK (%v)\n", id)
- c.Stats.GCPPubSub.Add("ok", 1)
+ c.Stats.GCPPubSub.Add(OK, 1)
go c.CountMetric("outputs", 1, []string{"output:gcppubsub", "status:ok"})
- c.PromStats.Outputs.With(map[string]string{"destination": "gcppubsub", "status": "ok"}).Inc()
+ c.PromStats.Outputs.With(map[string]string{"destination": "gcppubsub", "status": OK}).Inc()
}
diff --git a/outputs/influxdb.go b/outputs/influxdb.go
index 733889a3bd..25f1f78cff 100644
--- a/outputs/influxdb.go
+++ b/outputs/influxdb.go
@@ -1,41 +1,40 @@
-package outputs
-
-import (
- "strings"
-
- "github.com/falcosecurity/falcosidekick/types"
-)
-
-type influxdbPayload string
-
-func newInfluxdbPayload(falcopayload types.FalcoPayload, config *types.Configuration) influxdbPayload {
- var s string
-
- s = "events,rule=" + strings.Replace(falcopayload.Rule, " ", "_", -1) + ",priority=" + strings.Replace(falcopayload.Priority, " ", "_", -1)
-
- for i, j := range falcopayload.OutputFields {
- switch j.(type) {
- case string:
- s += "," + i + "=" + strings.Replace(j.(string), " ", "_", -1)
- default:
- continue
- }
- }
-
- s += " value=\"" + falcopayload.Output + "\""
-
- return influxdbPayload(s)
-}
-
-// InfluxdbPost posts event to InfluxDB
-func (c *Client) InfluxdbPost(falcopayload types.FalcoPayload) {
- err := c.Post(newInfluxdbPayload(falcopayload, c.Config))
- if err != nil {
- c.Stats.Influxdb.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "influxdb", "status": "error"}).Inc()
- } else {
- c.Stats.Influxdb.Add("ok", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "influxdb", "status": "ok"}).Inc()
- }
- c.Stats.Influxdb.Add("total", 1)
-}
+package outputs
+
+import (
+ "strings"
+
+ "github.com/falcosecurity/falcosidekick/types"
+)
+
+type influxdbPayload string
+
+func newInfluxdbPayload(falcopayload types.FalcoPayload, config *types.Configuration) influxdbPayload {
+ s := "events,rule=" + strings.Replace(falcopayload.Rule, " ", "_", -1) + ",priority=" + strings.Replace(falcopayload.Priority, " ", "_", -1)
+
+ for i, j := range falcopayload.OutputFields {
+ switch j.(type) {
+ case string:
+ s += "," + i + "=" + strings.Replace(j.(string), " ", "_", -1)
+ default:
+ continue
+ }
+ }
+
+ s += " value=\"" + falcopayload.Output + "\""
+
+ return influxdbPayload(s)
+}
+
+// InfluxdbPost posts event to InfluxDB
+func (c *Client) InfluxdbPost(falcopayload types.FalcoPayload) {
+ err := c.Post(newInfluxdbPayload(falcopayload, c.Config))
+ if err != nil {
+ c.Stats.Influxdb.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "influxdb", "status": Error}).Inc()
+ } else {
+ c.Stats.Influxdb.Add(OK, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "influxdb", "status": OK}).Inc()
+ }
+
+ c.Stats.Influxdb.Add(Total, 1)
+}
diff --git a/outputs/influxdb_test.go b/outputs/influxdb_test.go
index 2f515acadc..da0e5b68e3 100644
--- a/outputs/influxdb_test.go
+++ b/outputs/influxdb_test.go
@@ -1,21 +1,20 @@
-package outputs
-
-import (
- "encoding/json"
- "testing"
-
- "github.com/falcosecurity/falcosidekick/types"
-)
-
-func TestNewInfluxdbPayload(t *testing.T) {
- expectedOutput := `"events,rule=Test_rule,priority=Debug,proc.name=falcosidekick value=\"This is a test from falcosidekick\""`
-
- var f types.FalcoPayload
- json.Unmarshal([]byte(falcoTestInput), &f)
- influxdbPayload, _ := json.Marshal(newInfluxdbPayload(f, &types.Configuration{}))
-
- if string(influxdbPayload) != expectedOutput {
- // t.Fatalf("\nexpected payload: \n%v\ngot: \n%v\n", o1, o2)
- t.Fatalf("\nexpected payload: \n%v\ngot: \n%v\n", expectedOutput, string(influxdbPayload))
- }
-}
+package outputs
+
+import (
+ "encoding/json"
+ "testing"
+
+ "github.com/falcosecurity/falcosidekick/types"
+)
+
+func TestNewInfluxdbPayload(t *testing.T) {
+ expectedOutput := `"events,rule=Test_rule,priority=Debug,proc.name=falcosidekick value=\"This is a test from falcosidekick\""`
+
+ var f types.FalcoPayload
+ json.Unmarshal([]byte(falcoTestInput), &f)
+ influxdbPayload, _ := json.Marshal(newInfluxdbPayload(f, &types.Configuration{}))
+
+ if string(influxdbPayload) != expectedOutput {
+ t.Fatalf("\nexpected payload: \n%v\ngot: \n%v\n", expectedOutput, string(influxdbPayload))
+ }
+}
diff --git a/outputs/loki.go b/outputs/loki.go
index 90b2ce574d..7350965689 100644
--- a/outputs/loki.go
+++ b/outputs/loki.go
@@ -22,7 +22,6 @@ type lokiEntry struct {
}
func newLokiPayload(falcopayload types.FalcoPayload, config *types.Configuration) lokiPayload {
-
le := lokiEntry{Ts: falcopayload.Time.Format(time.RFC3339), Line: falcopayload.Output}
ls := lokiStream{Entries: []lokiEntry{le}}
@@ -35,6 +34,7 @@ func newLokiPayload(falcopayload types.FalcoPayload, config *types.Configuration
continue
}
}
+
s += "rule=\"" + falcopayload.Rule + "\","
s += "priority=\"" + falcopayload.Priority + "\","
@@ -47,11 +47,12 @@ func newLokiPayload(falcopayload types.FalcoPayload, config *types.Configuration
func (c *Client) LokiPost(falcopayload types.FalcoPayload) {
err := c.Post(newLokiPayload(falcopayload, c.Config))
if err != nil {
- c.Stats.Loki.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "loki", "status": "error"}).Inc()
+ c.Stats.Loki.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "loki", "status": Error}).Inc()
} else {
- c.Stats.Loki.Add("ok", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "loki", "status": "ok"}).Inc()
+ c.Stats.Loki.Add(OK, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "loki", "status": OK}).Inc()
}
- c.Stats.Loki.Add("total", 1)
+
+ c.Stats.Loki.Add(Total, 1)
}
diff --git a/outputs/loki_test.go b/outputs/loki_test.go
index 79c9676bfa..7e970fe929 100644
--- a/outputs/loki_test.go
+++ b/outputs/loki_test.go
@@ -1,32 +1,33 @@
-package outputs
-
-import (
- "encoding/json"
- "reflect"
- "testing"
-
- "github.com/falcosecurity/falcosidekick/types"
-)
-
-func TestNewLokiPayload(t *testing.T) {
- expectedOutput := lokiPayload{
- Streams: []lokiStream{
- lokiStream{
- Labels: "{procname=\"falcosidekick\",rule=\"Test rule\",priority=\"Debug\"}",
- Entries: []lokiEntry{
- lokiEntry{
- Ts: "2001-01-01T01:10:00Z",
- Line: "This is a test from falcosidekick",
- },
- },
- },
- },
- }
-
- var f types.FalcoPayload
- json.Unmarshal([]byte(falcoTestInput), &f)
- output := newLokiPayload(f, &types.Configuration{})
- if !reflect.DeepEqual(output, expectedOutput) {
- t.Fatalf("\nexpected payload: \n%#v\ngot: \n%#v\n", expectedOutput, output)
- }
-}
+package outputs
+
+import (
+ "encoding/json"
+ "reflect"
+ "testing"
+
+ "github.com/falcosecurity/falcosidekick/types"
+)
+
+func TestNewLokiPayload(t *testing.T) {
+ expectedOutput := lokiPayload{
+ Streams: []lokiStream{
+ {
+ Labels: "{procname=\"falcosidekick\",rule=\"Test rule\",priority=\"Debug\"}",
+ Entries: []lokiEntry{
+ {
+ Ts: "2001-01-01T01:10:00Z",
+ Line: "This is a test from falcosidekick",
+ },
+ },
+ },
+ },
+ }
+
+ var f types.FalcoPayload
+ json.Unmarshal([]byte(falcoTestInput), &f)
+ output := newLokiPayload(f, &types.Configuration{})
+
+ if !reflect.DeepEqual(output, expectedOutput) {
+ t.Fatalf("\nexpected payload: \n%#v\ngot: \n%#v\n", expectedOutput, output)
+ }
+}
diff --git a/outputs/mattermost.go b/outputs/mattermost.go
index fd7a5fd87e..8087fad7fa 100644
--- a/outputs/mattermost.go
+++ b/outputs/mattermost.go
@@ -15,7 +15,7 @@ func newMattermostPayload(falcopayload types.FalcoPayload, config *types.Configu
var fields []slackAttachmentField
var field slackAttachmentField
- if config.Mattermost.OutputFormat == "all" || config.Mattermost.OutputFormat == "fields" || config.Mattermost.OutputFormat == "" {
+ if config.Mattermost.OutputFormat == All || config.Mattermost.OutputFormat == Fields || config.Mattermost.OutputFormat == "" {
for i, j := range falcopayload.OutputFields {
switch j.(type) {
case string:
@@ -48,7 +48,7 @@ func newMattermostPayload(falcopayload types.FalcoPayload, config *types.Configu
attachment.Fallback = falcopayload.Output
attachment.Fields = fields
- if config.Mattermost.OutputFormat == "all" || config.Mattermost.OutputFormat == "fields" || config.Mattermost.OutputFormat == "" {
+ if config.Mattermost.OutputFormat == All || config.Mattermost.OutputFormat == Fields || config.Mattermost.OutputFormat == "" {
attachment.Text = falcopayload.Output
}
@@ -64,27 +64,27 @@ func newMattermostPayload(falcopayload types.FalcoPayload, config *types.Configu
var color string
switch strings.ToLower(falcopayload.Priority) {
case "emergency":
- color = "#e20b0b"
- case "alert":
- color = "#ff5400"
- case "critical":
- color = "#ff9000"
- case "error":
- color = "#ffc700"
- case "warning":
- color = "#ffff00"
- case "notice":
- color = "#5bffb5"
- case "informational":
- color = "#68c2ff"
- case "debug":
- color = "#ccfff2"
+ color = Red
+ case Alert:
+ color = Orange
+ case Critical:
+ color = Orange
+ case Error:
+ color = Red
+ case Warning:
+ color = Yellow
+ case Notice:
+ color = Lightcyan
+ case Informational:
+ color = LigthBlue
+ case Debug:
+ color = PaleCyan
}
attachment.Color = color
attachments = append(attachments, attachment)
- iconURL := "https://raw.githubusercontent.com/falcosecurity/falcosidekick/master/imgs/falcosidekick.png"
+ iconURL := DefaultIconURL
if config.Mattermost.Icon != "" {
iconURL = config.Mattermost.Icon
}
@@ -102,11 +102,12 @@ func newMattermostPayload(falcopayload types.FalcoPayload, config *types.Configu
func (c *Client) MattermostPost(falcopayload types.FalcoPayload) {
err := c.Post(newMattermostPayload(falcopayload, c.Config))
if err != nil {
- c.Stats.Rocketchat.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "mattermost", "status": "error"}).Inc()
+ c.Stats.Rocketchat.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "mattermost", "status": Error}).Inc()
} else {
- c.Stats.Rocketchat.Add("ok", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "mattermost", "status": "ok"}).Inc()
+ c.Stats.Rocketchat.Add(OK, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "mattermost", "status": OK}).Inc()
}
- c.Stats.Rocketchat.Add("total", 1)
+
+ c.Stats.Rocketchat.Add(Total, 1)
}
diff --git a/outputs/nats.go b/outputs/nats.go
index 54fc721504..90a2abef82 100644
--- a/outputs/nats.go
+++ b/outputs/nats.go
@@ -1,44 +1,46 @@
-package outputs
-
-import (
- "encoding/json"
- "log"
- "regexp"
- "strings"
-
- "github.com/falcosecurity/falcosidekick/types"
- nats "github.com/nats-io/nats.go"
-)
-
-var slugRegularExpression = regexp.MustCompile("[^a-z0-9]+")
-
-// NatsPublish publishes event to NATS
-func (c *Client) NatsPublish(falcopayload types.FalcoPayload) {
- nc, err := nats.Connect(c.EndpointURL.String())
- if err != nil {
- go c.CountMetric("outputs", 1, []string{"output:nats", "status:error"})
- c.Stats.Nats.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "nats", "status": "error"}).Inc()
- c.Stats.Nats.Add("total", 1)
- log.Printf("[ERROR] : NATS - %v\n", err)
- return
- }
-
- r := strings.Trim(slugRegularExpression.ReplaceAllString(strings.ToLower(falcopayload.Rule), "_"), "_")
- j, _ := json.Marshal(falcopayload)
- err = nc.Publish("falco."+strings.ToLower(falcopayload.Priority)+"."+r, j)
- nc.Flush()
- nc.Close()
- if err != nil {
- go c.CountMetric("outputs", 1, []string{"output:nats", "status:error"})
- c.Stats.Nats.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "nats", "status": "error"}).Inc()
- log.Printf("[ERROR] : NATS - %v\n", err)
- } else {
- go c.CountMetric("outputs", 1, []string{"output:nats", "status:ok"})
- c.Stats.Nats.Add("ok", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "nats", "status": "ok"}).Inc()
- log.Printf("[INFO] : NATS - Publish OK\n")
- }
- c.Stats.Nats.Add("total", 1)
-}
+package outputs
+
+import (
+ "encoding/json"
+ "log"
+ "regexp"
+ "strings"
+
+ "github.com/falcosecurity/falcosidekick/types"
+ nats "github.com/nats-io/nats.go"
+)
+
+var slugRegularExpression = regexp.MustCompile("[^a-z0-9]+")
+
+// NatsPublish publishes event to NATS
+func (c *Client) NatsPublish(falcopayload types.FalcoPayload) {
+ nc, err := nats.Connect(c.EndpointURL.String())
+ if err != nil {
+ go c.CountMetric("outputs", 1, []string{"output:nats", "status:error"})
+ c.Stats.Nats.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "nats", "status": Error}).Inc()
+ c.Stats.Nats.Add("total", 1)
+ log.Printf("[ERROR] : NATS - %v\n", err)
+ return
+ }
+
+ r := strings.Trim(slugRegularExpression.ReplaceAllString(strings.ToLower(falcopayload.Rule), "_"), "_")
+ j, _ := json.Marshal(falcopayload)
+
+ err = nc.Publish("falco."+strings.ToLower(falcopayload.Priority)+"."+r, j)
+ if err != nil {
+ go c.CountMetric("outputs", 1, []string{"output:nats", "status:error"})
+ c.Stats.Nats.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "nats", "status": Error}).Inc()
+ log.Printf("[ERROR] : NATS - %v\n", err)
+ } else {
+ go c.CountMetric("outputs", 1, []string{"output:nats", "status:ok"})
+ c.Stats.Nats.Add(OK, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "nats", "status": OK}).Inc()
+ log.Printf("[INFO] : NATS - Publish OK\n")
+ }
+ defer nc.Flush()
+ defer nc.Close()
+
+ c.Stats.Nats.Add(Total, 1)
+}
diff --git a/outputs/opsgenie.go b/outputs/opsgenie.go
index abbf607adb..66e4c8c522 100644
--- a/outputs/opsgenie.go
+++ b/outputs/opsgenie.go
@@ -27,13 +27,13 @@ func newOpsgeniePayload(falcopayload types.FalcoPayload, config *types.Configura
var prio string
switch strings.ToLower(falcopayload.Priority) {
- case "emergency", "alert":
+ case "emergency", Alert:
prio = "P1"
- case "critical":
+ case Critical:
prio = "P2"
- case "error":
+ case Error:
prio = "P3"
- case "warning":
+ case Warning:
prio = "P4"
default:
prio = "P5"
@@ -52,11 +52,12 @@ func newOpsgeniePayload(falcopayload types.FalcoPayload, config *types.Configura
func (c *Client) OpsgeniePost(falcopayload types.FalcoPayload) {
err := c.Post(newOpsgeniePayload(falcopayload, c.Config))
if err != nil {
- c.Stats.Opsgenie.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "opsgenie", "status": "error"}).Inc()
+ c.Stats.Opsgenie.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "opsgenie", "status": Error}).Inc()
} else {
c.Stats.Opsgenie.Add("ok", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "opsgenie", "status": "ok"}).Inc()
+ c.PromStats.Outputs.With(map[string]string{"destination": "opsgenie", "status": OK}).Inc()
}
- c.Stats.Opsgenie.Add("total", 1)
+
+ c.Stats.Opsgenie.Add(Total, 1)
}
diff --git a/outputs/opsgenie_test.go b/outputs/opsgenie_test.go
index f9b48f0bb4..297693d9f9 100644
--- a/outputs/opsgenie_test.go
+++ b/outputs/opsgenie_test.go
@@ -1,28 +1,29 @@
-package outputs
-
-import (
- "encoding/json"
- "reflect"
- "testing"
-
- "github.com/falcosecurity/falcosidekick/types"
-)
-
-func TestNewOpsgeniePayload(t *testing.T) {
- expectedOutput := opsgeniePayload{
- Message: "This is a test from falcosidekick",
- Entity: "Falcosidekick",
- Description: "Test rule",
- Details: map[string]string{
- "proc.name": "falcosidekick",
- },
- Priority: "P5",
- }
-
- var f types.FalcoPayload
- json.Unmarshal([]byte(falcoTestInput), &f)
- output := newOpsgeniePayload(f, &types.Configuration{})
- if !reflect.DeepEqual(output, expectedOutput) {
- t.Fatalf("\nexpected payload: \n%#v\ngot: \n%#v\n", expectedOutput, output)
- }
-}
+package outputs
+
+import (
+ "encoding/json"
+ "reflect"
+ "testing"
+
+ "github.com/falcosecurity/falcosidekick/types"
+)
+
+func TestNewOpsgeniePayload(t *testing.T) {
+ expectedOutput := opsgeniePayload{
+ Message: "This is a test from falcosidekick",
+ Entity: "Falcosidekick",
+ Description: "Test rule",
+ Details: map[string]string{
+ "proc.name": "falcosidekick",
+ },
+ Priority: "P5",
+ }
+
+ var f types.FalcoPayload
+ json.Unmarshal([]byte(falcoTestInput), &f)
+ output := newOpsgeniePayload(f, &types.Configuration{})
+
+ if !reflect.DeepEqual(output, expectedOutput) {
+ t.Fatalf("\nexpected payload: \n%#v\ngot: \n%#v\n", expectedOutput, output)
+ }
+}
diff --git a/outputs/rocketchat.go b/outputs/rocketchat.go
index 3a88e06d3e..b69845bcfa 100644
--- a/outputs/rocketchat.go
+++ b/outputs/rocketchat.go
@@ -15,7 +15,7 @@ func newRocketchatPayload(falcopayload types.FalcoPayload, config *types.Configu
var fields []slackAttachmentField
var field slackAttachmentField
- if config.Rocketchat.OutputFormat == "all" || config.Rocketchat.OutputFormat == "fields" || config.Rocketchat.OutputFormat == "" {
+ if config.Rocketchat.OutputFormat == All || config.Rocketchat.OutputFormat == Fields || config.Rocketchat.OutputFormat == "" {
for i, j := range falcopayload.OutputFields {
switch j.(type) {
case string:
@@ -32,15 +32,15 @@ func newRocketchatPayload(falcopayload types.FalcoPayload, config *types.Configu
fields = append(fields, field)
}
- field.Title = "rule"
+ field.Title = Rule
field.Value = falcopayload.Rule
field.Short = true
fields = append(fields, field)
- field.Title = "priority"
+ field.Title = Priority
field.Value = falcopayload.Priority
field.Short = true
fields = append(fields, field)
- field.Title = "time"
+ field.Title = Time
field.Short = false
field.Value = falcopayload.Time.String()
fields = append(fields, field)
@@ -48,7 +48,7 @@ func newRocketchatPayload(falcopayload types.FalcoPayload, config *types.Configu
attachment.Fallback = falcopayload.Output
attachment.Fields = fields
- if config.Rocketchat.OutputFormat == "all" || config.Rocketchat.OutputFormat == "fields" || config.Rocketchat.OutputFormat == "" {
+ if config.Rocketchat.OutputFormat == All || config.Rocketchat.OutputFormat == Fields || config.Rocketchat.OutputFormat == "" {
attachment.Text = falcopayload.Output
}
@@ -61,32 +61,32 @@ func newRocketchatPayload(falcopayload types.FalcoPayload, config *types.Configu
}
}
- if config.Rocketchat.OutputFormat == "all" || config.Rocketchat.OutputFormat == "fields" || config.Rocketchat.OutputFormat == "" {
+ if config.Rocketchat.OutputFormat == All || config.Rocketchat.OutputFormat == Fields || config.Rocketchat.OutputFormat == "" {
var color string
switch strings.ToLower(falcopayload.Priority) {
- case "emergency":
- color = "#e20b0b"
- case "alert":
- color = "#ff5400"
- case "critical":
- color = "#ff9000"
- case "error":
- color = "#ffc700"
- case "warning":
- color = "#ffff00"
- case "notice":
- color = "#5bffb5"
- case "informational":
- color = "#68c2ff"
- case "debug":
- color = "#ccfff2"
+ case Emergency:
+ color = Red
+ case Alert:
+ color = Orange
+ case Critical:
+ color = Orange
+ case Error:
+ color = Red
+ case Warning:
+ color = Yellow
+ case Notice:
+ color = Lightcyan
+ case Informational:
+ color = LigthBlue
+ case Debug:
+ color = PaleCyan
}
attachment.Color = color
attachments = append(attachments, attachment)
}
- iconURL := "https://raw.githubusercontent.com/falcosecurity/falcosidekick/master/imgs/falcosidekick.png"
+ iconURL := DefaultIconURL
if config.Rocketchat.Icon != "" {
iconURL = config.Rocketchat.Icon
}
@@ -104,11 +104,12 @@ func newRocketchatPayload(falcopayload types.FalcoPayload, config *types.Configu
func (c *Client) RocketchatPost(falcopayload types.FalcoPayload) {
err := c.Post(newRocketchatPayload(falcopayload, c.Config))
if err != nil {
- c.Stats.Rocketchat.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "rocketchat", "status": "error"}).Inc()
+ c.Stats.Rocketchat.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "rocketchat", "status": Error}).Inc()
} else {
- c.Stats.Rocketchat.Add("ok", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "rocketchat", "status": "ok"}).Inc()
+ c.Stats.Rocketchat.Add(OK, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "rocketchat", "status": OK}).Inc()
}
- c.Stats.Rocketchat.Add("total", 1)
+
+ c.Stats.Rocketchat.Add(Total, 1)
}
diff --git a/outputs/slack.go b/outputs/slack.go
index 5cdb4aa6e2..dba4b5df7f 100644
--- a/outputs/slack.go
+++ b/outputs/slack.go
@@ -40,7 +40,7 @@ func newSlackPayload(falcopayload types.FalcoPayload, config *types.Configuratio
var fields []slackAttachmentField
var field slackAttachmentField
- if config.Slack.OutputFormat == "all" || config.Slack.OutputFormat == "fields" || config.Slack.OutputFormat == "" {
+ if config.Slack.OutputFormat == All || config.Slack.OutputFormat == Fields || config.Slack.OutputFormat == "" {
for i, j := range falcopayload.OutputFields {
switch j.(type) {
case string:
@@ -57,20 +57,20 @@ func newSlackPayload(falcopayload types.FalcoPayload, config *types.Configuratio
fields = append(fields, field)
}
- field.Title = "rule"
+ field.Title = Rule
field.Value = falcopayload.Rule
field.Short = true
fields = append(fields, field)
- field.Title = "priority"
+ field.Title = Priority
field.Value = falcopayload.Priority
field.Short = true
fields = append(fields, field)
- field.Title = "time"
+ field.Title = Time
field.Short = false
field.Value = falcopayload.Time.String()
fields = append(fields, field)
- attachment.Footer = "https://github.com/falcosecurity/falcosidekick"
+ attachment.Footer = DefaultFooter
if config.Slack.Footer != "" {
attachment.Footer = config.Slack.Footer
}
@@ -78,7 +78,7 @@ func newSlackPayload(falcopayload types.FalcoPayload, config *types.Configuratio
attachment.Fallback = falcopayload.Output
attachment.Fields = fields
- if config.Slack.OutputFormat == "all" || config.Slack.OutputFormat == "fields" || config.Slack.OutputFormat == "" {
+ if config.Slack.OutputFormat == All || config.Slack.OutputFormat == Fields || config.Slack.OutputFormat == "" {
attachment.Text = falcopayload.Output
}
@@ -93,28 +93,28 @@ func newSlackPayload(falcopayload types.FalcoPayload, config *types.Configuratio
var color string
switch strings.ToLower(falcopayload.Priority) {
- case "emergency":
- color = "#e20b0b"
- case "alert":
- color = "#ff5400"
- case "critical":
- color = "#ff9000"
- case "error":
- color = "#ffc700"
- case "warning":
- color = "#ffff00"
- case "notice":
- color = "#5bffb5"
- case "informational":
- color = "#68c2ff"
- case "debug":
- color = "#ccfff2"
+ case Emergency:
+ color = Red
+ case Alert:
+ color = Orange
+ case Critical:
+ color = Orange
+ case Error:
+ color = Red
+ case Warning:
+ color = Yellow
+ case Notice:
+ color = Lightcyan
+ case Informational:
+ color = LigthBlue
+ case Debug:
+ color = PaleCyan
}
attachment.Color = color
attachments = append(attachments, attachment)
- // iconURL := "https://raw.githubusercontent.com/falcosecurity/falcosidekick/master/imgs/falcosidekick.png"
+ // iconURL := DefaultIconURL
// if config.Slack.Icon != "" {
// iconURL = config.Slack.Icon
// }
@@ -132,11 +132,12 @@ func newSlackPayload(falcopayload types.FalcoPayload, config *types.Configuratio
func (c *Client) SlackPost(falcopayload types.FalcoPayload) {
err := c.Post(newSlackPayload(falcopayload, c.Config))
if err != nil {
- c.Stats.Slack.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "slack", "status": "error"}).Inc()
+ c.Stats.Slack.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "slack", "status": Error}).Inc()
} else {
- c.Stats.Slack.Add("ok", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "slack", "status": "ok"}).Inc()
+ c.Stats.Slack.Add(OK, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "slack", "status": OK}).Inc()
}
- c.Stats.Slack.Add("total", 1)
+
+ c.Stats.Slack.Add(Total, 1)
}
diff --git a/outputs/slack_test.go b/outputs/slack_test.go
index ae6324ec95..2af605de16 100644
--- a/outputs/slack_test.go
+++ b/outputs/slack_test.go
@@ -13,30 +13,30 @@ func TestNewSlackPayload(t *testing.T) {
expectedOutput := slackPayload{
Text: "Rule: Test rule Priority: Debug",
Username: "Falcosidekick",
- IconURL: "https://raw.githubusercontent.com/falcosecurity/falcosidekick/master/imgs/falcosidekick.png",
+ IconURL: DefaultIconURL,
Attachments: []slackAttachment{
- slackAttachment{
+ {
Fallback: "This is a test from falcosidekick",
- Color: "#ccfff2",
+ Color: PaleCyan,
Text: "This is a test from falcosidekick",
Footer: "https://github.com/falcosecurity/falcosidekick",
Fields: []slackAttachmentField{
- slackAttachmentField{
+ {
Title: "proc.name",
Value: "falcosidekick",
Short: true,
},
- slackAttachmentField{
+ {
Title: "rule",
Value: "Test rule",
Short: true,
},
- slackAttachmentField{
+ {
Title: "priority",
Value: "Debug",
Short: true,
},
- slackAttachmentField{
+ {
Title: "time",
Value: "2001-01-01 01:10:00 +0000 UTC",
Short: false,
@@ -51,12 +51,13 @@ func TestNewSlackPayload(t *testing.T) {
config := &types.Configuration{
Slack: types.SlackOutputConfig{
Username: "Falcosidekick",
- Icon: "https://raw.githubusercontent.com/falcosecurity/falcosidekick/master/imgs/falcosidekick.png",
+ Icon: DefaultIconURL,
},
}
config.Slack.MessageFormatTemplate, _ = template.New("").Parse("Rule: {{ .Rule }} Priority: {{ .Priority }}")
output := newSlackPayload(f, config)
+
if !reflect.DeepEqual(output, expectedOutput) {
t.Fatalf("\nexpected payload: \n%#v\ngot: \n%#v\n", expectedOutput, output)
}
diff --git a/outputs/smtp.go b/outputs/smtp.go
index c6b5b74af3..ee742ee230 100644
--- a/outputs/smtp.go
+++ b/outputs/smtp.go
@@ -1,110 +1,110 @@
-package outputs
-
-import (
- "bytes"
- htmlTemplate "html/template"
- "log"
- "regexp"
- "strings"
- textTemplate "text/template"
-
- sasl "github.com/emersion/go-sasl"
- smtp "github.com/emersion/go-smtp"
-
- "github.com/DataDog/datadog-go/statsd"
- "github.com/falcosecurity/falcosidekick/types"
-)
-
-// SMTPPayload is payload for SMTP Output
-type SMTPPayload struct {
- To string
- Subject string
- Body string
-}
-
-// NewSMTPClient returns a new output.Client for accessing a SMTP server.
-func NewSMTPClient(config *types.Configuration, stats *types.Statistics, promStats *types.PromStatistics, statsdClient, dogstatsdClient *statsd.Client) (*Client, error) {
- reg := regexp.MustCompile(`.*:[0-9]+`)
- if !reg.MatchString(config.SMTP.HostPort) {
- log.Printf("[ERROR] : SMTP - Bad Host:Port\n")
- return nil, ErrClientCreation
- }
-
- return &Client{
- OutputType: "SMTP",
- Config: config,
- Stats: stats,
- PromStats: promStats,
- StatsdClient: statsdClient,
- DogstatsdClient: dogstatsdClient,
- }, nil
-}
-
-func newSMTPPayload(falcopayload types.FalcoPayload, config *types.Configuration) SMTPPayload {
- s := SMTPPayload{
- To: "To: " + config.SMTP.To,
- Subject: "Subject: [" + falcopayload.Priority + "] " + falcopayload.Output,
- }
-
- s.Body = "MIME-version: 1.0;\n"
-
- if config.SMTP.OutputFormat != "text" {
- s.Body += "Content-Type: multipart/alternative; boundary=4t74weu9byeSdJTM\n\n\n--4t74weu9byeSdJTM\n"
- }
-
- s.Body += "Content-Type: text/plain; charset=\"UTF-8\";\n\n"
-
- ttmpl := textTemplate.New("text")
- ttmpl, _ = ttmpl.Parse(plaintextTmpl)
- var outtext bytes.Buffer
- err := ttmpl.Execute(&outtext, falcopayload)
- if err != nil {
- log.Printf("[ERROR] : SMTP - %v\n", err)
- return s
- }
- s.Body += outtext.String()
-
- if config.SMTP.OutputFormat == "text" {
- return s
- }
-
- s.Body += "--4t74weu9byeSdJTM\nContent-Type: text/html; charset=\"UTF-8\";\n\n"
-
- htmpl := htmlTemplate.New("html")
- htmpl, _ = htmpl.Parse(htmlTmpl)
- var outhtml bytes.Buffer
- err = htmpl.Execute(&outhtml, falcopayload)
- if err != nil {
- log.Printf("[ERROR] : SMTP - %v\n", err)
- return s
- }
- s.Body += outhtml.String()
-
- return s
-}
-
-// SendMail sends email to SMTP server
-func (c *Client) SendMail(falcopayload types.FalcoPayload) {
- sp := newSMTPPayload(falcopayload, c.Config)
-
- to := strings.Split(strings.Replace(c.Config.SMTP.To, " ", "", -1), ",")
- auth := sasl.NewPlainClient("", c.Config.SMTP.User, c.Config.SMTP.Password)
- body := sp.To + "\n" + sp.Subject + "\n" + sp.Body
-
- if c.Config.Debug == true {
- log.Printf("[DEBUG] : SMTP payload : \nServer: %v\nFrom: %v\nTo: %v\nSubject: %v\n", c.Config.SMTP.HostPort, c.Config.SMTP.From, sp.To, sp.Subject)
- }
-
- c.Stats.SMTP.Add("total", 1)
- err := smtp.SendMail(c.Config.SMTP.HostPort, auth, c.Config.SMTP.From, to, strings.NewReader(body))
- if err != nil {
- go c.CountMetric("outputs", 1, []string{"output:smtp", "status:error"})
- c.Stats.SMTP.Add("error", 1)
- log.Printf("[ERROR] : SMTP - %v\n", err)
- return
- }
-
- log.Printf("[INFO] : SMTP - Sent OK\n")
- go c.CountMetric("outputs", 1, []string{"output:smtp", "status:ok"})
- c.Stats.SMTP.Add("ok", 1)
-}
+package outputs
+
+import (
+ "bytes"
+ htmlTemplate "html/template"
+ "log"
+ "regexp"
+ "strings"
+ textTemplate "text/template"
+
+ sasl "github.com/emersion/go-sasl"
+ smtp "github.com/emersion/go-smtp"
+
+ "github.com/DataDog/datadog-go/statsd"
+ "github.com/falcosecurity/falcosidekick/types"
+)
+
+// SMTPPayload is payload for SMTP Output
+type SMTPPayload struct {
+ To string
+ Subject string
+ Body string
+}
+
+// NewSMTPClient returns a new output.Client for accessing a SMTP server.
+func NewSMTPClient(config *types.Configuration, stats *types.Statistics, promStats *types.PromStatistics, statsdClient, dogstatsdClient *statsd.Client) (*Client, error) {
+ reg := regexp.MustCompile(`.*:[0-9]+`)
+ if !reg.MatchString(config.SMTP.HostPort) {
+ log.Printf("[ERROR] : SMTP - Bad Host:Port\n")
+ return nil, ErrClientCreation
+ }
+
+ return &Client{
+ OutputType: "SMTP",
+ Config: config,
+ Stats: stats,
+ PromStats: promStats,
+ StatsdClient: statsdClient,
+ DogstatsdClient: dogstatsdClient,
+ }, nil
+}
+
+func newSMTPPayload(falcopayload types.FalcoPayload, config *types.Configuration) SMTPPayload {
+ s := SMTPPayload{
+ To: "To: " + config.SMTP.To,
+ Subject: "Subject: [" + falcopayload.Priority + "] " + falcopayload.Output,
+ }
+
+ s.Body = "MIME-version: 1.0;\n"
+
+ if config.SMTP.OutputFormat != Text {
+ s.Body += "Content-Type: multipart/alternative; boundary=4t74weu9byeSdJTM\n\n\n--4t74weu9byeSdJTM\n"
+ }
+
+ s.Body += "Content-Type: text/plain; charset=\"UTF-8\";\n\n"
+
+ ttmpl := textTemplate.New(Text)
+ ttmpl, _ = ttmpl.Parse(plaintextTmpl)
+ var outtext bytes.Buffer
+ err := ttmpl.Execute(&outtext, falcopayload)
+ if err != nil {
+ log.Printf("[ERROR] : SMTP - %v\n", err)
+ return s
+ }
+ s.Body += outtext.String()
+
+ if config.SMTP.OutputFormat == Text {
+ return s
+ }
+
+ s.Body += "--4t74weu9byeSdJTM\nContent-Type: text/html; charset=\"UTF-8\";\n\n"
+
+ htmpl := htmlTemplate.New("html")
+ htmpl, _ = htmpl.Parse(htmlTmpl)
+ var outhtml bytes.Buffer
+ err = htmpl.Execute(&outhtml, falcopayload)
+ if err != nil {
+ log.Printf("[ERROR] : SMTP - %v\n", err)
+ return s
+ }
+ s.Body += outhtml.String()
+
+ return s
+}
+
+// SendMail sends email to SMTP server
+func (c *Client) SendMail(falcopayload types.FalcoPayload) {
+ sp := newSMTPPayload(falcopayload, c.Config)
+
+ to := strings.Split(strings.Replace(c.Config.SMTP.To, " ", "", -1), ",")
+ auth := sasl.NewPlainClient("", c.Config.SMTP.User, c.Config.SMTP.Password)
+ body := sp.To + "\n" + sp.Subject + "\n" + sp.Body
+
+ if c.Config.Debug == true {
+ log.Printf("[DEBUG] : SMTP payload : \nServer: %v\nFrom: %v\nTo: %v\nSubject: %v\n", c.Config.SMTP.HostPort, c.Config.SMTP.From, sp.To, sp.Subject)
+ }
+
+ c.Stats.SMTP.Add("total", 1)
+ err := smtp.SendMail(c.Config.SMTP.HostPort, auth, c.Config.SMTP.From, to, strings.NewReader(body))
+ if err != nil {
+ go c.CountMetric("outputs", 1, []string{"output:smtp", "status:error"})
+ c.Stats.SMTP.Add(Error, 1)
+ log.Printf("[ERROR] : SMTP - %v\n", err)
+ return
+ }
+
+ log.Printf("[INFO] : SMTP - Sent OK\n")
+ go c.CountMetric("outputs", 1, []string{"output:smtp", "status:ok"})
+ c.Stats.SMTP.Add(OK, 1)
+}
diff --git a/outputs/smtp_templates.go b/outputs/smtp_templates.go
index 59b901efd8..f774846265 100644
--- a/outputs/smtp_templates.go
+++ b/outputs/smtp_templates.go
@@ -1,81 +1,81 @@
-package outputs
-
-var plaintextTmpl = `Priority: {{ .Priority }}
-Output: {{ .Output }}
-Rule: {{ .Rule }}
-Time: {{ .Time }}
-
---Fields--
-{{ range $key, $value := .OutputFields }}{{ $key }}: {{ $value }}
-{{ end }}
-
-`
-
-var htmlTmpl = `
-{{ $color := "#858585"}}
-{{ if or (eq .Priority "Emergency") (eq .Priority "emergency") }}{{ $color = "#e20b0b" }}{{ end }}
-{{ if or (eq .Priority "Alert") (eq .Priority "Alert") }}{{ $color = "#ff5400" }}{{ end }}
-{{ if or (eq .Priority "Critical") (eq .Priority "critical") }}{{ $color = "#ff9000" }}{{ end }}
-{{ if or (eq .Priority "Error") (eq .Priority "error") }}{{ $color = "#ffc700" }}{{ end }}
-{{ if or (eq .Priority "Warning") (eq .Priority "warning") }}{{ $color = "#ffff00" }}{{ end }}
-{{ if or (eq .Priority "Notice") (eq .Priority "notice") }}{{ $color = "#5bffb5" }}{{ end }}
-{{ if or (eq .Priority "Informational") (eq .Priority "informational") }}{{ $color = "#68c2ff" }}{{ end }}
-{{ if or (eq .Priority "Debug") (eq .Priority "debug") }}{{ $color = "#ccfff2" }}{{ end }}
-
-
-
-
-
-
-
- |
- |
-
-
-
-
-
-
-
- {{ .Priority }} |
-
-
-
-
-
-
- Output |
- {{ .Output }} |
-
-
- Rule |
- {{ .Rule }} |
-
-
- Time |
- {{ .Time }} |
-
-
-
-
-
-
-
-
- {{ range $key, $value := .OutputFields }}
-
- {{ $key }} |
- {{ $value }} |
-
- {{ end }}
-
-
---4t74weu9byeSdJTM--`
+package outputs
+
+var plaintextTmpl = `Priority: {{ .Priority }}
+Output: {{ .Output }}
+Rule: {{ .Rule }}
+Time: {{ .Time }}
+
+--Fields--
+{{ range $key, $value := .OutputFields }}{{ $key }}: {{ $value }}
+{{ end }}
+
+`
+
+var htmlTmpl = `
+{{ $color := "#858585"}}
+{{ if or (eq .Priority "Emergency") (eq .Priority "emergency") }}{{ $color = "#e20b0b" }}{{ end }}
+{{ if or (eq .Priority ALERT) (eq .Priority ALERT) }}{{ $color = "#ff5400" }}{{ end }}
+{{ if or (eq .Priority CRITICAL) (eq .Priority CRITICAL) }}{{ $color = "#ff9000" }}{{ end }}
+{{ if or (eq .Priority ERROR) (eq .Priority ERROR) }}{{ $color = "#ffc700" }}{{ end }}
+{{ if or (eq .Priority WARNING) (eq .Priority WARNING) }}{{ $color = "#ffff00" }}{{ end }}
+{{ if or (eq .Priority NOTICE) (eq .Priority NOTICE) }}{{ $color = "#5bffb5" }}{{ end }}
+{{ if or (eq .Priority INFORMATIONAL) (eq .Priority INFORMATIONAL) }}{{ $color = "#68c2ff" }}{{ end }}
+{{ if or (eq .Priority DEBUG) (eq .Priority DEBUG) }}{{ $color = "#ccfff2" }}{{ end }}
+
+
+
+
+
+
+
+ |
+ |
+
+
+
+
+
+
+
+ {{ .Priority }} |
+
+
+
+
+
+
+ Output |
+ {{ .Output }} |
+
+
+ Rule |
+ {{ .Rule }} |
+
+
+ Time |
+ {{ .Time }} |
+
+
+
+
+
+
+
+
+ {{ range $key, $value := .OutputFields }}
+
+ {{ $key }} |
+ {{ $value }} |
+
+ {{ end }}
+
+
+--4t74weu9byeSdJTM--`
diff --git a/outputs/statsd.go b/outputs/statsd.go
index 42bed42cbc..25fc02aebf 100644
--- a/outputs/statsd.go
+++ b/outputs/statsd.go
@@ -1,55 +1,61 @@
-package outputs
-
-import (
- "github.com/DataDog/datadog-go/statsd"
- "github.com/falcosecurity/falcosidekick/types"
-
- "log"
- "strings"
-)
-
-// NewStatsdClient returns a new output.Client for sending metrics to StatsD.
-func NewStatsdClient(outputType string, config *types.Configuration, stats *types.Statistics) (*statsd.Client, error) {
- statsdClient, err := statsd.New(config.Statsd.Forwarder, statsd.WithNamespace(config.Statsd.Namespace), statsd.WithTags(config.Statsd.Tags))
- if err != nil {
- log.Printf("[ERROR] : Can't configure %v client for %v - %v", outputType, config.Statsd.Forwarder, err)
- return nil, err
- }
-
- return statsdClient, nil
-}
-
-// CountMetric sends metrics to StatsD/DogStatsD.
-func (c *Client) CountMetric(metric string, value int64, tags []string) {
- if c.StatsdClient != nil {
- c.Stats.Statsd.Add("total", 1)
- t := ""
- if len(tags) != 0 {
- for _, i := range tags {
- s := strings.Split(i, ":")
- t += "." + strings.Replace(s[1], " ", "", -1)
- }
- }
- if err := c.StatsdClient.Count(metric+t, value, []string{}, 1); err != nil {
- c.Stats.Statsd.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "statsd", "status": "error"}).Inc()
- log.Printf("[ERROR] : StatsD - Unable to send metric (%v%v%v) : %v\n", c.Config.Statsd.Namespace, metric, t, err)
- return
- }
- c.Stats.Statsd.Add("ok", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "statsd", "status": "ok"}).Inc()
- log.Printf("[INFO] : StatsD - Send Metric OK (%v%v%v)\n", c.Config.Statsd.Namespace, metric, t)
- }
- if c.DogstatsdClient != nil {
- c.Stats.Dogstatsd.Add("total", 1)
- if err := c.DogstatsdClient.Count(metric, value, tags, 1); err != nil {
- c.Stats.Dogstatsd.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "dogstatsd", "status": "error"}).Inc()
- log.Printf("[ERROR] : DogStatsD - Send Metric Error (%v%v%v) : %v\n", c.Config.Statsd.Namespace, metric, tags, err)
- return
- }
- c.Stats.Dogstatsd.Add("ok", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "dogstatsd", "status": "ok"}).Inc()
- log.Printf("[INFO] : DogStatsD - Send Metric OK (%v%v %v)\n", c.Config.Statsd.Namespace, metric, tags)
- }
-}
+package outputs
+
+import (
+ "github.com/DataDog/datadog-go/statsd"
+ "github.com/falcosecurity/falcosidekick/types"
+
+ "log"
+ "strings"
+)
+
+// NewStatsdClient returns a new output.Client for sending metrics to StatsD.
+func NewStatsdClient(outputType string, config *types.Configuration, stats *types.Statistics) (*statsd.Client, error) {
+ statsdClient, err := statsd.New(config.Statsd.Forwarder, statsd.WithNamespace(config.Statsd.Namespace), statsd.WithTags(config.Statsd.Tags))
+ if err != nil {
+ log.Printf("[ERROR] : Can't configure %v client for %v - %v", outputType, config.Statsd.Forwarder, err)
+ return nil, err
+ }
+
+ return statsdClient, nil
+}
+
+// CountMetric sends metrics to StatsD/DogStatsD.
+func (c *Client) CountMetric(metric string, value int64, tags []string) {
+ if c.StatsdClient != nil {
+ c.Stats.Statsd.Add("total", 1)
+ t := ""
+ if len(tags) != 0 {
+ for _, i := range tags {
+ s := strings.Split(i, ":")
+ t += "." + strings.Replace(s[1], " ", "", -1)
+ }
+ }
+
+ if err := c.StatsdClient.Count(metric+t, value, []string{}, 1); err != nil {
+ c.Stats.Statsd.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "statsd", "status": Error}).Inc()
+ log.Printf("[ERROR] : StatsD - Unable to send metric (%v%v%v) : %v\n", c.Config.Statsd.Namespace, metric, t, err)
+
+ return
+ }
+
+ c.Stats.Statsd.Add(OK, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "statsd", "status": OK}).Inc()
+ log.Printf("[INFO] : StatsD - Send Metric OK (%v%v%v)\n", c.Config.Statsd.Namespace, metric, t)
+ }
+
+ if c.DogstatsdClient != nil {
+ c.Stats.Dogstatsd.Add("total", 1)
+ if err := c.DogstatsdClient.Count(metric, value, tags, 1); err != nil {
+ c.Stats.Dogstatsd.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "dogstatsd", "status": Error}).Inc()
+ log.Printf("[ERROR] : DogStatsD - Send Metric Error (%v%v%v) : %v\n", c.Config.Statsd.Namespace, metric, tags, err)
+
+ return
+ }
+
+ c.Stats.Dogstatsd.Add(OK, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "dogstatsd", "status": OK}).Inc()
+ log.Printf("[INFO] : DogStatsD - Send Metric OK (%v%v %v)\n", c.Config.Statsd.Namespace, metric, tags)
+ }
+}
diff --git a/outputs/teams.go b/outputs/teams.go
index e00b86274a..32c80ed2f7 100644
--- a/outputs/teams.go
+++ b/outputs/teams.go
@@ -1,112 +1,113 @@
-package outputs
-
-import (
- "strings"
-
- "github.com/falcosecurity/falcosidekick/types"
-)
-
-type teamsFact struct {
- Name string `json:"name"`
- Value string `json:"value"`
-}
-
-type teamsSection struct {
- ActivityTitle string `json:"activityTitle"`
- ActivitySubTitle string `json:"activitySubtitle"`
- ActivityImage string `json:"activityImage,omitempty"`
- Text string `json:"text"`
- Facts []teamsFact `json:"facts,omitempty"`
-}
-
-// Payload
-type teamsPayload struct {
- Type string `json:"@type"`
- Summary string `json:"summary,omitempty"`
- ThemeColor string `json:"themeColor,omitempty"`
- Sections []teamsSection `json:"sections"`
-}
-
-func newTeamsPayload(falcopayload types.FalcoPayload, config *types.Configuration) teamsPayload {
- var sections []teamsSection
- var section teamsSection
- var facts []teamsFact
- var fact teamsFact
-
- section.ActivityTitle = "Falco Sidekick"
- section.ActivitySubTitle = falcopayload.Time.String()
-
- if config.Teams.OutputFormat == "all" || config.Teams.OutputFormat == "text" || config.Teams.OutputFormat == "" {
- section.Text = falcopayload.Output
- }
-
- if config.Teams.ActivityImage != "" {
- section.ActivityImage = config.Teams.ActivityImage
- }
-
- if config.Teams.OutputFormat == "all" || config.Teams.OutputFormat == "facts" || config.Teams.OutputFormat == "" {
- for i, j := range falcopayload.OutputFields {
- switch j.(type) {
- case string:
- fact.Name = i
- fact.Value = j.(string)
- default:
- continue
- }
- facts = append(facts, fact)
- }
-
- fact.Name = "rule"
- fact.Value = falcopayload.Rule
- facts = append(facts, fact)
- fact.Name = "priority"
- fact.Value = falcopayload.Priority
- facts = append(facts, fact)
- }
-
- section.Facts = facts
-
- var color string
- switch strings.ToLower(falcopayload.Priority) {
- case "emergency":
- color = "e20b0b"
- case "alert":
- color = "ff5400"
- case "critical":
- color = "ff9000"
- case "error":
- color = "ffc700"
- case "warning":
- color = "ffff00"
- case "notice":
- color = "5bffb5"
- case "informational":
- color = "68c2ff"
- case "debug":
- color = "ccfff2"
- }
-
- sections = append(sections, section)
-
- t := teamsPayload{
- Type: "MessageCard",
- Summary: falcopayload.Output,
- ThemeColor: color,
- Sections: sections,
- }
-
- return t
-}
-
-// TeamsPost posts event to Teams
-func (c *Client) TeamsPost(falcopayload types.FalcoPayload) {
- err := c.Post(newTeamsPayload(falcopayload, c.Config))
- if err != nil {
- c.Stats.Teams.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "teams", "status": "error"}).Inc()
- } else {
- c.Stats.Teams.Add("ok", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "teams", "status": "ok"}).Inc()
- }
- c.Stats.Teams.Add("total", 1)
-}
+package outputs
+
+import (
+ "strings"
+
+ "github.com/falcosecurity/falcosidekick/types"
+)
+
+type teamsFact struct {
+ Name string `json:"name"`
+ Value string `json:"value"`
+}
+
+type teamsSection struct {
+ ActivityTitle string `json:"activityTitle"`
+ ActivitySubTitle string `json:"activitySubtitle"`
+ ActivityImage string `json:"activityImage,omitempty"`
+ Text string `json:"text"`
+ Facts []teamsFact `json:"facts,omitempty"`
+}
+
+// Payload
+type teamsPayload struct {
+ Type string `json:"@type"`
+ Summary string `json:"summary,omitempty"`
+ ThemeColor string `json:"themeColor,omitempty"`
+ Sections []teamsSection `json:"sections"`
+}
+
+func newTeamsPayload(falcopayload types.FalcoPayload, config *types.Configuration) teamsPayload {
+ var sections []teamsSection
+ var section teamsSection
+ var facts []teamsFact
+ var fact teamsFact
+
+ section.ActivityTitle = "Falco Sidekick"
+ section.ActivitySubTitle = falcopayload.Time.String()
+
+ if config.Teams.OutputFormat == All || config.Teams.OutputFormat == "text" || config.Teams.OutputFormat == "" {
+ section.Text = falcopayload.Output
+ }
+
+ if config.Teams.ActivityImage != "" {
+ section.ActivityImage = config.Teams.ActivityImage
+ }
+
+ if config.Teams.OutputFormat == All || config.Teams.OutputFormat == "facts" || config.Teams.OutputFormat == "" {
+ for i, j := range falcopayload.OutputFields {
+ switch j.(type) {
+ case string:
+ fact.Name = i
+ fact.Value = j.(string)
+ default:
+ continue
+ }
+ facts = append(facts, fact)
+ }
+
+ fact.Name = Rule
+ fact.Value = falcopayload.Rule
+ facts = append(facts, fact)
+ fact.Name = Priority
+ fact.Value = falcopayload.Priority
+ facts = append(facts, fact)
+ }
+
+ section.Facts = facts
+
+ var color string
+ switch strings.ToLower(falcopayload.Priority) {
+ case Emergency:
+ color = "e20b0b"
+ case Alert:
+ color = "ff5400"
+ case Critical:
+ color = "ff9000"
+ case Error:
+ color = "ffc700"
+ case Warning:
+ color = "ffff00"
+ case Notice:
+ color = "5bffb5"
+ case Informational:
+ color = "68c2ff"
+ case Debug:
+ color = "ccfff2"
+ }
+
+ sections = append(sections, section)
+
+ t := teamsPayload{
+ Type: "MessageCard",
+ Summary: falcopayload.Output,
+ ThemeColor: color,
+ Sections: sections,
+ }
+
+ return t
+}
+
+// TeamsPost posts event to Teams
+func (c *Client) TeamsPost(falcopayload types.FalcoPayload) {
+ err := c.Post(newTeamsPayload(falcopayload, c.Config))
+ if err != nil {
+ c.Stats.Teams.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "teams", "status": Error}).Inc()
+ } else {
+ c.Stats.Teams.Add(OK, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "teams", "status": OK}).Inc()
+ }
+
+ c.Stats.Teams.Add(Total, 1)
+}
diff --git a/outputs/teams_test.go b/outputs/teams_test.go
index 840b447611..6840e8d636 100644
--- a/outputs/teams_test.go
+++ b/outputs/teams_test.go
@@ -1,46 +1,47 @@
-package outputs
-
-import (
- "encoding/json"
- "reflect"
- "testing"
-
- "github.com/falcosecurity/falcosidekick/types"
-)
-
-func TestNewTeamsPayload(t *testing.T) {
- expectedOutput := teamsPayload{
- Type: "MessageCard",
- Summary: "This is a test from falcosidekick",
- ThemeColor: "ccfff2",
- Sections: []teamsSection{
- teamsSection{
- ActivityTitle: "Falco Sidekick",
- ActivitySubTitle: "2001-01-01 01:10:00 +0000 UTC",
- ActivityImage: "",
- Text: "This is a test from falcosidekick",
- Facts: []teamsFact{
- teamsFact{
- Name: "proc.name",
- Value: "falcosidekick",
- },
- teamsFact{
- Name: "rule",
- Value: "Test rule",
- },
- teamsFact{
- Name: "priority",
- Value: "Debug",
- },
- },
- },
- },
- }
-
- var f types.FalcoPayload
- json.Unmarshal([]byte(falcoTestInput), &f)
- output := newTeamsPayload(f, &types.Configuration{})
- if !reflect.DeepEqual(output, expectedOutput) {
- t.Fatalf("\nexpected payload: \n%#v\ngot: \n%#v\n", expectedOutput, output)
- }
-}
+package outputs
+
+import (
+ "encoding/json"
+ "reflect"
+ "testing"
+
+ "github.com/falcosecurity/falcosidekick/types"
+)
+
+func TestNewTeamsPayload(t *testing.T) {
+ expectedOutput := teamsPayload{
+ Type: "MessageCard",
+ Summary: "This is a test from falcosidekick",
+ ThemeColor: "ccfff2",
+ Sections: []teamsSection{
+ {
+ ActivityTitle: "Falco Sidekick",
+ ActivitySubTitle: "2001-01-01 01:10:00 +0000 UTC",
+ ActivityImage: "",
+ Text: "This is a test from falcosidekick",
+ Facts: []teamsFact{
+ {
+ Name: "proc.name",
+ Value: "falcosidekick",
+ },
+ {
+ Name: "rule",
+ Value: "Test rule",
+ },
+ {
+ Name: "priority",
+ Value: "Debug",
+ },
+ },
+ },
+ },
+ }
+
+ var f types.FalcoPayload
+ json.Unmarshal([]byte(falcoTestInput), &f)
+ output := newTeamsPayload(f, &types.Configuration{})
+
+ if !reflect.DeepEqual(output, expectedOutput) {
+ t.Fatalf("\nexpected payload: \n%#v\ngot: \n%#v\n", expectedOutput, output)
+ }
+}
diff --git a/outputs/webhook.go b/outputs/webhook.go
index 59dc2cc87d..af09a72bd4 100644
--- a/outputs/webhook.go
+++ b/outputs/webhook.go
@@ -8,11 +8,12 @@ import (
func (c *Client) WebhookPost(falcopayload types.FalcoPayload) {
err := c.Post(falcopayload)
if err != nil {
- c.Stats.Webhook.Add("error", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "webhook", "status": "error"}).Inc()
+ c.Stats.Webhook.Add(Error, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "webhook", "status": Error}).Inc()
} else {
- c.Stats.Webhook.Add("ok", 1)
- c.PromStats.Outputs.With(map[string]string{"destination": "webhook", "status": "ok"}).Inc()
+ c.Stats.Webhook.Add(OK, 1)
+ c.PromStats.Outputs.With(map[string]string{"destination": "webhook", "status": OK}).Inc()
}
- c.Stats.Webhook.Add("total", 1)
+
+ c.Stats.Webhook.Add(Total, 1)
}
diff --git a/types/types.go b/types/types.go
index 99b294cd90..83ffbf317b 100644
--- a/types/types.go
+++ b/types/types.go
@@ -19,8 +19,10 @@ type FalcoPayload struct {
// Configuration is a struct to store configuration
type Configuration struct {
- ListenPort int
+ CheckCert bool
Debug bool
+ ListenPort int
+ Customfields map[string]string
Slack SlackOutputConfig
Mattermost mattermostOutputConfig
Rocketchat rocketchatOutputConfig
@@ -40,8 +42,6 @@ type Configuration struct {
Webhook WebhookOutputConfig
Azure azureConfig
GCP gcpOutputConfig
- Customfields map[string]string
- CheckCert bool
}
// SlackOutputConfig represents parameters for Slack
@@ -231,7 +231,7 @@ type Statistics struct {
Dogstatsd *expvar.Map
Webhook *expvar.Map
AzureEventHub *expvar.Map
- GCPPubSub *expvar.Map
+ GCPPubSub *expvar.Map
}
// PromStatistics is a struct to store prometheus metrics