From 39b5a8dbd2b37dea29a671b88e8db1b14d3fc4dc Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Thu, 17 Nov 2016 15:32:34 -0600 Subject: [PATCH] Move alerta api token to header and add option to skip TLS verification. --- CHANGELOG.md | 1 + integrations/streamer_test.go | 10 +++++++-- server/server_test.go | 4 ++++ services/alerta/config.go | 2 ++ services/alerta/service.go | 39 +++++++++++++++++++++++++---------- 5 files changed, 43 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a419fb86e..5d5a25b48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ stream - [#327](https://github.com/influxdata/kapacitor/issues/327): You can now window based on count in addition to time. - [#913](https://github.com/influxdata/kapacitor/issues/913): Add fillPeriod option to Window node, so that the first emit waits till the period has elapsed before emitting. - [#898](https://github.com/influxdata/kapacitor/issues/898): Now when the Window node every value is zero, the window will be emitted immediately for each new point. +- [#1052](https://github.com/influxdata/kapacitor/issues/1052): Move alerta api token to header and add option to skip TLS verification. ### Bugfixes diff --git a/integrations/streamer_test.go b/integrations/streamer_test.go index 60a711224..ec4c81a1b 100644 --- a/integrations/streamer_test.go +++ b/integrations/streamer_test.go @@ -6790,9 +6790,12 @@ func TestStream_AlertAlerta(t *testing.T) { dec.Decode(&pd) if rc := atomic.LoadInt32(&requestCount); rc == 1 { - if exp := "/alert?api-key=testtoken1234567"; r.URL.String() != exp { + if exp := "/alert"; r.URL.String() != exp { t.Errorf("unexpected url got %s exp %s", r.URL.String(), exp) } + if exp := "Bearer testtoken1234567"; r.Header.Get("Authorization") != exp { + t.Errorf("unexpected token in header got %s exp %s", r.Header.Get("Authorization"), exp) + } if exp := "cpu"; pd.Resource != exp { t.Errorf("unexpected resource got %s exp %s", pd.Resource, exp) } @@ -6815,9 +6818,12 @@ func TestStream_AlertAlerta(t *testing.T) { t.Errorf("unexpected origin got %s exp %s", pd.Origin, exp) } } else { - if exp := "/alert?api-key=anothertesttoken"; r.URL.String() != exp { + if exp := "/alert"; r.URL.String() != exp { t.Errorf("unexpected url got %s exp %s", r.URL.String(), exp) } + if exp := "Bearer anothertesttoken"; r.Header.Get("Authorization") != exp { + t.Errorf("unexpected token in header got %s exp %s", r.Header.Get("Authorization"), exp) + } if exp := "resource: serverA"; pd.Resource != exp { t.Errorf("unexpected resource got %s exp %s", pd.Resource, exp) } diff --git a/server/server_test.go b/server/server_test.go index b02144e27..3d4b9ea77 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -5296,6 +5296,7 @@ func TestServer_UpdateConfig(t *testing.T) { "origin": "", "token": false, "url": "http://alerta.example.com", + "insecure-skip-verify": false, }, Redacted: []string{ "token", @@ -5310,6 +5311,7 @@ func TestServer_UpdateConfig(t *testing.T) { "origin": "", "token": false, "url": "http://alerta.example.com", + "insecure-skip-verify": false, }, Redacted: []string{ "token", @@ -5333,6 +5335,7 @@ func TestServer_UpdateConfig(t *testing.T) { "origin": "kapacitor", "token": true, "url": "http://alerta.example.com", + "insecure-skip-verify": false, }, Redacted: []string{ "token", @@ -5347,6 +5350,7 @@ func TestServer_UpdateConfig(t *testing.T) { "origin": "kapacitor", "token": true, "url": "http://alerta.example.com", + "insecure-skip-verify": false, }, Redacted: []string{ "token", diff --git a/services/alerta/config.go b/services/alerta/config.go index 13eeacb09..75882167a 100644 --- a/services/alerta/config.go +++ b/services/alerta/config.go @@ -11,6 +11,8 @@ type Config struct { Enabled bool `toml:"enabled" override:"enabled"` // The Alerta URL. URL string `toml:"url" override:"url"` + // Whether to skip the tls verification of the alerta host + InsecureSkipVerify bool `toml:"insecure-skip-verify" override:"insecure-skip-verify"` // The authentication token for this notification, can be overridden per alert. Token string `toml:"token" override:"token,redact"` // The environment in which to raise the alert. diff --git a/services/alerta/service.go b/services/alerta/service.go index ae96a3205..bc75f4e0a 100644 --- a/services/alerta/service.go +++ b/services/alerta/service.go @@ -2,10 +2,10 @@ package alerta import ( "bytes" + "crypto/tls" "encoding/json" "errors" "fmt" - "io" "io/ioutil" "log" "net/http" @@ -16,6 +16,7 @@ import ( type Service struct { configValue atomic.Value + clientValue atomic.Value logger *log.Logger } @@ -24,6 +25,11 @@ func NewService(c Config, l *log.Logger) *Service { logger: l, } s.configValue.Store(c) + s.clientValue.Store(&http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: c.InsecureSkipVerify}, + }, + }) return s } @@ -95,7 +101,13 @@ func (s *Service) Update(newConfig []interface{}) error { return fmt.Errorf("expected config object to be of type %T, got %T", c, newConfig[0]) } else { s.configValue.Store(c) + s.clientValue.Store(&http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: c.InsecureSkipVerify}, + }, + }) } + return nil } @@ -104,12 +116,13 @@ func (s *Service) Alert(token, resource, event, environment, severity, group, va return errors.New("Resource and Event are required to send an alert") } - url, post, err := s.preparePost(token, resource, event, environment, severity, group, value, message, origin, service, data) + req, err := s.preparePost(token, resource, event, environment, severity, group, value, message, origin, service, data) if err != nil { return err } - resp, err := http.Post(url, "application/json", post) + client := s.clientValue.Load().(*http.Client) + resp, err := client.Do(req) if err != nil { return err } @@ -131,11 +144,11 @@ func (s *Service) Alert(token, resource, event, environment, severity, group, va return nil } -func (s *Service) preparePost(token, resource, event, environment, severity, group, value, message, origin string, service []string, data interface{}) (string, io.Reader, error) { +func (s *Service) preparePost(token, resource, event, environment, severity, group, value, message, origin string, service []string, data interface{}) (*http.Request, error) { c := s.config() if !c.Enabled { - return "", nil, errors.New("service is not enabled") + return nil, errors.New("service is not enabled") } if token == "" { @@ -152,12 +165,9 @@ func (s *Service) preparePost(token, resource, event, environment, severity, gro u, err := url.Parse(c.URL) if err != nil { - return "", nil, err + return nil, err } u.Path = path.Join(u.Path, "alert") - v := url.Values{} - v.Set("api-key", token) - u.RawQuery = v.Encode() postData := make(map[string]interface{}) postData["resource"] = resource @@ -177,8 +187,15 @@ func (s *Service) preparePost(token, resource, event, environment, severity, gro enc := json.NewEncoder(&post) err = enc.Encode(postData) if err != nil { - return "", nil, err + return nil, err + } + + req, err := http.NewRequest("POST", u.String(), &post) + req.Header.Add("Authorization", "Bearer "+token) + req.Header.Add("Content-Type", "application/json") + if err != nil { + return nil, err } - return u.String(), &post, nil + return req, nil }