From 740bb2cc00d59ea417c2e5600f4e718ef35d3169 Mon Sep 17 00:00:00 2001 From: Roman Khavronenko Date: Fri, 30 Sep 2022 17:10:17 +0200 Subject: [PATCH] vmalert: support auth configs per static_target (#3188) Allow configuring authorization params per list of targets in vmalert's notifier config for `static_configs`. See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2690 Signed-off-by: hagen1778 Signed-off-by: hagen1778 --- app/vmalert/README.md | 37 +++++++++++++++++-- app/vmalert/notifier/config.go | 2 + app/vmalert/notifier/config_watcher.go | 31 +++++++++++++++- app/vmalert/notifier/config_watcher_test.go | 19 ++++++++++ .../notifier/testdata/static.good.yaml | 16 +++++++- docs/CHANGELOG.md | 1 + docs/vmalert.md | 37 +++++++++++++++++-- 7 files changed, 135 insertions(+), 8 deletions(-) diff --git a/app/vmalert/README.md b/app/vmalert/README.md index 13724ae9b..b020eada7 100644 --- a/app/vmalert/README.md +++ b/app/vmalert/README.md @@ -1158,7 +1158,7 @@ is the following: # password and password_file are mutually exclusive. basic_auth: [ username: ] - [ password: ] + [ password: ] [ password_file: ] # Optional `Authorization` header configuration. @@ -1177,10 +1177,41 @@ authorization: tls_config: [ ] +# Configures Bearer authentication token via string +bearer_token: +# or by passing path to the file with token. +bearer_token_file: + +# Configures OAuth 2.0 authentication +# see https://prometheus.io/docs/prometheus/latest/configuration/configuration/#oauth2 +oauth2: + [ ] + +# Optional list of HTTP headers in form `header-name: value` +# applied for all requests to notifiers +# For example: +# headers: +# - "CustomHeader: foo" +# - "CustomHeader2: bar" +headers: + [ , ...] + # List of labeled statically configured Notifiers. +# +# Each list of targets may be additionally instructed with +# authorization params. Target's authorization params will +# inherit params from global authorization params if there +# are no conflicts. static_configs: - targets: - [ - '' ] + [ - targets: ] + [ - '' ] + [ oauth2 ] + [ basic_auth ] + [ authorization ] + [ tls_config ] + [ bearer_token ] + [ bearer_token_file ] + [ headers ] # List of Consul service discovery configurations. # See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#consul_sd_config diff --git a/app/vmalert/notifier/config.go b/app/vmalert/notifier/config.go index 1fb41ef17..f7b7e02ba 100644 --- a/app/vmalert/notifier/config.go +++ b/app/vmalert/notifier/config.go @@ -68,6 +68,8 @@ type Config struct { // [ - '' ] type StaticConfig struct { Targets []string `yaml:"targets"` + // HTTPClientConfig contains HTTP configuration for the Targets + HTTPClientConfig promauth.HTTPClientConfig `yaml:",inline"` } // UnmarshalYAML implements the yaml.Unmarshaler interface. diff --git a/app/vmalert/notifier/config_watcher.go b/app/vmalert/notifier/config_watcher.go index 297eb06ba..f70fed7c5 100644 --- a/app/vmalert/notifier/config_watcher.go +++ b/app/vmalert/notifier/config_watcher.go @@ -6,6 +6,7 @@ import ( "time" "github.com/VictoriaMetrics/VictoriaMetrics/lib/logger" + "github.com/VictoriaMetrics/VictoriaMetrics/lib/promauth" "github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discovery/consul" "github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discovery/dns" ) @@ -161,12 +162,13 @@ func (cw *configWatcher) start() error { if len(cw.cfg.StaticConfigs) > 0 { var targets []Target for _, cfg := range cw.cfg.StaticConfigs { + httpCfg := mergeHTTPClientConfigs(cw.cfg.HTTPClientConfig, cfg.HTTPClientConfig) for _, target := range cfg.Targets { address, labels, err := parseLabels(target, nil, cw.cfg) if err != nil { return fmt.Errorf("failed to parse labels for target %q: %s", target, err) } - notifier, err := NewAlertManager(address, cw.genFn, cw.cfg.HTTPClientConfig, cw.cfg.parsedAlertRelabelConfigs, cw.cfg.Timeout.Duration()) + notifier, err := NewAlertManager(address, cw.genFn, httpCfg, cw.cfg.parsedAlertRelabelConfigs, cw.cfg.Timeout.Duration()) if err != nil { return fmt.Errorf("failed to init alertmanager for addr %q: %s", address, err) } @@ -252,3 +254,30 @@ func (cw *configWatcher) setTargets(key TargetType, targets []Target) { cw.targets[key] = targets cw.targetsMu.Unlock() } + +// mergeHTTPClientConfigs merges fields between child and parent params +// by populating child from parent params if they're missing. +func mergeHTTPClientConfigs(parent, child promauth.HTTPClientConfig) promauth.HTTPClientConfig { + if child.Authorization == nil { + child.Authorization = parent.Authorization + } + if child.BasicAuth == nil { + child.BasicAuth = parent.BasicAuth + } + if child.BearerToken == nil { + child.BearerToken = parent.BearerToken + } + if child.BearerTokenFile == "" { + child.BearerTokenFile = parent.BearerTokenFile + } + if child.OAuth2 == nil { + child.OAuth2 = parent.OAuth2 + } + if child.TLSConfig == nil { + child.TLSConfig = parent.TLSConfig + } + if child.Headers == nil { + child.Headers = parent.Headers + } + return child +} diff --git a/app/vmalert/notifier/config_watcher_test.go b/app/vmalert/notifier/config_watcher_test.go index 8b70df842..61550a626 100644 --- a/app/vmalert/notifier/config_watcher_test.go +++ b/app/vmalert/notifier/config_watcher_test.go @@ -8,6 +8,8 @@ import ( "os" "sync" "testing" + + "github.com/VictoriaMetrics/VictoriaMetrics/lib/promauth" ) func TestConfigWatcherReload(t *testing.T) { @@ -298,3 +300,20 @@ func newFakeConsulServer() *httptest.Server { return httptest.NewServer(mux) } + +func TestMergeHTTPClientConfigs(t *testing.T) { + cfg1 := promauth.HTTPClientConfig{Headers: []string{"Header:Foo"}} + cfg2 := promauth.HTTPClientConfig{BasicAuth: &promauth.BasicAuthConfig{ + Username: "foo", + Password: promauth.NewSecret("bar"), + }} + + result := mergeHTTPClientConfigs(cfg1, cfg2) + + if result.Headers == nil { + t.Fatalf("expected Headers to be inherited") + } + if result.BasicAuth == nil { + t.Fatalf("expected BasicAuth tp be present") + } +} diff --git a/app/vmalert/notifier/testdata/static.good.yaml b/app/vmalert/notifier/testdata/static.good.yaml index 99cb98eb2..1d95d252d 100644 --- a/app/vmalert/notifier/testdata/static.good.yaml +++ b/app/vmalert/notifier/testdata/static.good.yaml @@ -1,7 +1,21 @@ +headers: + - 'CustomHeader: foo' + static_configs: - targets: - localhost:9093 - localhost:9095 + basic_auth: + username: foo + password: bar + + - targets: + - localhost:9096 + - localhost:9097 + basic_auth: + username: foo + password: baz + alert_relabel_configs: - target_label: "foo" - replacement: "aaa" \ No newline at end of file + replacement: "aaa" diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index f9080cee1..b645e8478 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -32,6 +32,7 @@ The following tip changes can be tested by building VictoriaMetrics components f * FEATURE: [vmalert](https://docs.victoriametrics.com/vmalert.html): add `debug` mode to the alerting rule settings for printing additional information into logs during evaluation. See `debug` param in [alerting rule config](https://docs.victoriametrics.com/vmalert.html#alerting-rules). * FEATURE: [vmalert](https://docs.victoriametrics.com/vmalert.html): add experimental feature for displaying last 10 states of the rule (recording or alerting) evaluation. The state is available on the Rule page, which can be opened by clicking on `Details` link next to Rule's name on the `/groups` page. * FEATURE: [vmalert](https://docs.victoriametrics.com/vmalert.html): allow using extra labels in annotiations. See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3013). +* FEATURE: [vmalert](https://docs.victoriametrics.com/vmalert.html): allow configuring authorization params per list of targets in vmalert's notifier config for `static_configs`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2690). * FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent.html): minimize the time needed for reading large responses from scrape targets in [stream parsing mode](https://docs.victoriametrics.com/vmagent.html#stream-parsing-mode). This should reduce scrape durations for such targets as [kube-state-metrics](https://github.com/kubernetes/kube-state-metrics) running in a big Kubernetes cluster. * FEATURE: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): add [sort_by_label_numeric](https://docs.victoriametrics.com/MetricsQL.html#sort_by_label_numeric) and [sort_by_label_numeric_desc](https://docs.victoriametrics.com/MetricsQL.html#sort_by_label_numeric_desc) functions for [numeric sort](https://www.gnu.org/software/coreutils/manual/html_node/Version-sort-is-not-the-same-as-numeric-sort.html) of input time series by the specified labels. See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2938). * FEATURE: [vmbackup](https://docs.victoriametrics.com/vmbackup.html) and [vmrestore](https://docs.victoriametrics.com/vmrestore.html): retry GCS operations for up to 3 minutes on temporary failures. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3147). diff --git a/docs/vmalert.md b/docs/vmalert.md index 4ee7fd44d..528728524 100644 --- a/docs/vmalert.md +++ b/docs/vmalert.md @@ -1162,7 +1162,7 @@ is the following: # password and password_file are mutually exclusive. basic_auth: [ username: ] - [ password: ] + [ password: ] [ password_file: ] # Optional `Authorization` header configuration. @@ -1181,10 +1181,41 @@ authorization: tls_config: [ ] +# Configures Bearer authentication token via string +bearer_token: +# or by passing path to the file with token. +bearer_token_file: + +# Configures OAuth 2.0 authentication +# see https://prometheus.io/docs/prometheus/latest/configuration/configuration/#oauth2 +oauth2: + [ ] + +# Optional list of HTTP headers in form `header-name: value` +# applied for all requests to notifiers +# For example: +# headers: +# - "CustomHeader: foo" +# - "CustomHeader2: bar" +headers: + [ , ...] + # List of labeled statically configured Notifiers. +# +# Each list of targets may be additionally instructed with +# authorization params. Target's authorization params will +# inherit params from global authorization params if there +# are no conflicts. static_configs: - targets: - [ - '' ] + [ - targets: ] + [ - '' ] + [ oauth2 ] + [ basic_auth ] + [ authorization ] + [ tls_config ] + [ bearer_token ] + [ bearer_token_file ] + [ headers ] # List of Consul service discovery configurations. # See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#consul_sd_config