From bf0dfa44ecbaa9cd1d95cf6e0a4c3f5ce88214b4 Mon Sep 17 00:00:00 2001 From: Yannick te Kulve <738464+YannickTeKulve@users.noreply.github.com> Date: Fri, 19 Jan 2024 18:10:44 +0100 Subject: [PATCH] Add basic auth to loki client (#394) * Add basic auth to loki client Signed-off-by: Yannick te Kulve <738464+YannickTeKulve@users.noreply.github.com> * Add extra tests Signed-off-by: Yannick te Kulve <738464+YannickTeKulve@users.noreply.github.com> --------- Signed-off-by: Yannick te Kulve <738464+YannickTeKulve@users.noreply.github.com> --- pkg/config/config.go | 2 ++ pkg/config/target_factory.go | 10 ++++++++++ pkg/config/target_factory_test.go | 30 ++++++++++++++++++++++++++---- pkg/target/loki/loki.go | 9 +++++++++ pkg/target/loki/loki_test.go | 6 ++++++ 5 files changed, 53 insertions(+), 4 deletions(-) diff --git a/pkg/config/config.go b/pkg/config/config.go index 293ce221..867df47d 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -96,6 +96,8 @@ type Loki struct { Certificate string `mapstructure:"certificate"` Path string `mapstructure:"path"` Channels []*Loki `mapstructure:"channels"` + Username string `mapstructure:"username"` + Password string `mapstructure:"password"` } // Elasticsearch configuration diff --git a/pkg/config/target_factory.go b/pkg/config/target_factory.go index d38fe43c..83e96c6a 100644 --- a/pkg/config/target_factory.go +++ b/pkg/config/target_factory.go @@ -371,6 +371,8 @@ func (f *TargetFactory) createLokiClient(config, parent *Loki) target.Client { setFallback(&config.Certificate, parent.Certificate) setFallback(&config.Path, parent.Path) setBool(&config.SkipTLS, parent.SkipTLS) + setFallback(&config.Username, parent.Username) + setFallback(&config.Password, parent.Password) config.MapBaseParent(parent.TargetBaseOptions) @@ -391,6 +393,8 @@ func (f *TargetFactory) createLokiClient(config, parent *Loki) target.Client { Host: config.Host + config.Path, CustomLabels: config.CustomFields, HTTPClient: http.NewClient(config.Certificate, config.SkipTLS), + Username: config.Username, + Password: config.Password, }) } @@ -799,6 +803,12 @@ func (f *TargetFactory) mapSecretValues(config any, ref, mountedSecret string) { if values.Host != "" { c.Host = values.Host } + if values.Username != "" { + c.Username = values.Username + } + if values.Password != "" { + c.Password = values.Password + } case *Slack: if values.Webhook != "" { diff --git a/pkg/config/target_factory_test.go b/pkg/config/target_factory_test.go index a25bf272..0d43bb74 100644 --- a/pkg/config/target_factory_test.go +++ b/pkg/config/target_factory_test.go @@ -298,10 +298,21 @@ func Test_GetValuesFromSecret(t *testing.T) { t.Fatal("Expected one client created") } - fv := reflect.ValueOf(clients[0]).Elem().FieldByName("host") - if v := fv.String(); v != "http://localhost:9200/api/prom/push" { + client := reflect.ValueOf(clients[0]).Elem() + + if v := client.FieldByName("host").String(); v != "http://localhost:9200/api/prom/push" { t.Errorf("Expected host from secret, got %s", v) } + + username := client.FieldByName("username").String() + if username != "username" { + t.Errorf("Expected username from secret, got %s", username) + } + + password := client.FieldByName("password").String() + if password != "password" { + t.Errorf("Expected password from secret, got %s", password) + } }) t.Run("Get Elasticsearch values from Secret", func(t *testing.T) { @@ -625,10 +636,21 @@ func Test_GetValuesFromMountedSecret(t *testing.T) { t.Error("Expected one client created") } - fv := reflect.ValueOf(clients[0]).Elem().FieldByName("host") - if v := fv.String(); v != "http://localhost:9200/api/prom/push" { + client := reflect.ValueOf(clients[0]).Elem() + if v := client.FieldByName("host").String(); v != "http://localhost:9200/api/prom/push" { t.Errorf("Expected host from mounted secret, got %s", v) } + + username := client.FieldByName("username").String() + if username != "username" { + t.Errorf("Expected username from mounted secret, got %s", username) + } + + password := client.FieldByName("password").String() + if password != "password" { + t.Errorf("Expected password from mounted secret, got %s", password) + } + }) t.Run("Get Elasticsearch values from MountedSecret", func(t *testing.T) { diff --git a/pkg/target/loki/loki.go b/pkg/target/loki/loki.go index 9513ea12..33ee603d 100644 --- a/pkg/target/loki/loki.go +++ b/pkg/target/loki/loki.go @@ -15,6 +15,8 @@ type Options struct { Host string CustomLabels map[string]string HTTPClient http.Client + Username string + Password string } type payload struct { @@ -92,6 +94,8 @@ type client struct { host string client http.Client customLabels map[string]string + username string + password string } func (l *client) Send(result v1alpha2.PolicyReportResult) { @@ -101,6 +105,9 @@ func (l *client) Send(result v1alpha2.PolicyReportResult) { } req.Header.Set("Content-Type", "application/json") + if l.username != "" { + req.SetBasicAuth(l.username, l.password) + } resp, err := l.client.Do(req) http.ProcessHTTPResponse(l.Name(), resp, err) @@ -113,5 +120,7 @@ func NewClient(options Options) target.Client { options.Host, options.HTTPClient, options.CustomLabels, + options.Username, + options.Password, } } diff --git a/pkg/target/loki/loki_test.go b/pkg/target/loki/loki_test.go index d59a6f99..18f6b7a3 100644 --- a/pkg/target/loki/loki_test.go +++ b/pkg/target/loki/loki_test.go @@ -40,6 +40,10 @@ func Test_LokiTarget(t *testing.T) { t.Errorf("Unexpected Host: %s", url) } + if req.Header.Get("Authorization") == "" { + t.Error("Expected Authentication header for BasicAuth is set") + } + expectedLine := fmt.Sprintf("[%s] %s", strings.ToUpper(fixtures.CompleteTargetSendResult.Priority.String()), fixtures.CompleteTargetSendResult.Message) labels, line := convertAndValidateBody(req, t) if line != expectedLine { @@ -95,6 +99,8 @@ func Test_LokiTarget(t *testing.T) { Host: "http://localhost:3100/api/prom/push", CustomLabels: map[string]string{"custom": "label"}, HTTPClient: testClient{callback, 200}, + Username: "username", + Password: "password", }) client.Send(fixtures.CompleteTargetSendResult) })