diff --git a/app/vmauth/auth_config.go b/app/vmauth/auth_config.go index 43b40bc94e..72a5bd4602 100644 --- a/app/vmauth/auth_config.go +++ b/app/vmauth/auth_config.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "encoding/base64" "flag" "fmt" @@ -290,6 +291,13 @@ func (sp *SrcPath) MarshalYAML() (interface{}, error) { return sp.sOriginal, nil } +var ( + configReloads = metrics.NewCounter(`vmauth_config_last_reload_total`) + configReloadErrors = metrics.NewCounter(`vmauth_config_last_reload_errors_total`) + configSuccess = metrics.NewCounter(`vmauth_config_last_reload_successful`) + configTimestamp = metrics.NewCounter(`vmauth_config_last_reload_success_timestamp_seconds`) +) + func initAuthConfig() { if len(*authConfigPath) == 0 { logger.Fatalf("missing required `-auth.config` command-line flag") @@ -300,11 +308,14 @@ func initAuthConfig() { // See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1240 sighupCh := procutil.NewSighupChan() - err := loadAuthConfig() + _, err := loadAuthConfig() if err != nil { logger.Fatalf("cannot load auth config: %s", err) } + configSuccess.Set(1) + configTimestamp.Set(fasttime.UnixTimestamp()) + stopCh = make(chan struct{}) authConfigWG.Add(1) go func() { @@ -327,52 +338,75 @@ func authConfigReloader(sighupCh <-chan os.Signal) { refreshCh = ticker.C } + updateFn := func() { + configReloads.Inc() + updated, err := loadAuthConfig() + if err != nil { + logger.Errorf("failed to load auth config; using the last successfully loaded config; error: %s", err) + configSuccess.Set(0) + configReloadErrors.Inc() + return + } + configSuccess.Set(1) + if updated { + configTimestamp.Set(fasttime.UnixTimestamp()) + } + } + for { select { case <-stopCh: return case <-refreshCh: - procutil.SelfSIGHUP() + updateFn() case <-sighupCh: logger.Infof("SIGHUP received; loading -auth.config=%q", *authConfigPath) - err := loadAuthConfig() - if err != nil { - logger.Errorf("failed to load auth config; using the last successfully loaded config; error: %s", err) - continue - } + updateFn() } } } +// authConfigData stores the yaml definition for this config. +// authConfigData needs to be updated each time authConfig is updated. +var authConfigData atomic.Pointer[[]byte] + var authConfig atomic.Pointer[AuthConfig] var authUsers atomic.Pointer[map[string]*UserInfo] var authConfigWG sync.WaitGroup var stopCh chan struct{} -func loadAuthConfig() error { - ac, err := readAuthConfig(*authConfigPath) +// loadAuthConfig loads and applies the config from *authConfigPath. +// It returns bool value to identify if new config was applied. +// The config can be not applied if there is a parsing error +// or if there are no changes to the current authConfig. +func loadAuthConfig() (bool, error) { + data, err := fs.ReadFileOrHTTP(*authConfigPath) if err != nil { - return fmt.Errorf("failed to load -auth.config=%q: %s", *authConfigPath, err) + return false, fmt.Errorf("failed to read -auth.config=%q: %s", *authConfigPath, err) + } + + oldData := authConfigData.Load() + if oldData != nil && bytes.Equal(data, *oldData) { + // there are no updates in the config - skip reloading. + return false, nil + } + + ac, err := parseAuthConfig(data) + if err != nil { + return false, fmt.Errorf("failed to parse -auth.config=%q: %s", *authConfigPath, err) } m, err := parseAuthConfigUsers(ac) if err != nil { - return fmt.Errorf("failed to parse users from -auth.config=%q: %s", *authConfigPath, err) + return false, fmt.Errorf("failed to parse users from -auth.config=%q: %s", *authConfigPath, err) } logger.Infof("loaded information about %d users from -auth.config=%q", len(m), *authConfigPath) authConfig.Store(ac) + authConfigData.Store(&data) authUsers.Store(&m) - return nil -} - -func readAuthConfig(path string) (*AuthConfig, error) { - data, err := fs.ReadFileOrHTTP(path) - if err != nil { - return nil, err - } - return parseAuthConfig(data) + return true, nil } func parseAuthConfig(data []byte) (*AuthConfig, error) { diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 2a9802ec37..91e47b9959 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -38,9 +38,10 @@ The following `tip` changes can be tested by building VictoriaMetrics components * FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): improve accessibility score to 100 according to [Google's Lighthouse](https://developer.chrome.com/docs/lighthouse/accessibility/) tests. * FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): organize `min`, `max`, `median` values on the chart legend and tooltips for better visibility. * FEATURE: dashboards: provide copies of Grafana dashboards alternated with VictoriaMetrics datasource at [dashboards/vm](https://github.com/VictoriaMetrics/VictoriaMetrics/tree/master/dashboards/vm). -* FEATURE: [vmauth](https://docs.victoriametrics.com/vmauth.html): added ability to set, override and clear request and response headers on a per-user and per-path basis. See [this i -ssue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4825) and [these docs](https://docs.victoriametrics.com/vmauth.html#auth-config) for details. +* FEATURE: [vmauth](https://docs.victoriametrics.com/vmauth.html): added ability to set, override and clear request and response headers on a per-user and per-path basis. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4825) and [these docs](https://docs.victoriametrics.com/vmauth.html#auth-config) for details. * FEATURE: [vmauth](https://docs.victoriametrics.com/vmauth.html): add ability to retry requests to the [remaining backends](https://docs.victoriametrics.com/vmauth.html#load-balancing) if they return response status codes specified in the `retry_status_codes` list. See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4893). +* FEATURE: [vmauth](https://docs.victoriametrics.com/vmauth.html): expose metrics `vmauth_config_last_reload_*` for tracking the state of config reloads, similarly to vmagent/vmalert components. +* FEATURE: [vmauth](https://docs.victoriametrics.com/vmauth.html): do not print logs like `SIGHUP received...` once per configured `-configCheckInterval` cmd-line flag. This log will be printed only if config reload was invoked manually. * FEATURE: [vmalert](https://docs.victoriametrics.com/vmalert.html): add `eval_offset` attribute for [Groups](https://docs.victoriametrics.com/vmalert.html#groups). If specified, Group will be evaluated at the exact time offset on the range of [0...evaluationInterval]. The setting might be useful for cron-like rules which must be evaluated at specific moments of time. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3409) for details. * FEATURE: [vmalert](https://docs.victoriametrics.com/vmalert.html): validate [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html) function names in alerting and recording rules when `vmalert` runs with `-dryRun` command-line flag. Previously it was allowed to use unknown (aka invalid) MetricsQL function names there. For example, `foo()` was counted as a valid query. See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4933). * FEATURE: limit the length of string params in log messages to 500 chars. Longer string params are replaced with the `first_250_chars..last_250_chars`. This prevents from too long log lines, which can be emitted by VictoriaMetrics components. @@ -60,6 +61,7 @@ The v1.93.x line will be supported for at least 12 months since [v1.93.0](https: * BUGFIX: [Graphite Render API](https://docs.victoriametrics.com/#graphite-render-api-usage): correctly return `null` instead of `Inf` in JSON query responses. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3783). * BUGFIX: [vmbackup](https://docs.victoriametrics.com/vmbackup.html): properly copy `parts.json` files inside `<-storageDataPath>/{data,indexdb}` folders during [incremental backups](https://docs.victoriametrics.com/vmbackup.html#incremental-backups). Previously the new `parts.json` could be skipped during incremental backups, which could lead to inability to restore from the backup. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5005). This issue has been introduced in [v1.90.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.90.0). * BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent.html): properly close connections to Kubernetes API server after the change in `selectors` or `namespaces` sections of [kubernetes_sd_configs](https://docs.victoriametrics.com/sd_configs.html#kubernetes_sd_configs). Previously `vmagent` could continue polling Kubernetes API server with the old `selectors` or `namespaces` configs additionally to polling new configs. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4850). +* BUGFIX: [vmauth](https://docs.victoriametrics.com/vmauth.html): prevent configuration reloading if there were no changes in config. This improves memory usage when `-configCheckInterval` cmd-line flag is configured and config has extensive list of regexp expressions requiring additional memory on parsing. ## [v1.93.4](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.93.4)