mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Encryption: Refactor securejsondata.SecureJsonData to stop relying on global functions (#38865)
* Encryption: Add support to encrypt/decrypt sjd * Add datasources.Service as a proxy to datasources db operations * Encrypt ds.SecureJsonData before calling SQLStore * Move ds cache code into ds service * Fix tlsmanager tests * Fix pluginproxy tests * Remove some securejsondata.GetEncryptedJsonData usages * Add pluginsettings.Service as a proxy for plugin settings db operations * Add AlertNotificationService as a proxy for alert notification db operations * Remove some securejsondata.GetEncryptedJsonData usages * Remove more securejsondata.GetEncryptedJsonData usages * Fix lint errors * Minor fixes * Remove encryption global functions usages from ngalert * Fix lint errors * Minor fixes * Minor fixes * Remove securejsondata.DecryptedValue usage * Refactor the refactor * Remove securejsondata.DecryptedValue usage * Move securejsondata to migrations package * Move securejsondata to migrations package * Minor fix * Fix integration test * Fix integration tests * Undo undesired changes * Fix tests * Add context.Context into encryption methods * Fix tests * Fix tests * Fix tests * Trigger CI * Fix test * Add names to params of encryption service interface * Remove bus from CacheServiceImpl * Add logging * Add keys to logger Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com> * Add missing key to logger Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com> * Undo changes in markdown files * Fix formatting * Add context to secrets service * Rename decryptSecureJsonData to decryptSecureJsonDataFn * Name args in GetDecryptedValueFn * Add template back to NewAlertmanagerNotifier * Copy GetDecryptedValueFn to ngalert * Add logging to pluginsettings * Fix pluginsettings test Co-authored-by: Tania B <yalyna.ts@gmail.com> Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com>
This commit is contained in:
committed by
GitHub
parent
da813877fb
commit
722c414fef
@@ -31,7 +31,6 @@ import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/common/model"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/securejsondata"
|
||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
@@ -118,9 +117,12 @@ type Alertmanager struct {
|
||||
config *apimodels.PostableUserConfig
|
||||
configHash [16]byte
|
||||
orgID int64
|
||||
|
||||
decryptFn channels.GetDecryptedValueFn
|
||||
}
|
||||
|
||||
func newAlertmanager(orgID int64, cfg *setting.Cfg, store store.AlertingStore, kvStore kvstore.KVStore, peer ClusterPeer, m *metrics.Alertmanager) (*Alertmanager, error) {
|
||||
func newAlertmanager(orgID int64, cfg *setting.Cfg, store store.AlertingStore, kvStore kvstore.KVStore,
|
||||
peer ClusterPeer, decryptFn channels.GetDecryptedValueFn, m *metrics.Alertmanager) (*Alertmanager, error) {
|
||||
am := &Alertmanager{
|
||||
Settings: cfg,
|
||||
stopc: make(chan struct{}),
|
||||
@@ -133,6 +135,7 @@ func newAlertmanager(orgID int64, cfg *setting.Cfg, store store.AlertingStore, k
|
||||
peerTimeout: cfg.UnifiedAlerting.HAPeerTimeout,
|
||||
Metrics: m,
|
||||
orgID: orgID,
|
||||
decryptFn: decryptFn,
|
||||
}
|
||||
|
||||
am.gokitLogger = gokit_log.NewLogfmtLogger(logging.NewWrapper(am.logger))
|
||||
@@ -472,7 +475,7 @@ func (am *Alertmanager) buildReceiverIntegrations(receiver *apimodels.PostableAp
|
||||
|
||||
func (am *Alertmanager) buildReceiverIntegration(r *apimodels.PostableGrafanaReceiver, tmpl *template.Template) (NotificationChannel, error) {
|
||||
// secure settings are already encrypted at this point
|
||||
secureSettings := securejsondata.SecureJsonData(make(map[string][]byte, len(r.SecureSettings)))
|
||||
secureSettings := make(map[string][]byte, len(r.SecureSettings))
|
||||
|
||||
for k, v := range r.SecureSettings {
|
||||
d, err := base64.StdEncoding.DecodeString(v)
|
||||
@@ -501,13 +504,13 @@ func (am *Alertmanager) buildReceiverIntegration(r *apimodels.PostableGrafanaRec
|
||||
case "email":
|
||||
n, err = channels.NewEmailNotifier(cfg, tmpl) // Email notifier already has a default template.
|
||||
case "pagerduty":
|
||||
n, err = channels.NewPagerdutyNotifier(cfg, tmpl)
|
||||
n, err = channels.NewPagerdutyNotifier(cfg, tmpl, am.decryptFn)
|
||||
case "pushover":
|
||||
n, err = channels.NewPushoverNotifier(cfg, tmpl)
|
||||
n, err = channels.NewPushoverNotifier(cfg, tmpl, am.decryptFn)
|
||||
case "slack":
|
||||
n, err = channels.NewSlackNotifier(cfg, tmpl)
|
||||
n, err = channels.NewSlackNotifier(cfg, tmpl, am.decryptFn)
|
||||
case "telegram":
|
||||
n, err = channels.NewTelegramNotifier(cfg, tmpl)
|
||||
n, err = channels.NewTelegramNotifier(cfg, tmpl, am.decryptFn)
|
||||
case "victorops":
|
||||
n, err = channels.NewVictoropsNotifier(cfg, tmpl)
|
||||
case "teams":
|
||||
@@ -517,21 +520,21 @@ func (am *Alertmanager) buildReceiverIntegration(r *apimodels.PostableGrafanaRec
|
||||
case "kafka":
|
||||
n, err = channels.NewKafkaNotifier(cfg, tmpl)
|
||||
case "webhook":
|
||||
n, err = channels.NewWebHookNotifier(cfg, tmpl)
|
||||
n, err = channels.NewWebHookNotifier(cfg, tmpl, am.decryptFn)
|
||||
case "sensugo":
|
||||
n, err = channels.NewSensuGoNotifier(cfg, tmpl)
|
||||
n, err = channels.NewSensuGoNotifier(cfg, tmpl, am.decryptFn)
|
||||
case "discord":
|
||||
n, err = channels.NewDiscordNotifier(cfg, tmpl)
|
||||
case "googlechat":
|
||||
n, err = channels.NewGoogleChatNotifier(cfg, tmpl)
|
||||
case "LINE":
|
||||
n, err = channels.NewLineNotifier(cfg, tmpl)
|
||||
n, err = channels.NewLineNotifier(cfg, tmpl, am.decryptFn)
|
||||
case "threema":
|
||||
n, err = channels.NewThreemaNotifier(cfg, tmpl)
|
||||
n, err = channels.NewThreemaNotifier(cfg, tmpl, am.decryptFn)
|
||||
case "opsgenie":
|
||||
n, err = channels.NewOpsgenieNotifier(cfg, tmpl)
|
||||
n, err = channels.NewOpsgenieNotifier(cfg, tmpl, am.decryptFn)
|
||||
case "prometheus-alertmanager":
|
||||
n, err = channels.NewAlertmanagerNotifier(cfg, tmpl)
|
||||
n, err = channels.NewAlertmanagerNotifier(cfg, tmpl, am.decryptFn)
|
||||
default:
|
||||
return nil, InvalidReceiverError{
|
||||
Receiver: r,
|
||||
|
||||
@@ -9,23 +9,22 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
|
||||
gokit_log "github.com/go-kit/kit/log"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/prometheus/alertmanager/api/v2/models"
|
||||
"github.com/prometheus/alertmanager/provider/mem"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/logging"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/metrics"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/prometheus/alertmanager/api/v2/models"
|
||||
"github.com/prometheus/alertmanager/provider/mem"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func setupAMTest(t *testing.T) *Alertmanager {
|
||||
@@ -48,7 +47,8 @@ func setupAMTest(t *testing.T) *Alertmanager {
|
||||
}
|
||||
|
||||
kvStore := newFakeKVStore(t)
|
||||
am, err := newAlertmanager(1, cfg, s, kvStore, &NilPeer{}, m)
|
||||
decryptFn := ossencryption.ProvideService().GetDecryptedValue
|
||||
am, err := newAlertmanager(1, cfg, s, kvStore, &NilPeer{}, decryptFn, m)
|
||||
require.NoError(t, err)
|
||||
return am
|
||||
}
|
||||
|
||||
@@ -10,12 +10,17 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
old_notifiers "github.com/grafana/grafana/pkg/services/alerting/notifiers"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
)
|
||||
|
||||
// GetDecryptedValueFn is a function that returns the decrypted value of
|
||||
// the given key. If the key is not present, then it returns the fallback value.
|
||||
type GetDecryptedValueFn func(ctx context.Context, sjd map[string][]byte, key string, fallback string, secret string) string
|
||||
|
||||
// NewAlertmanagerNotifier returns a new Alertmanager notifier.
|
||||
func NewAlertmanagerNotifier(model *NotificationChannelConfig, t *template.Template) (*AlertmanagerNotifier, error) {
|
||||
func NewAlertmanagerNotifier(model *NotificationChannelConfig, _ *template.Template, fn GetDecryptedValueFn) (*AlertmanagerNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Reason: "no settings supplied"}
|
||||
}
|
||||
@@ -41,7 +46,7 @@ func NewAlertmanagerNotifier(model *NotificationChannelConfig, t *template.Templ
|
||||
urls = append(urls, u)
|
||||
}
|
||||
basicAuthUser := model.Settings.Get("basicAuthUser").MustString()
|
||||
basicAuthPassword := model.DecryptedValue("basicAuthPassword", model.Settings.Get("basicAuthPassword").MustString())
|
||||
basicAuthPassword := fn(context.Background(), model.SecureSettings, "basicAuthPassword", model.Settings.Get("basicAuthPassword").MustString(), setting.SecretKey)
|
||||
|
||||
return &AlertmanagerNotifier{
|
||||
NotifierBase: old_notifiers.NewNotifierBase(&models.AlertNotification{
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
|
||||
"github.com/prometheus/alertmanager/notify"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
@@ -77,7 +79,8 @@ func TestAlertmanagerNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
sn, err := NewAlertmanagerNotifier(m, tmpl)
|
||||
decryptFn := ossencryption.ProvideService().GetDecryptedValue
|
||||
sn, err := NewAlertmanagerNotifier(m, tmpl, decryptFn)
|
||||
if c.expInitError != "" {
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
return
|
||||
|
||||
@@ -6,13 +6,13 @@ import (
|
||||
"net/url"
|
||||
"path"
|
||||
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
old_notifiers "github.com/grafana/grafana/pkg/services/alerting/notifiers"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -20,8 +20,8 @@ var (
|
||||
)
|
||||
|
||||
// NewLineNotifier is the constructor for the LINE notifier
|
||||
func NewLineNotifier(model *NotificationChannelConfig, t *template.Template) (*LineNotifier, error) {
|
||||
token := model.DecryptedValue("token", model.Settings.Get("token").MustString())
|
||||
func NewLineNotifier(model *NotificationChannelConfig, t *template.Template, fn GetDecryptedValueFn) (*LineNotifier, error) {
|
||||
token := fn(context.Background(), model.SecureSettings, "token", model.Settings.Get("token").MustString(), setting.SecretKey)
|
||||
if token == "" {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "could not find token in settings"}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
|
||||
"github.com/prometheus/alertmanager/notify"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
@@ -88,7 +90,8 @@ func TestLineNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
pn, err := NewLineNotifier(m, tmpl)
|
||||
decryptFn := ossencryption.ProvideService().GetDecryptedValue
|
||||
pn, err := NewLineNotifier(m, tmpl, decryptFn)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
|
||||
@@ -7,16 +7,16 @@ import (
|
||||
"net/http"
|
||||
"sort"
|
||||
|
||||
"github.com/prometheus/alertmanager/notify"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
old_notifiers "github.com/grafana/grafana/pkg/services/alerting/notifiers"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/prometheus/alertmanager/notify"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -43,10 +43,10 @@ type OpsgenieNotifier struct {
|
||||
}
|
||||
|
||||
// NewOpsgenieNotifier is the constructor for the Opsgenie notifier
|
||||
func NewOpsgenieNotifier(model *NotificationChannelConfig, t *template.Template) (*OpsgenieNotifier, error) {
|
||||
func NewOpsgenieNotifier(model *NotificationChannelConfig, t *template.Template, fn GetDecryptedValueFn) (*OpsgenieNotifier, error) {
|
||||
autoClose := model.Settings.Get("autoClose").MustBool(true)
|
||||
overridePriority := model.Settings.Get("overridePriority").MustBool(true)
|
||||
apiKey := model.DecryptedValue("apiKey", model.Settings.Get("apiKey").MustString())
|
||||
apiKey := fn(context.Background(), model.SecureSettings, "apiKey", model.Settings.Get("apiKey").MustString(), setting.SecretKey)
|
||||
apiURL := model.Settings.Get("apiUrl").MustString()
|
||||
if apiKey == "" {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "could not find api key property in settings"}
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
|
||||
"github.com/prometheus/alertmanager/notify"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
@@ -168,7 +170,8 @@ func TestOpsgenieNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
pn, err := NewOpsgenieNotifier(m, tmpl)
|
||||
decryptFn := ossencryption.ProvideService().GetDecryptedValue
|
||||
pn, err := NewOpsgenieNotifier(m, tmpl, decryptFn)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
|
||||
@@ -6,15 +6,15 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/prometheus/alertmanager/notify"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
old_notifiers "github.com/grafana/grafana/pkg/services/alerting/notifiers"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/prometheus/alertmanager/notify"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -42,12 +42,12 @@ type PagerdutyNotifier struct {
|
||||
}
|
||||
|
||||
// NewPagerdutyNotifier is the constructor for the PagerDuty notifier
|
||||
func NewPagerdutyNotifier(model *NotificationChannelConfig, t *template.Template) (*PagerdutyNotifier, error) {
|
||||
func NewPagerdutyNotifier(model *NotificationChannelConfig, t *template.Template, fn GetDecryptedValueFn) (*PagerdutyNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
|
||||
key := model.DecryptedValue("integrationKey", model.Settings.Get("integrationKey").MustString())
|
||||
key := fn(context.Background(), model.SecureSettings, "integrationKey", model.Settings.Get("integrationKey").MustString(), setting.SecretKey)
|
||||
if key == "" {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "could not find integration key property in settings"}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
|
||||
"github.com/prometheus/alertmanager/notify"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
@@ -134,7 +136,8 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
pn, err := NewPagerdutyNotifier(m, tmpl)
|
||||
decryptFn := ossencryption.ProvideService().GetDecryptedValue
|
||||
pn, err := NewPagerdutyNotifier(m, tmpl, decryptFn)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
old_notifiers "github.com/grafana/grafana/pkg/services/alerting/notifiers"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
@@ -40,13 +41,13 @@ type PushoverNotifier struct {
|
||||
}
|
||||
|
||||
// NewSlackNotifier is the constructor for the Slack notifier
|
||||
func NewPushoverNotifier(model *NotificationChannelConfig, t *template.Template) (*PushoverNotifier, error) {
|
||||
func NewPushoverNotifier(model *NotificationChannelConfig, t *template.Template, fn GetDecryptedValueFn) (*PushoverNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
|
||||
userKey := model.DecryptedValue("userKey", model.Settings.Get("userKey").MustString())
|
||||
APIToken := model.DecryptedValue("apiToken", model.Settings.Get("apiToken").MustString())
|
||||
userKey := fn(context.Background(), model.SecureSettings, "userKey", model.Settings.Get("userKey").MustString(), setting.SecretKey)
|
||||
APIToken := fn(context.Background(), model.SecureSettings, "apiToken", model.Settings.Get("apiToken").MustString(), setting.SecretKey)
|
||||
device := model.Settings.Get("device").MustString()
|
||||
alertingPriority, err := strconv.Atoi(model.Settings.Get("priority").MustString("0")) // default Normal
|
||||
if err != nil {
|
||||
|
||||
@@ -11,6 +11,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
@@ -141,7 +143,8 @@ func TestPushoverNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
pn, err := NewPushoverNotifier(m, tmpl)
|
||||
decryptFn := ossencryption.ProvideService().GetDecryptedValue
|
||||
pn, err := NewPushoverNotifier(m, tmpl, decryptFn)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
old_notifiers "github.com/grafana/grafana/pkg/services/alerting/notifiers"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
@@ -31,7 +32,7 @@ type SensuGoNotifier struct {
|
||||
}
|
||||
|
||||
// NewSensuGoNotifier is the constructor for the SensuGo notifier
|
||||
func NewSensuGoNotifier(model *NotificationChannelConfig, t *template.Template) (*SensuGoNotifier, error) {
|
||||
func NewSensuGoNotifier(model *NotificationChannelConfig, t *template.Template, fn GetDecryptedValueFn) (*SensuGoNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
@@ -41,7 +42,7 @@ func NewSensuGoNotifier(model *NotificationChannelConfig, t *template.Template)
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "could not find URL property in settings"}
|
||||
}
|
||||
|
||||
apikey := model.DecryptedValue("apikey", model.Settings.Get("apikey").MustString())
|
||||
apikey := fn(context.Background(), model.SecureSettings, "apikey", model.Settings.Get("apikey").MustString(), setting.SecretKey)
|
||||
if apikey == "" {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "could not find the API key property in settings"}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
|
||||
"github.com/prometheus/alertmanager/notify"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
@@ -139,7 +141,8 @@ func TestSensuGoNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
sn, err := NewSensuGoNotifier(m, tmpl)
|
||||
decryptFn := ossencryption.ProvideService().GetDecryptedValue
|
||||
sn, err := NewSensuGoNotifier(m, tmpl, decryptFn)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
|
||||
@@ -14,14 +14,13 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/alertmanager/config"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
old_notifiers "github.com/grafana/grafana/pkg/services/alerting/notifiers"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/prometheus/alertmanager/config"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
)
|
||||
|
||||
// SlackNotifier is responsible for sending
|
||||
@@ -49,12 +48,12 @@ var reRecipient *regexp.Regexp = regexp.MustCompile("^((@[a-z0-9][a-zA-Z0-9._-]*
|
||||
var SlackAPIEndpoint = "https://slack.com/api/chat.postMessage"
|
||||
|
||||
// NewSlackNotifier is the constructor for the Slack notifier
|
||||
func NewSlackNotifier(model *NotificationChannelConfig, t *template.Template) (*SlackNotifier, error) {
|
||||
func NewSlackNotifier(model *NotificationChannelConfig, t *template.Template, fn GetDecryptedValueFn) (*SlackNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
|
||||
slackURL := model.DecryptedValue("url", model.Settings.Get("url").MustString())
|
||||
slackURL := fn(context.Background(), model.SecureSettings, "url", model.Settings.Get("url").MustString(), setting.SecretKey)
|
||||
if slackURL == "" {
|
||||
slackURL = SlackAPIEndpoint
|
||||
}
|
||||
@@ -99,7 +98,7 @@ func NewSlackNotifier(model *NotificationChannelConfig, t *template.Template) (*
|
||||
}
|
||||
}
|
||||
|
||||
token := model.DecryptedValue("token", model.Settings.Get("token").MustString())
|
||||
token := fn(context.Background(), model.SecureSettings, "token", model.Settings.Get("token").MustString(), setting.SecretKey)
|
||||
if token == "" && apiURL.String() == SlackAPIEndpoint {
|
||||
return nil, receiverInitError{Cfg: *model,
|
||||
Reason: "token must be specified when using the Slack chat API",
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
|
||||
"github.com/prometheus/alertmanager/notify"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
@@ -169,7 +171,8 @@ func TestSlackNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
pn, err := NewSlackNotifier(m, tmpl)
|
||||
decryptFn := ossencryption.ProvideService().GetDecryptedValue
|
||||
pn, err := NewSlackNotifier(m, tmpl, decryptFn)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
|
||||
@@ -6,13 +6,13 @@ import (
|
||||
"fmt"
|
||||
"mime/multipart"
|
||||
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
old_notifiers "github.com/grafana/grafana/pkg/services/alerting/notifiers"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -31,12 +31,12 @@ type TelegramNotifier struct {
|
||||
}
|
||||
|
||||
// NewTelegramNotifier is the constructor for the Telegram notifier
|
||||
func NewTelegramNotifier(model *NotificationChannelConfig, t *template.Template) (*TelegramNotifier, error) {
|
||||
func NewTelegramNotifier(model *NotificationChannelConfig, t *template.Template, fn GetDecryptedValueFn) (*TelegramNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
|
||||
botToken := model.DecryptedValue("bottoken", model.Settings.Get("bottoken").MustString())
|
||||
botToken := fn(context.Background(), model.SecureSettings, "bottoken", model.Settings.Get("bottoken").MustString(), setting.SecretKey)
|
||||
chatID := model.Settings.Get("chatid").MustString()
|
||||
message := model.Settings.Get("message").MustString(`{{ template "default.message" . }}`)
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
|
||||
"github.com/prometheus/alertmanager/notify"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
@@ -94,7 +96,8 @@ func TestTelegramNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
pn, err := NewTelegramNotifier(m, tmpl)
|
||||
decryptFn := ossencryption.ProvideService().GetDecryptedValue
|
||||
pn, err := NewTelegramNotifier(m, tmpl, decryptFn)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
|
||||
@@ -7,14 +7,14 @@ import (
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
old_notifiers "github.com/grafana/grafana/pkg/services/alerting/notifiers"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -33,14 +33,14 @@ type ThreemaNotifier struct {
|
||||
}
|
||||
|
||||
// NewThreemaNotifier is the constructor for the Threema notifier
|
||||
func NewThreemaNotifier(model *NotificationChannelConfig, t *template.Template) (*ThreemaNotifier, error) {
|
||||
func NewThreemaNotifier(model *NotificationChannelConfig, t *template.Template, fn GetDecryptedValueFn) (*ThreemaNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
||||
}
|
||||
|
||||
gatewayID := model.Settings.Get("gateway_id").MustString()
|
||||
recipientID := model.Settings.Get("recipient_id").MustString()
|
||||
apiSecret := model.DecryptedValue("api_secret", model.Settings.Get("api_secret").MustString())
|
||||
apiSecret := fn(context.Background(), model.SecureSettings, "api_secret", model.Settings.Get("api_secret").MustString(), setting.SecretKey)
|
||||
|
||||
// Validation
|
||||
if gatewayID == "" {
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
|
||||
"github.com/prometheus/alertmanager/notify"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
@@ -106,7 +108,8 @@ func TestThreemaNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
pn, err := NewThreemaNotifier(m, tmpl)
|
||||
decryptFn := ossencryption.ProvideService().GetDecryptedValue
|
||||
pn, err := NewThreemaNotifier(m, tmpl, decryptFn)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/prometheus/common/model"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/securejsondata"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
)
|
||||
|
||||
@@ -56,20 +55,12 @@ func getAlertStatusColor(status model.AlertStatus) string {
|
||||
}
|
||||
|
||||
type NotificationChannelConfig struct {
|
||||
UID string `json:"uid"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
DisableResolveMessage bool `json:"disableResolveMessage"`
|
||||
Settings *simplejson.Json `json:"settings"`
|
||||
SecureSettings securejsondata.SecureJsonData `json:"secureSettings"`
|
||||
}
|
||||
|
||||
// DecryptedValue returns decrypted value from secureSettings
|
||||
func (an *NotificationChannelConfig) DecryptedValue(field string, fallback string) string {
|
||||
if value, ok := an.SecureSettings.DecryptedValue(field); ok {
|
||||
return value
|
||||
}
|
||||
return fallback
|
||||
UID string `json:"uid"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
DisableResolveMessage bool `json:"disableResolveMessage"`
|
||||
Settings *simplejson.Json `json:"settings"`
|
||||
SecureSettings map[string][]byte `json:"secureSettings"`
|
||||
}
|
||||
|
||||
type httpCfg struct {
|
||||
|
||||
@@ -4,15 +4,15 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/prometheus/alertmanager/notify"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
old_notifiers "github.com/grafana/grafana/pkg/services/alerting/notifiers"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/prometheus/alertmanager/notify"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
)
|
||||
|
||||
// WebhookNotifier is responsible for sending
|
||||
@@ -30,7 +30,7 @@ type WebhookNotifier struct {
|
||||
|
||||
// NewWebHookNotifier is the constructor for
|
||||
// the WebHook notifier.
|
||||
func NewWebHookNotifier(model *NotificationChannelConfig, t *template.Template) (*WebhookNotifier, error) {
|
||||
func NewWebHookNotifier(model *NotificationChannelConfig, t *template.Template, fn GetDecryptedValueFn) (*WebhookNotifier, error) {
|
||||
if model.Settings == nil {
|
||||
return nil, receiverInitError{Cfg: *model, Reason: "could not find settings property"}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ func NewWebHookNotifier(model *NotificationChannelConfig, t *template.Template)
|
||||
}),
|
||||
URL: url,
|
||||
User: model.Settings.Get("username").MustString(),
|
||||
Password: model.DecryptedValue("password", model.Settings.Get("password").MustString()),
|
||||
Password: fn(context.Background(), model.SecureSettings, "password", model.Settings.Get("password").MustString(), setting.SecretKey),
|
||||
HTTPMethod: model.Settings.Get("httpMethod").MustString("POST"),
|
||||
MaxAlerts: model.Settings.Get("maxAlerts").MustInt(0),
|
||||
log: log.New("alerting.notifier.webhook"),
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
|
||||
"github.com/prometheus/alertmanager/notify"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
@@ -183,7 +185,8 @@ func TestWebhookNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
pn, err := NewWebHookNotifier(m, tmpl)
|
||||
decryptFn := ossencryption.ProvideService().GetDecryptedValue
|
||||
pn, err := NewWebHookNotifier(m, tmpl, decryptFn)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
|
||||
@@ -6,18 +6,18 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/logging"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/notifier/channels"
|
||||
|
||||
gokit_log "github.com/go-kit/kit/log"
|
||||
"github.com/prometheus/alertmanager/cluster"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/logging"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/metrics"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/prometheus/alertmanager/cluster"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -40,10 +40,14 @@ type MultiOrgAlertmanager struct {
|
||||
orgStore store.OrgStore
|
||||
kvStore kvstore.KVStore
|
||||
|
||||
decryptFn channels.GetDecryptedValueFn
|
||||
|
||||
metrics *metrics.MultiOrgAlertmanager
|
||||
}
|
||||
|
||||
func NewMultiOrgAlertmanager(cfg *setting.Cfg, configStore store.AlertingStore, orgStore store.OrgStore, kvStore kvstore.KVStore, m *metrics.MultiOrgAlertmanager, l log.Logger) (*MultiOrgAlertmanager, error) {
|
||||
func NewMultiOrgAlertmanager(cfg *setting.Cfg, configStore store.AlertingStore, orgStore store.OrgStore,
|
||||
kvStore kvstore.KVStore, decryptFn channels.GetDecryptedValueFn, m *metrics.MultiOrgAlertmanager, l log.Logger,
|
||||
) (*MultiOrgAlertmanager, error) {
|
||||
moa := &MultiOrgAlertmanager{
|
||||
logger: l,
|
||||
settings: cfg,
|
||||
@@ -51,6 +55,7 @@ func NewMultiOrgAlertmanager(cfg *setting.Cfg, configStore store.AlertingStore,
|
||||
configStore: configStore,
|
||||
orgStore: orgStore,
|
||||
kvStore: kvStore,
|
||||
decryptFn: decryptFn,
|
||||
metrics: m,
|
||||
}
|
||||
|
||||
@@ -162,7 +167,7 @@ func (moa *MultiOrgAlertmanager) SyncAlertmanagersForOrgs(ctx context.Context, o
|
||||
// To export them, we need to translate the metrics from each individual registry and,
|
||||
// then aggregate them on the main registry.
|
||||
m := metrics.NewAlertmanagerMetrics(moa.metrics.GetOrCreateOrgRegistry(orgID))
|
||||
am, err := newAlertmanager(orgID, moa.settings, moa.configStore, moa.kvStore, moa.peer, m)
|
||||
am, err := newAlertmanager(orgID, moa.settings, moa.configStore, moa.kvStore, moa.peer, moa.decryptFn, m)
|
||||
if err != nil {
|
||||
moa.logger.Error("unable to create Alertmanager for org", "org", orgID, "err", err)
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/metrics"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/testutil"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -29,6 +29,7 @@ func TestMultiOrgAlertmanager_SyncAlertmanagersForOrgs(t *testing.T) {
|
||||
tmpDir, err := ioutil.TempDir("", "test")
|
||||
require.NoError(t, err)
|
||||
kvStore := newFakeKVStore(t)
|
||||
decryptFn := ossencryption.ProvideService().GetDecryptedValue
|
||||
reg := prometheus.NewPedanticRegistry()
|
||||
m := metrics.NewNGAlert(reg)
|
||||
cfg := &setting.Cfg{
|
||||
@@ -39,7 +40,7 @@ func TestMultiOrgAlertmanager_SyncAlertmanagersForOrgs(t *testing.T) {
|
||||
DisabledOrgs: map[int64]struct{}{5: {}},
|
||||
}, // do not poll in tests.
|
||||
}
|
||||
mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, m.GetMultiOrgAlertmanagerMetrics(), log.New("testlogger"))
|
||||
mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), log.New("testlogger"))
|
||||
require.NoError(t, err)
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -108,9 +109,10 @@ func TestMultiOrgAlertmanager_AlertmanagerFor(t *testing.T) {
|
||||
UnifiedAlerting: setting.UnifiedAlertingSettings{AlertmanagerConfigPollInterval: 3 * time.Minute, DefaultConfiguration: setting.GetAlertmanagerDefaultConfiguration()}, // do not poll in tests.
|
||||
}
|
||||
kvStore := newFakeKVStore(t)
|
||||
decryptFn := ossencryption.ProvideService().GetDecryptedValue
|
||||
reg := prometheus.NewPedanticRegistry()
|
||||
m := metrics.NewNGAlert(reg)
|
||||
mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, m.GetMultiOrgAlertmanagerMetrics(), log.New("testlogger"))
|
||||
mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), log.New("testlogger"))
|
||||
require.NoError(t, err)
|
||||
ctx := context.Background()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user