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:
Joan López de la Franca Beltran
2021-10-07 16:33:50 +02:00
committed by GitHub
parent da813877fb
commit 722c414fef
141 changed files with 1968 additions and 1197 deletions

View File

@@ -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,

View File

@@ -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
}

View File

@@ -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{

View File

@@ -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

View File

@@ -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"}
}

View File

@@ -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())

View File

@@ -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"}

View File

@@ -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())

View File

@@ -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"}
}

View File

@@ -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())

View File

@@ -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 {

View File

@@ -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())

View File

@@ -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"}
}

View File

@@ -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())

View File

@@ -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",

View File

@@ -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())

View File

@@ -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" . }}`)

View File

@@ -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())

View File

@@ -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 == "" {

View File

@@ -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())

View File

@@ -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 {

View File

@@ -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"),

View File

@@ -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())

View File

@@ -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)
}

View File

@@ -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()