Skip to content

Commit

Permalink
feat(alertmanager-extra-infos): Adding extra labels or annotations to…
Browse files Browse the repository at this point in the history
… the alert

Signed-off-by: Lyonel Martinez <[email protected]>
  • Loading branch information
Lowaiz authored and poiana committed Jul 25, 2022
1 parent 6837830 commit 8602cca
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 6 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,8 @@ alertmanager:
# checkcert: true # check if ssl certificate of the output is valid (default: true)
# endpoint: "" # alertmanager endpoint for posting alerts: "/api/v1/alerts" or "/api/v2/alerts" (default: "/api/v1/alerts")
# expiresafter: "" if set to a non-zero value, alert expires after that time in seconds (default: 0)
# extralabels: "" # comma separated list of labels composed of a ':' separated name and value that is added to the Alerts. Example: my_label_1:my_value_1, my_label_1:my_value_2
# extraannotations: "" # comma separated list of annotations composed of a ':' separated name and value that is added to the Alerts. Example: my_annotation_1:my_value_1, my_annotation_1:my_value_2

elasticsearch:
# hostport: "" # http://{domain or ip}:{port}, if not empty, Elasticsearch output is enabled
Expand Down Expand Up @@ -608,6 +610,10 @@ care of lower/uppercases**) : `yaml: a.b --> envvar: A_B` :
- **ALERTMANAGER_ENDPOINT** : alertmanager endpoint on which falcosidekick posts alerts, choice is:
`"/api/v1/alerts" or "/api/v2/alerts" , default is "/api/v1/alerts"`
- **ALERTMANAGER_EXPIRESAFTER** : if set to a non-zero value, alert expires after that time in seconds (default: 0)
- **ALERTMANAGER_EXTRALABELS** : comma separated list of labels composed of a ':' separated name and value that is
added to the Alerts. Example: `my_label_1:my_value_1, my_label_1:my_value_2` (default: `""`)
- **ALERTMANAGER_EXTRAANNOTATIONS** : comma separated list of annotations composed of a ':' separated name and
value that is added to the Alerts. Example: `my_annotation_1:my_value_1, my_annotation_1:my_value_2` (default: `""`)
- **ELASTICSEARCH_HOSTPORT** : Elasticsearch http://host:port, if not `empty`,
Elasticsearch is _enabled_
- **ELASTICSEARCH_INDEX** : Elasticsearch index (default: falco)
Expand Down
41 changes: 41 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func getConfig() *types.Configuration {
c := &types.Configuration{
Customfields: make(map[string]string),
Webhook: types.WebhookOutputConfig{CustomHeaders: make(map[string]string)},
Alertmanager: types.AlertmanagerOutputConfig{ExtraLabels: make(map[string]string), ExtraAnnotations: make(map[string]string)},
CloudEvents: types.CloudEventsOutputConfig{Extensions: make(map[string]string)},
}

Expand Down Expand Up @@ -362,6 +363,8 @@ func getConfig() *types.Configuration {
v.GetStringMapString("Customfields")
v.GetStringMapString("Webhook.CustomHeaders")
v.GetStringMapString("CloudEvents.Extensions")
v.GetStringMapString("AlertManager.ExtraLabels")
v.GetStringMapString("AlertManager.ExtraAnnotations")
if err := v.Unmarshal(c); err != nil {
log.Printf("[ERROR] : Error unmarshalling config : %s", err)
}
Expand Down Expand Up @@ -395,6 +398,44 @@ func getConfig() *types.Configuration {
}
}
}
regex, _ := regexp.Compile("^[a-zA-Z_:][a-zA-Z0-9_:]*$")
if value, present := os.LookupEnv("ALERTMANAGER_EXTRALABELS"); present {
extralabels := strings.Split(value, ",")
for _, labelData := range extralabels {
if !regex.MatchString(labelData) {
log.Printf("[ERROR] : AlertManager - Extra field '%v' is not a valid prometheus labelData", labelData)
continue
}
values := strings.SplitN(labelData, ":", 2)
label := strings.TrimSpace(values[0])
if !regex.MatchString(label) {
log.Printf("[ERROR] : AlertManager - Extra field '%v' is not a valid prometheus label", label)
continue
}
if len(values) == 2 {
c.Alertmanager.ExtraLabels[label] = strings.TrimSpace(values[1])
} else {
c.Alertmanager.ExtraLabels[label] = ""
}
}
}

if value, present := os.LookupEnv("ALERTMANAGER_EXTRAANNOTATIONS"); present {
extraannotations := strings.Split(value, ",")
for _, annotationData := range extraannotations {
values := strings.SplitN(annotationData, ":", 2)
annotation := strings.TrimSpace(values[0])
if !regex.MatchString(annotation) {
log.Printf("[ERROR] : AlertManager - Extra field '%v' is not a valid prometheus annotation", annotation)
continue
}
if len(values) == 2 {
c.Alertmanager.ExtraAnnotations[annotation] = strings.TrimSpace(values[1])
} else {
c.Alertmanager.ExtraAnnotations[annotation] = ""
}
}
}

if c.ListenPort == 0 || c.ListenPort > 65536 {
log.Fatalf("[ERROR] : Bad port number\n")
Expand Down
2 changes: 2 additions & 0 deletions config_example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ alertmanager:
# checkcert: true # check if ssl certificate of the output is valid (default: true)
# endpoint: "" # alertmanager endpoint for posting alerts: "/api/v1/alerts" or "/api/v2/alerts" (default: "/api/v1/alerts")
# expiresafter: "" if set to a non-zero value, alert expires after that time in seconds (default: 0)
# extralabels: "" # comma separated list of labels composed of a ':' separated name and value that is added to the Alerts. Example: my_label_1:my_value_1, my_label_1:my_value_2
# extraannotations: "" # comma separated list of annotations composed of a ':' separated name and value that is added to the Alerts. Example: my_annotation_1:my_value_1, my_annotation_1:my_value_2

elasticsearch:
# hostport: "" # http://{domain or ip}:{port}, if not empty, Elasticsearch output is enabled
Expand Down
6 changes: 6 additions & 0 deletions outputs/alertmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ func newAlertmanagerPayload(falcopayload types.FalcoPayload, config *types.Confi
if config.Alertmanager.ExpiresAfter != 0 {
amPayload.EndsAt = falcopayload.Time.Add(time.Duration(config.Alertmanager.ExpiresAfter) * time.Second)
}
for label, value := range config.Alertmanager.ExtraLabels {
amPayload.Labels[label] = value
}
for annotation, value := range config.Alertmanager.ExtraAnnotations {
amPayload.Annotations[annotation] = value
}

var a []alertmanagerPayload

Expand Down
14 changes: 8 additions & 6 deletions types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,14 @@ type DiscordOutputConfig struct {
}

type AlertmanagerOutputConfig struct {
HostPort string
MinimumPriority string
CheckCert bool
MutualTLS bool
Endpoint string
ExpiresAfter int
HostPort string
MinimumPriority string
CheckCert bool
MutualTLS bool
Endpoint string
ExpiresAfter int
ExtraLabels map[string]string
ExtraAnnotations map[string]string
}

type elasticsearchOutputConfig struct {
Expand Down

0 comments on commit 8602cca

Please sign in to comment.