Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support loading webhook URL from a file #3223

Merged
merged 5 commits into from
Mar 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 11 additions & 5 deletions config/notifiers.go
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,8 @@ type WebhookConfig struct {
HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`

// URL to send POST request to.
URL *SecretURL `yaml:"url" json:"url"`
URL *SecretURL `yaml:"url" json:"url"`
URLFile string `yaml:"url_file" json:"url_file"`

// MaxAlerts is the maximum number of alerts to be sent per webhook message.
// Alerts exceeding this threshold will be truncated. Setting this to 0
Expand All @@ -488,11 +489,16 @@ func (c *WebhookConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
if err := unmarshal((*plain)(c)); err != nil {
return err
}
if c.URL == nil {
return fmt.Errorf("missing URL in webhook config")
if c.URL == nil && c.URLFile == "" {
return fmt.Errorf("one of url or url_file must be configured")
}
if c.URL.Scheme != "https" && c.URL.Scheme != "http" {
return fmt.Errorf("scheme required for webhook url")
if c.URL != nil && c.URLFile != "" {
return fmt.Errorf("at most one of url & url_file must be configured")
}
if c.URL != nil {
if c.URL.Scheme != "https" && c.URL.Scheme != "http" {
return fmt.Errorf("scheme required for webhook url")
}
}
return nil
}
Expand Down
20 changes: 19 additions & 1 deletion config/notifiers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,25 @@ func TestWebhookURLIsPresent(t *testing.T) {
var cfg WebhookConfig
err := yaml.UnmarshalStrict([]byte(in), &cfg)

expected := "missing URL in webhook config"
expected := "one of url or url_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 TestWebhookURLOrURLFile(t *testing.T) {
in := `
url: 'http://example.com'
url_file: 'http://example.com'
`
var cfg WebhookConfig
err := yaml.UnmarshalStrict([]byte(in), &cfg)

expected := "at most one of url & url_file must be configured"

if err == nil {
t.Fatalf("no error returned, expected:\n%v", expected)
Expand Down
4 changes: 3 additions & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,7 @@ 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 key.
# The recipient user's key.
# user_key and user_key_file are mutually exclusive.
user_key: <secret>
user_key_file: <filepath>
Expand Down Expand Up @@ -1116,7 +1116,9 @@ The webhook receiver allows configuring a generic receiver.
[ send_resolved: <boolean> | default = true ]

# The endpoint to send HTTP POST requests to.
# url and url_file are mutually exclusive.
url: <secret>
url_file: <filepath>

# The HTTP client's configuration.
[ http_config: <http_config> | default = global.http_config ]
Expand Down
51 changes: 51 additions & 0 deletions notify/pushover/pushover_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package pushover

import (
"fmt"
"os"
"testing"

"github.com/go-kit/log"
Expand Down Expand Up @@ -59,3 +60,53 @@ func TestPushoverRedactedURL(t *testing.T) {

test.AssertNotifyLeaksNoSecret(ctx, t, notifier, key, token)
}

func TestPushoverReadingUserKeyFromFile(t *testing.T) {
ctx, apiURL, fn := test.GetContextWithCancelingURL()
defer fn()

const userKey = "user key"
f, err := os.CreateTemp("", "pushover_user_key")
require.NoError(t, err, "creating temp file failed")
_, err = f.WriteString(userKey)
require.NoError(t, err, "writing to temp file failed")

notifier, err := New(
&config.PushoverConfig{
UserKeyFile: f.Name(),
Token: config.Secret("token"),
HTTPConfig: &commoncfg.HTTPClientConfig{},
},
test.CreateTmpl(t),
log.NewNopLogger(),
)
notifier.apiURL = apiURL.String()
require.NoError(t, err)

test.AssertNotifyLeaksNoSecret(ctx, t, notifier, userKey)
}

func TestPushoverReadingTokenFromFile(t *testing.T) {
ctx, apiURL, fn := test.GetContextWithCancelingURL()
defer fn()

const token = "token"
f, err := os.CreateTemp("", "pushover_token")
require.NoError(t, err, "creating temp file failed")
_, err = f.WriteString(token)
require.NoError(t, err, "writing to temp file failed")

notifier, err := New(
&config.PushoverConfig{
UserKey: config.Secret("user key"),
TokenFile: f.Name(),
HTTPConfig: &commoncfg.HTTPClientConfig{},
},
test.CreateTmpl(t),
log.NewNopLogger(),
)
notifier.apiURL = apiURL.String()
require.NoError(t, err)

test.AssertNotifyLeaksNoSecret(ctx, t, notifier, token)
}
14 changes: 13 additions & 1 deletion notify/webhook/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"fmt"
"io"
"net/http"
"os"

"github.com/go-kit/log"
"github.com/go-kit/log/level"
Expand Down Expand Up @@ -101,7 +102,18 @@ func (n *Notifier) Notify(ctx context.Context, alerts ...*types.Alert) (bool, er
return false, err
}

resp, err := notify.PostJSON(ctx, n.client, n.conf.URL.String(), &buf)
var url string
if n.conf.URL != nil {
url = n.conf.URL.String()
} else {
content, err := os.ReadFile(n.conf.URLFile)
if err != nil {
return false, fmt.Errorf("read url_file: %w", err)
}
url = string(content)
}

resp, err := notify.PostJSON(ctx, n.client, url, &buf)
if err != nil {
return true, notify.RedactURL(err)
}
Expand Down
23 changes: 23 additions & 0 deletions notify/webhook/webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"io"
"net/http"
"net/url"
"os"
"testing"

"github.com/go-kit/log"
Expand Down Expand Up @@ -116,3 +117,25 @@ func TestWebhookRedactedURL(t *testing.T) {

test.AssertNotifyLeaksNoSecret(ctx, t, notifier, secret)
}

func TestWebhookReadingURLFromFile(t *testing.T) {
ctx, u, fn := test.GetContextWithCancelingURL()
defer fn()

f, err := os.CreateTemp("", "webhook_url")
require.NoError(t, err, "creating temp file failed")
_, err = f.WriteString(u.String())
require.NoError(t, err, "writing to temp file failed")

notifier, err := New(
&config.WebhookConfig{
URLFile: f.Name(),
HTTPConfig: &commoncfg.HTTPClientConfig{},
},
test.CreateTmpl(t),
log.NewNopLogger(),
)
require.NoError(t, err)

test.AssertNotifyLeaksNoSecret(ctx, t, notifier, u.String())
}