Add compat function for notify.GrafanaIntegrationConfig to EmbeddedContactPoint (#75995)

Co-authored-by: Matthew Jacobson <matthew.jacobson@grafana.com>
This commit is contained in:
Yuri Tseretyan 2023-10-05 16:13:34 -04:00 committed by GitHub
parent bd5d67ed28
commit 4343c99e2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 59 deletions

View File

@ -3,7 +3,9 @@ package provisioning
import ( import (
alertingNotify "github.com/grafana/alerting/notify" alertingNotify "github.com/grafana/alerting/notify"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
"github.com/grafana/grafana/pkg/services/ngalert/models"
) )
func EmbeddedContactPointToGrafanaIntegrationConfig(e definitions.EmbeddedContactPoint) (alertingNotify.GrafanaIntegrationConfig, error) { func EmbeddedContactPointToGrafanaIntegrationConfig(e definitions.EmbeddedContactPoint) (alertingNotify.GrafanaIntegrationConfig, error) {
@ -20,3 +22,26 @@ func EmbeddedContactPointToGrafanaIntegrationConfig(e definitions.EmbeddedContac
SecureSettings: nil, SecureSettings: nil,
}, nil }, nil
} }
func PostableGrafanaReceiverToEmbeddedContactPoint(contactPoint *definitions.PostableGrafanaReceiver, provenance models.Provenance, decryptValue func(string) string) (definitions.EmbeddedContactPoint, error) {
simpleJson, err := simplejson.NewJson(contactPoint.Settings)
if err != nil {
return definitions.EmbeddedContactPoint{}, err
}
embeddedContactPoint := definitions.EmbeddedContactPoint{
UID: contactPoint.UID,
Type: contactPoint.Type,
Name: contactPoint.Name,
DisableResolveMessage: contactPoint.DisableResolveMessage,
Settings: simpleJson,
Provenance: string(provenance),
}
for k, v := range contactPoint.SecureSettings {
decryptedValue := decryptValue(v)
if decryptedValue == "" {
continue
}
embeddedContactPoint.Settings.Set(k, decryptedValue)
}
return embeddedContactPoint, nil
}

View File

@ -12,7 +12,6 @@ import (
alertingNotify "github.com/grafana/alerting/notify" alertingNotify "github.com/grafana/alerting/notify"
"github.com/prometheus/alertmanager/config" "github.com/prometheus/alertmanager/config"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
@ -77,42 +76,21 @@ func (ecp *ContactPointService) GetContactPoints(ctx context.Context, q ContactP
if err != nil { if err != nil {
return nil, err return nil, err
} }
contactPoints := []apimodels.EmbeddedContactPoint{} var contactPoints []apimodels.EmbeddedContactPoint
for _, contactPoint := range revision.cfg.GetGrafanaReceiverMap() { for _, contactPoint := range revision.cfg.GetGrafanaReceiverMap() {
if q.Name != "" && contactPoint.Name != q.Name { if q.Name != "" && contactPoint.Name != q.Name {
continue continue
} }
simpleJson, err := simplejson.NewJson(contactPoint.Settings) embeddedContactPoint, err := PostableGrafanaReceiverToEmbeddedContactPoint(
contactPoint,
provenances[contactPoint.UID],
ecp.decryptValueOrRedacted(q.Decrypt, contactPoint.UID),
)
if err != nil { if err != nil {
return nil, err return nil, err
} }
embeddedContactPoint := apimodels.EmbeddedContactPoint{
UID: contactPoint.UID,
Type: contactPoint.Type,
Name: contactPoint.Name,
DisableResolveMessage: contactPoint.DisableResolveMessage,
Settings: simpleJson,
}
if val, exists := provenances[embeddedContactPoint.UID]; exists && val != "" {
embeddedContactPoint.Provenance = string(val)
}
for k, v := range contactPoint.SecureSettings {
decryptedValue, err := ecp.decryptValue(v)
if err != nil {
ecp.log.Warn("Decrypting value failed", "error", err.Error())
continue
}
if decryptedValue == "" {
continue
}
if q.Decrypt {
embeddedContactPoint.Settings.Set(k, decryptedValue)
} else {
embeddedContactPoint.Settings.Set(k, apimodels.RedactedValue)
}
}
contactPoints = append(contactPoints, embeddedContactPoint) contactPoints = append(contactPoints, embeddedContactPoint)
} }
sort.SliceStable(contactPoints, func(i, j int) bool { sort.SliceStable(contactPoints, func(i, j int) bool {
@ -138,28 +116,14 @@ func (ecp *ContactPointService) getContactPointDecrypted(ctx context.Context, or
if receiver.UID != uid { if receiver.UID != uid {
continue continue
} }
simpleJson, err := simplejson.NewJson(receiver.Settings) embeddedContactPoint, err := PostableGrafanaReceiverToEmbeddedContactPoint(
receiver,
models.ProvenanceNone,
ecp.decryptValueOrRedacted(true, receiver.UID),
)
if err != nil { if err != nil {
return apimodels.EmbeddedContactPoint{}, err return apimodels.EmbeddedContactPoint{}, err
} }
embeddedContactPoint := apimodels.EmbeddedContactPoint{
UID: receiver.UID,
Type: receiver.Type,
Name: receiver.Name,
DisableResolveMessage: receiver.DisableResolveMessage,
Settings: simpleJson,
}
for k, v := range receiver.SecureSettings {
decryptedValue, err := ecp.decryptValue(v)
if err != nil {
ecp.log.Warn("Decrypting value failed", "error", err.Error())
continue
}
if decryptedValue == "" {
continue
}
embeddedContactPoint.Settings.Set(k, decryptedValue)
}
return embeddedContactPoint, nil return embeddedContactPoint, nil
} }
return apimodels.EmbeddedContactPoint{}, fmt.Errorf("%w: contact point with uid '%s' not found", ErrNotFound, uid) return apimodels.EmbeddedContactPoint{}, fmt.Errorf("%w: contact point with uid '%s' not found", ErrNotFound, uid)
@ -428,18 +392,27 @@ func isContactPointInUse(name string, routes []*apimodels.Route) bool {
return false return false
} }
func (ecp *ContactPointService) decryptValue(value string) (string, error) { // decryptValueOrRedacted returns a function that decodes a string from Base64 and then decrypts using secrets.Service.
decodeValue, err := base64.StdEncoding.DecodeString(value) // If argument 'decrypt' is false, then returns definitions.RedactedValue regardless of the decrypted value.
if err != nil { // Otherwise, it returns the decoded and decrypted value. The function returns empty string in the case of errors, which are logged
return "", err func (ecp *ContactPointService) decryptValueOrRedacted(decrypt bool, integrationUID string) func(v string) string {
return func(value string) string {
decodeValue, err := base64.StdEncoding.DecodeString(value)
if err != nil {
ecp.log.Warn("Failed to decode secret value from Base64", "error", err.Error(), "integrationUid", integrationUID)
return ""
}
decryptedValue, err := ecp.encryptionService.Decrypt(context.Background(), decodeValue)
if err != nil {
ecp.log.Warn("Failed to decrypt secret value", "error", err.Error(), "integrationUid", integrationUID)
return ""
}
if decrypt {
return string(decryptedValue)
} else {
return apimodels.RedactedValue
}
} }
decryptedValue, err := ecp.encryptionService.Decrypt(context.Background(), decodeValue)
if err != nil {
return "", err
}
return string(decryptedValue), nil
} }
func (ecp *ContactPointService) encryptValue(value string) (string, error) { func (ecp *ContactPointService) encryptValue(value string) (string, error) {