Skip to content

Commit

Permalink
feat: add webex output
Browse files Browse the repository at this point in the history
Signed-off-by: k0rventen <49311792+k0rventen@users.noreply.github.com>
  • Loading branch information
k0rventen authored and poiana committed Sep 5, 2024
1 parent 1ccb742 commit 45f6cb7
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ Follow the links to get the configuration of each output.
- [**Rocketchat**](https://github.com/falcosecurity/falcosidekick/blob/master/docs/outputs/rocketchat.md)
- [**Mattermost**](https://github.com/falcosecurity/falcosidekick/blob/master/docs/outputs/mattermost.md)
- [**Teams**](https://github.com/falcosecurity/falcosidekick/blob/master/docs/outputs/teams.md)
- [**Webex**](https://github.com/falcosecurity/falcosidekick/blob/master/docs/outputs/webex.md)
- [**Discord**](https://github.com/falcosecurity/falcosidekick/blob/master/docs/outputs/discord.md)
- [**Google Chat**](https://github.com/falcosecurity/falcosidekick/blob/master/docs/outputs/googlechat.md)
- [**Zoho Cliq**](https://github.com/falcosecurity/falcosidekick/blob/master/docs/outputs/cliq.md)
Expand Down
5 changes: 5 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ var httpOutputDefaults = map[string]map[string]any{
"OutputFormat": "all",
"MinimumPriority": "",
},
"Webex": {
"WebhookURL": "",
"MinimumPriority": "",
},
"Datadog": {
"APIKey": "",
"Host": "https://api.datadoghq.com",
Expand Down Expand Up @@ -807,6 +811,7 @@ func getConfig() *types.Configuration {
c.Rocketchat.MinimumPriority = checkPriority(c.Rocketchat.MinimumPriority)
c.Mattermost.MinimumPriority = checkPriority(c.Mattermost.MinimumPriority)
c.Teams.MinimumPriority = checkPriority(c.Teams.MinimumPriority)
c.Webex.MinimumPriority = checkPriority(c.Webex.MinimumPriority)
c.Datadog.MinimumPriority = checkPriority(c.Datadog.MinimumPriority)
c.Alertmanager.MinimumPriority = checkPriority(c.Alertmanager.MinimumPriority)
c.Alertmanager.DropEventDefaultPriority = checkPriority(c.Alertmanager.DropEventDefaultPriority)
Expand Down
4 changes: 4 additions & 0 deletions config_example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ teams:
outputformat: "all" # all (default), text, facts
minimumpriority: "" # minimum priority of event for using this output, order is emergency|alert|critical|error|warning|notice|informational|debug or "" (default)

webex:
# webhookurl: "" # Webex WebhookURL, if not empty, Teams Webex is enabled
# minimumpriority: "" # minimum priority of event for using this output, order is emergency|alert|critical|error|warning|notice|informational|debug or "" (default)

datadog:
# apikey: "" # Datadog API Key, if not empty, Datadog output is enabled
# host: "" # Datadog host. Override if you are on the Datadog EU site. Defaults to american site with "https://api.datadoghq.com"
Expand Down
Binary file added docs/outputs/images/webex.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 35 additions & 0 deletions docs/outputs/webex.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Webex

- **Category**: Chat/Messaging
- **Website**: https://webex.com

## Table of content

- [Teams](#teams)
- [Table of content](#table-of-content)
- [Configuration](#configuration)
- [Example of config.yaml](#example-of-configyaml)
- [Screenshots](#screenshots)

## Configuration

| Setting | Env var | Default value | Description |
| ----------------------- | ----------------------- | --------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `webex.webhookurl` | `WEBEX_WEBHOOKURL` | | Teams WebhookURL, if not empty, Webex output is **enabled** |
| `webex.minimumpriority` | `WEBEX_MINIMUMPRIORITY` | `""` (= `debug`) | Minimum priority of event for using this output, order is `emergency,alert,critical,error,warning,notice,informational,debug or ""` |


> [!NOTE]
The Env var values override the settings from yaml file.

## Example of config.yaml

```yaml
webex:
webhookurl: "" # Webex WebhookURL, if not empty, Webex output is enabled
# minimumpriority: "debug" # minimum priority of event for using this output, order is emergency|alert|critical|error|warning|notice|informational|debug or "" (default)
```
## Screenshots

![webex example](images/webex.png)

3 changes: 3 additions & 0 deletions handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ func forwardEvent(falcopayload types.FalcoPayload) {
go teamsClient.TeamsPost(falcopayload)
}

if config.Webex.WebhookURL != "" && (falcopayload.Priority >= types.Priority(config.Webex.MinimumPriority) || falcopayload.Rule == testRule) {
go webexClient.WebexPost(falcopayload)
}
if config.Datadog.APIKey != "" && (falcopayload.Priority >= types.Priority(config.Datadog.MinimumPriority) || falcopayload.Rule == testRule) {
go datadogClient.DatadogPost(falcopayload)
}
Expand Down
11 changes: 11 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ var (
rocketchatClient *outputs.Client
mattermostClient *outputs.Client
teamsClient *outputs.Client
webexClient *outputs.Client
datadogClient *outputs.Client
discordClient *outputs.Client
alertmanagerClient *outputs.Client
Expand Down Expand Up @@ -195,6 +196,16 @@ func init() {
}
}

if config.Webex.WebhookURL != "" {
var err error
webexClient, err = outputs.NewClient("Webex", config.Webex.WebhookURL, config.Webex.CommonConfig, *initClientArgs)
if err != nil {
config.Webex.WebhookURL = ""
} else {
outputs.EnabledOutputs = append(outputs.EnabledOutputs, "Webex")
}
}

if config.Datadog.APIKey != "" {
var err error
endpointUrl := fmt.Sprintf("%s?api_key=%s", config.Datadog.Host+outputs.DatadogPath, config.Datadog.APIKey)
Expand Down
71 changes: 71 additions & 0 deletions outputs/webex.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// SPDX-License-Identifier: MIT OR Apache-2.0

package outputs

import (
"bytes"
"log"
"text/template"

"github.com/falcosecurity/falcosidekick/types"
)

var md string = `# Falco Rule '{{ .Rule }}'
### {{ .Output }}
Additional informations:
* Hostname: {{ .Hostname }}
* Source: {{ .Source }}
* Priority: {{ .Priority }}
* Tags:
{{ range $t := .Tags }}
* {{ $t }}
{{ end }}
* Fields:
{{ range $key, $value := .OutputFields }}
* {{ $key }}: {{ $value }}
{{ end }}
`

// Load the md template
var webexTmpl, _ = template.New("markdown").Parse(md)

// the format is {"markdown":"..."}
type webexPayload struct {
Markdown string `json:"markdown"`
}

func newWebexPayload(falcopayload types.FalcoPayload) webexPayload {
var tpl bytes.Buffer

if err := webexTmpl.Execute(&tpl, falcopayload); err != nil {
log.Printf("[ERROR] : Webex Template - %v\n", err)

}
t := webexPayload{
Markdown: tpl.String(),
}

return t
}

// WebexPost sends event to a Webex Room through a Webhook
func (c *Client) WebexPost(falcopayload types.FalcoPayload) {
c.Stats.Webex.Add(Total, 1)

err := c.Post(newWebexPayload(falcopayload))

if err != nil {
go c.CountMetric(Outputs, 1, []string{"output:webex", "status:error"})
c.Stats.Webhook.Add(Error, 1)
c.PromStats.Outputs.With(map[string]string{"destination": "webex", "status": Error}).Inc()
log.Printf("[ERROR] : Webex - %v\n", err.Error())
return
}

// Setting the success status
go c.CountMetric(Outputs, 1, []string{"output:webex", "status:ok"})
c.Stats.Webhook.Add(OK, 1)
c.PromStats.Outputs.With(map[string]string{"destination": "webex", "status": OK}).Inc()
}
1 change: 1 addition & 0 deletions stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ func getInitStats() *types.Statistics {
Rocketchat: getOutputNewMap("rocketchat"),
Mattermost: getOutputNewMap("mattermost"),
Teams: getOutputNewMap("teams"),
Webex: getOutputNewMap("webex"),
Datadog: getOutputNewMap("datadog"),
Discord: getOutputNewMap("discord"),
Alertmanager: getOutputNewMap("alertmanager"),
Expand Down
8 changes: 8 additions & 0 deletions types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ type Configuration struct {
Mattermost MattermostOutputConfig
Rocketchat RocketchatOutputConfig
Teams teamsOutputConfig
Webex WebexOutputConfig
Datadog datadogOutputConfig
Discord DiscordOutputConfig
Alertmanager AlertmanagerOutputConfig
Expand Down Expand Up @@ -226,6 +227,12 @@ type teamsOutputConfig struct {
MinimumPriority string
}

type WebexOutputConfig struct {
CommonConfig `mapstructure:",squash"`
WebhookURL string
MinimumPriority string
}

type datadogOutputConfig struct {
CommonConfig `mapstructure:",squash"`
APIKey string
Expand Down Expand Up @@ -831,6 +838,7 @@ type Statistics struct {
Statsd *expvar.Map
Dogstatsd *expvar.Map
Webhook *expvar.Map
Webex *expvar.Map
AzureEventHub *expvar.Map
GCPPubSub *expvar.Map
GCPStorage *expvar.Map
Expand Down

0 comments on commit 45f6cb7

Please sign in to comment.