support loading pushover secrets from files (#3200)
* support loading pushover secrets from files Add the user_key_file and token_file keys to the pushover config. /cc https://github.com/prometheus/alertmanager/issues/2498 Signed-off-by: Simon Rozet <me@simonrozet.com>
This commit is contained in:
parent
9c7adc4024
commit
a8e4c166a8
|
@ -667,7 +667,9 @@ type PushoverConfig struct {
|
||||||
HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`
|
HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`
|
||||||
|
|
||||||
UserKey Secret `yaml:"user_key,omitempty" json:"user_key,omitempty"`
|
UserKey Secret `yaml:"user_key,omitempty" json:"user_key,omitempty"`
|
||||||
|
UserKeyFile string `yaml:"user_key_file,omitempty" json:"user_key_file,omitempty"`
|
||||||
Token Secret `yaml:"token,omitempty" json:"token,omitempty"`
|
Token Secret `yaml:"token,omitempty" json:"token,omitempty"`
|
||||||
|
TokenFile string `yaml:"token_file,omitempty" json:"token_file,omitempty"`
|
||||||
Title string `yaml:"title,omitempty" json:"title,omitempty"`
|
Title string `yaml:"title,omitempty" json:"title,omitempty"`
|
||||||
Message string `yaml:"message,omitempty" json:"message,omitempty"`
|
Message string `yaml:"message,omitempty" json:"message,omitempty"`
|
||||||
URL string `yaml:"url,omitempty" json:"url,omitempty"`
|
URL string `yaml:"url,omitempty" json:"url,omitempty"`
|
||||||
|
@ -686,11 +688,17 @@ func (c *PushoverConfig) UnmarshalYAML(unmarshal func(interface{}) error) error
|
||||||
if err := unmarshal((*plain)(c)); err != nil {
|
if err := unmarshal((*plain)(c)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if c.UserKey == "" {
|
if c.UserKey == "" && c.UserKeyFile == "" {
|
||||||
return fmt.Errorf("missing user key in Pushover config")
|
return fmt.Errorf("one of user_key or user_key_file must be configured")
|
||||||
}
|
}
|
||||||
if c.Token == "" {
|
if c.UserKey != "" && c.UserKeyFile != "" {
|
||||||
return fmt.Errorf("missing token in Pushover config")
|
return fmt.Errorf("at most one of user_key & user_key_file must be configured")
|
||||||
|
}
|
||||||
|
if c.Token == "" && c.TokenFile == "" {
|
||||||
|
return fmt.Errorf("one of token or token_file must be configured")
|
||||||
|
}
|
||||||
|
if c.Token != "" && c.TokenFile != "" {
|
||||||
|
return fmt.Errorf("at most one of token & token_file must be configured")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -391,7 +391,25 @@ user_key: ''
|
||||||
var cfg PushoverConfig
|
var cfg PushoverConfig
|
||||||
err := yaml.UnmarshalStrict([]byte(in), &cfg)
|
err := yaml.UnmarshalStrict([]byte(in), &cfg)
|
||||||
|
|
||||||
expected := "missing user key in Pushover config"
|
expected := "one of user_key or user_key_file must be configured"
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("no error returned, expected:\n%v", expected)
|
||||||
|
}
|
||||||
|
if err.Error() != expected {
|
||||||
|
t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPushoverUserKeyOrUserKeyFile(t *testing.T) {
|
||||||
|
in := `
|
||||||
|
user_key: 'user key'
|
||||||
|
user_key_file: /pushover/user_key
|
||||||
|
`
|
||||||
|
var cfg PushoverConfig
|
||||||
|
err := yaml.UnmarshalStrict([]byte(in), &cfg)
|
||||||
|
|
||||||
|
expected := "at most one of user_key & user_key_file must be configured"
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("no error returned, expected:\n%v", expected)
|
t.Fatalf("no error returned, expected:\n%v", expected)
|
||||||
|
@ -409,7 +427,26 @@ token: ''
|
||||||
var cfg PushoverConfig
|
var cfg PushoverConfig
|
||||||
err := yaml.UnmarshalStrict([]byte(in), &cfg)
|
err := yaml.UnmarshalStrict([]byte(in), &cfg)
|
||||||
|
|
||||||
expected := "missing token in Pushover config"
|
expected := "one of token or token_file must be configured"
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("no error returned, expected:\n%v", expected)
|
||||||
|
}
|
||||||
|
if err.Error() != expected {
|
||||||
|
t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPushoverTokenOrTokenFile(t *testing.T) {
|
||||||
|
in := `
|
||||||
|
token: 'pushover token'
|
||||||
|
token_file: /pushover/token
|
||||||
|
user_key: 'user key'
|
||||||
|
`
|
||||||
|
var cfg PushoverConfig
|
||||||
|
err := yaml.UnmarshalStrict([]byte(in), &cfg)
|
||||||
|
|
||||||
|
expected := "at most one of token & token_file must be configured"
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("no error returned, expected:\n%v", expected)
|
t.Fatalf("no error returned, expected:\n%v", expected)
|
||||||
|
|
|
@ -862,13 +862,17 @@ Pushover notifications are sent via the [Pushover API](https://pushover.net/api)
|
||||||
# Whether to notify about resolved alerts.
|
# Whether to notify about resolved alerts.
|
||||||
[ send_resolved: <boolean> | default = true ]
|
[ send_resolved: <boolean> | default = true ]
|
||||||
|
|
||||||
# The recipient user's user key.
|
# The recipient user's key.
|
||||||
|
# user_key and user_key_file are mutually exclusive.
|
||||||
user_key: <secret>
|
user_key: <secret>
|
||||||
|
user_key_file: <filepath>
|
||||||
|
|
||||||
# Your registered application's API token, see https://pushover.net/apps
|
# Your registered application's API token, see https://pushover.net/apps
|
||||||
# You can also register a token by cloning this Prometheus app:
|
# You can also register a token by cloning this Prometheus app:
|
||||||
# https://pushover.net/apps/clone/prometheus
|
# https://pushover.net/apps/clone/prometheus
|
||||||
|
# token and token_file are mutually exclusive.
|
||||||
token: <secret>
|
token: <secret>
|
||||||
|
token_file: <filepath>
|
||||||
|
|
||||||
# Notification title.
|
# Notification title.
|
||||||
[ title: <tmpl_string> | default = '{{ template "pushover.default.title" . }}' ]
|
[ title: <tmpl_string> | default = '{{ template "pushover.default.title" . }}' ]
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -83,9 +84,32 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error)
|
||||||
tmpl := notify.TmplText(n.tmpl, data, &err)
|
tmpl := notify.TmplText(n.tmpl, data, &err)
|
||||||
tmplHTML := notify.TmplHTML(n.tmpl, data, &err)
|
tmplHTML := notify.TmplHTML(n.tmpl, data, &err)
|
||||||
|
|
||||||
|
var (
|
||||||
|
token string
|
||||||
|
userKey string
|
||||||
|
)
|
||||||
|
if n.conf.Token != "" {
|
||||||
|
token = string(n.conf.Token)
|
||||||
|
} else {
|
||||||
|
content, err := os.ReadFile(n.conf.TokenFile)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("read token_file: %w", err)
|
||||||
|
}
|
||||||
|
token = string(content)
|
||||||
|
}
|
||||||
|
if n.conf.UserKey != "" {
|
||||||
|
userKey = string(n.conf.UserKey)
|
||||||
|
} else {
|
||||||
|
content, err := os.ReadFile(n.conf.UserKeyFile)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("read user_key_file: %w", err)
|
||||||
|
}
|
||||||
|
userKey = string(content)
|
||||||
|
}
|
||||||
|
|
||||||
parameters := url.Values{}
|
parameters := url.Values{}
|
||||||
parameters.Add("token", tmpl(string(n.conf.Token)))
|
parameters.Add("token", tmpl(token))
|
||||||
parameters.Add("user", tmpl(string(n.conf.UserKey)))
|
parameters.Add("user", tmpl(userKey))
|
||||||
|
|
||||||
title, truncated := notify.TruncateInRunes(tmpl(n.conf.Title), maxTitleLenRunes)
|
title, truncated := notify.TruncateInRunes(tmpl(n.conf.Title), maxTitleLenRunes)
|
||||||
if truncated {
|
if truncated {
|
||||||
|
|
Loading…
Reference in New Issue