Alerting: Support storing sensitive notifier settings securely/encrypted (#25114)
Support storing sensitive notification settings securely/encrypted. Move slack notifier url and api token to secure settings. Migrating slack notifier to store token and url encrypted is currently a manual process by saving an existing slack alert notification channel. saving an existing slack alert notification channel will reset the stored non-secure url and token. Closes #25113 Ref #25967 Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
This commit is contained in:
co-authored by
Marcus Efraimsson
parent
b26ef1db25
commit
292c985b76
+84
-5
@@ -281,6 +281,11 @@ func CreateAlertNotification(c *models.ReqContext, cmd models.CreateAlertNotific
|
||||
func UpdateAlertNotification(c *models.ReqContext, cmd models.UpdateAlertNotificationCommand) Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
err := fillWithSecureSettingsData(&cmd)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to update alert notification", err)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to update alert notification", err)
|
||||
}
|
||||
@@ -289,13 +294,27 @@ func UpdateAlertNotification(c *models.ReqContext, cmd models.UpdateAlertNotific
|
||||
return Error(404, "Alert notification not found", nil)
|
||||
}
|
||||
|
||||
return JSON(200, dtos.NewAlertNotification(cmd.Result))
|
||||
query := models.GetAlertNotificationsQuery{
|
||||
OrgId: c.OrgId,
|
||||
Id: cmd.Id,
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "Failed to get alert notification", err)
|
||||
}
|
||||
|
||||
return JSON(200, dtos.NewAlertNotification(query.Result))
|
||||
}
|
||||
|
||||
func UpdateAlertNotificationByUID(c *models.ReqContext, cmd models.UpdateAlertNotificationWithUidCommand) Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.Uid = c.Params("uid")
|
||||
|
||||
err := fillWithSecureSettingsDataByUID(&cmd)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to update alert notification", err)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to update alert notification", err)
|
||||
}
|
||||
@@ -304,7 +323,64 @@ func UpdateAlertNotificationByUID(c *models.ReqContext, cmd models.UpdateAlertNo
|
||||
return Error(404, "Alert notification not found", nil)
|
||||
}
|
||||
|
||||
return JSON(200, dtos.NewAlertNotification(cmd.Result))
|
||||
query := models.GetAlertNotificationsWithUidQuery{
|
||||
OrgId: cmd.OrgId,
|
||||
Uid: cmd.Uid,
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "Failed to get alert notification", err)
|
||||
}
|
||||
|
||||
return JSON(200, dtos.NewAlertNotification(query.Result))
|
||||
}
|
||||
|
||||
func fillWithSecureSettingsData(cmd *models.UpdateAlertNotificationCommand) error {
|
||||
if len(cmd.SecureSettings) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
query := &models.GetAlertNotificationsQuery{
|
||||
OrgId: cmd.OrgId,
|
||||
Id: cmd.Id,
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(query); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
secureSettings := query.Result.SecureSettings.Decrypt()
|
||||
for k, v := range secureSettings {
|
||||
if _, ok := cmd.SecureSettings[k]; !ok {
|
||||
cmd.SecureSettings[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func fillWithSecureSettingsDataByUID(cmd *models.UpdateAlertNotificationWithUidCommand) error {
|
||||
if len(cmd.SecureSettings) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
query := &models.GetAlertNotificationsWithUidQuery{
|
||||
OrgId: cmd.OrgId,
|
||||
Uid: cmd.Uid,
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(query); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
secureSettings := query.Result.SecureSettings.Decrypt()
|
||||
for k, v := range secureSettings {
|
||||
if _, ok := cmd.SecureSettings[k]; !ok {
|
||||
cmd.SecureSettings[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteAlertNotification(c *models.ReqContext) Response {
|
||||
@@ -336,9 +412,12 @@ func DeleteAlertNotificationByUID(c *models.ReqContext) Response {
|
||||
//POST /api/alert-notifications/test
|
||||
func NotificationTest(c *models.ReqContext, dto dtos.NotificationTestCommand) Response {
|
||||
cmd := &alerting.NotificationTestCommand{
|
||||
Name: dto.Name,
|
||||
Type: dto.Type,
|
||||
Settings: dto.Settings,
|
||||
OrgID: c.OrgId,
|
||||
ID: dto.ID,
|
||||
Name: dto.Name,
|
||||
Type: dto.Type,
|
||||
Settings: dto.Settings,
|
||||
SecureSettings: dto.SecureSettings,
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(cmd); err != nil {
|
||||
|
||||
@@ -48,7 +48,7 @@ func formatShort(interval time.Duration) string {
|
||||
}
|
||||
|
||||
func NewAlertNotification(notification *models.AlertNotification) *AlertNotification {
|
||||
return &AlertNotification{
|
||||
dto := &AlertNotification{
|
||||
Id: notification.Id,
|
||||
Uid: notification.Uid,
|
||||
Name: notification.Name,
|
||||
@@ -60,7 +60,16 @@ func NewAlertNotification(notification *models.AlertNotification) *AlertNotifica
|
||||
SendReminder: notification.SendReminder,
|
||||
DisableResolveMessage: notification.DisableResolveMessage,
|
||||
Settings: notification.Settings,
|
||||
SecureFields: map[string]bool{},
|
||||
}
|
||||
|
||||
if notification.SecureSettings != nil {
|
||||
for k := range notification.SecureSettings {
|
||||
dto.SecureFields[k] = true
|
||||
}
|
||||
}
|
||||
|
||||
return dto
|
||||
}
|
||||
|
||||
type AlertNotification struct {
|
||||
@@ -75,6 +84,7 @@ type AlertNotification struct {
|
||||
Created time.Time `json:"created"`
|
||||
Updated time.Time `json:"updated"`
|
||||
Settings *simplejson.Json `json:"settings"`
|
||||
SecureFields map[string]bool `json:"secureFields"`
|
||||
}
|
||||
|
||||
func NewAlertNotificationLookup(notification *models.AlertNotification) *AlertNotificationLookup {
|
||||
@@ -122,12 +132,14 @@ type EvalMatch struct {
|
||||
}
|
||||
|
||||
type NotificationTestCommand struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
SendReminder bool `json:"sendReminder"`
|
||||
DisableResolveMessage bool `json:"disableResolveMessage"`
|
||||
Frequency string `json:"frequency"`
|
||||
Settings *simplejson.Json `json:"settings"`
|
||||
ID int64 `json:"id,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
SendReminder bool `json:"sendReminder"`
|
||||
DisableResolveMessage bool `json:"disableResolveMessage"`
|
||||
Frequency string `json:"frequency"`
|
||||
Settings *simplejson.Json `json:"settings"`
|
||||
SecureSettings map[string]string `json:"secureSettings"`
|
||||
}
|
||||
|
||||
type PauseAlertCommand struct {
|
||||
|
||||
Reference in New Issue
Block a user