Unified Alerting: Validate PostableSilence API. (#46892)

Invalid PostableSilences could be passed to the Alerting API - if they
are passed all the way down into the alertmanager data layer, they can
cause a panic. This change adds validation to avoid a panic in the
alertmanager.
pull/48323/head
Joe Blubaugh 3 years ago committed by GitHub
parent 7798b08b1e
commit 103087a1a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      pkg/services/ngalert/api/api_alertmanager.go
  2. 60
      pkg/services/ngalert/api/api_alertmanager_test.go

@ -9,6 +9,7 @@ import (
"strings"
"time"
"github.com/go-openapi/strfmt"
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models"
@ -50,6 +51,12 @@ func (srv AlertmanagerSrv) RouteGetAMStatus(c *models.ReqContext) response.Respo
}
func (srv AlertmanagerSrv) RouteCreateSilence(c *models.ReqContext, postableSilence apimodels.PostableSilence) response.Response {
err := postableSilence.Validate(strfmt.Default)
if err != nil {
srv.log.Error("silence failed validation", "err", err)
return ErrResp(http.StatusBadRequest, err, "silence failed validation")
}
am, errResp := srv.AlertmanagerFor(c.OrgId)
if errResp != nil {
return errResp

@ -239,6 +239,66 @@ func TestAlertmanagerConfig(t *testing.T) {
})
}
func TestSilenceCreate(t *testing.T) {
makeSilence := func(comment string, createdBy string,
startsAt, endsAt strfmt.DateTime, matchers amv2.Matchers) amv2.Silence {
return amv2.Silence{
Comment: &comment,
CreatedBy: &createdBy,
StartsAt: &startsAt,
EndsAt: &endsAt,
Matchers: matchers,
}
}
now := time.Now()
dt := func(t time.Time) strfmt.DateTime { return strfmt.DateTime(t) }
tru := true
testString := "testName"
matchers := amv2.Matchers{&amv2.Matcher{Name: &testString, IsEqual: &tru, IsRegex: &tru, Value: &testString}}
cases := []struct {
name string
silence amv2.Silence
status int
}{
{"Valid Silence",
makeSilence("", "tests", dt(now), dt(now.Add(1*time.Second)), matchers),
http.StatusAccepted,
},
{"No Comment Silence",
func() amv2.Silence {
s := makeSilence("", "tests", dt(now), dt(now.Add(1*time.Second)), matchers)
s.Comment = nil
return s
}(),
http.StatusBadRequest,
},
}
for _, cas := range cases {
t.Run(cas.name, func(t *testing.T) {
rc := models.ReqContext{
Context: &web.Context{
Req: &http.Request{},
},
SignedInUser: &models.SignedInUser{
OrgRole: models.ROLE_EDITOR,
OrgId: 1,
},
}
srv := createSut(t, nil)
resp := srv.RouteCreateSilence(&rc, amv2.PostableSilence{
ID: "",
Silence: cas.silence,
})
require.Equal(t, cas.status, resp.Status())
})
}
}
func TestRouteCreateSilence(t *testing.T) {
tesCases := []struct {
name string

Loading…
Cancel
Save