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
|
@ -666,17 +666,19 @@ type PushoverConfig struct {
|
|||
|
||||
HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`
|
||||
|
||||
UserKey Secret `yaml:"user_key,omitempty" json:"user_key,omitempty"`
|
||||
Token Secret `yaml:"token,omitempty" json:"token,omitempty"`
|
||||
Title string `yaml:"title,omitempty" json:"title,omitempty"`
|
||||
Message string `yaml:"message,omitempty" json:"message,omitempty"`
|
||||
URL string `yaml:"url,omitempty" json:"url,omitempty"`
|
||||
URLTitle string `yaml:"url_title,omitempty" json:"url_title,omitempty"`
|
||||
Sound string `yaml:"sound,omitempty" json:"sound,omitempty"`
|
||||
Priority string `yaml:"priority,omitempty" json:"priority,omitempty"`
|
||||
Retry duration `yaml:"retry,omitempty" json:"retry,omitempty"`
|
||||
Expire duration `yaml:"expire,omitempty" json:"expire,omitempty"`
|
||||
HTML bool `yaml:"html" json:"html,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"`
|
||||
TokenFile string `yaml:"token_file,omitempty" json:"token_file,omitempty"`
|
||||
Title string `yaml:"title,omitempty" json:"title,omitempty"`
|
||||
Message string `yaml:"message,omitempty" json:"message,omitempty"`
|
||||
URL string `yaml:"url,omitempty" json:"url,omitempty"`
|
||||
URLTitle string `yaml:"url_title,omitempty" json:"url_title,omitempty"`
|
||||
Sound string `yaml:"sound,omitempty" json:"sound,omitempty"`
|
||||
Priority string `yaml:"priority,omitempty" json:"priority,omitempty"`
|
||||
Retry duration `yaml:"retry,omitempty" json:"retry,omitempty"`
|
||||
Expire duration `yaml:"expire,omitempty" json:"expire,omitempty"`
|
||||
HTML bool `yaml:"html" json:"html,omitempty"`
|
||||
}
|
||||
|
||||
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
||||
|
@ -686,11 +688,17 @@ func (c *PushoverConfig) UnmarshalYAML(unmarshal func(interface{}) error) error
|
|||
if err := unmarshal((*plain)(c)); err != nil {
|
||||
return err
|
||||
}
|
||||
if c.UserKey == "" {
|
||||
return fmt.Errorf("missing user key in Pushover config")
|
||||
if c.UserKey == "" && c.UserKeyFile == "" {
|
||||
return fmt.Errorf("one of user_key or user_key_file must be configured")
|
||||
}
|
||||
if c.Token == "" {
|
||||
return fmt.Errorf("missing token in Pushover config")
|
||||
if c.UserKey != "" && c.UserKeyFile != "" {
|
||||
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
|
||||
}
|
||||
|
|
|
@ -391,7 +391,25 @@ user_key: ''
|
|||
var cfg PushoverConfig
|
||||
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 {
|
||||
t.Fatalf("no error returned, expected:\n%v", expected)
|
||||
|
@ -409,7 +427,26 @@ token: ''
|
|||
var cfg PushoverConfig
|
||||
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 {
|
||||
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.
|
||||
[ 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_file: <filepath>
|
||||
|
||||
# Your registered application's API token, see https://pushover.net/apps
|
||||
# You can also register a token by cloning this Prometheus app:
|
||||
# https://pushover.net/apps/clone/prometheus
|
||||
# token and token_file are mutually exclusive.
|
||||
token: <secret>
|
||||
token_file: <filepath>
|
||||
|
||||
# Notification title.
|
||||
[ title: <tmpl_string> | default = '{{ template "pushover.default.title" . }}' ]
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -83,9 +84,32 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error)
|
|||
tmpl := notify.TmplText(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.Add("token", tmpl(string(n.conf.Token)))
|
||||
parameters.Add("user", tmpl(string(n.conf.UserKey)))
|
||||
parameters.Add("token", tmpl(token))
|
||||
parameters.Add("user", tmpl(userKey))
|
||||
|
||||
title, truncated := notify.TruncateInRunes(tmpl(n.conf.Title), maxTitleLenRunes)
|
||||
if truncated {
|
||||
|
|
Loading…
Reference in New Issue