From 07ed958b82011fddfe3208b0058596b572b918c3 Mon Sep 17 00:00:00 2001 From: Aliaksandr Valialkin Date: Wed, 17 Apr 2024 17:12:17 +0200 Subject: [PATCH] app/vmauth: add support for client TLS sertificates for backend requests over https While at it, also add support for TLS ServerName for backend requests over https --- app/vmauth/auth_config.go | 9 ++++++--- app/vmauth/main.go | 33 +++++++++++++++++++++++++++------ docs/CHANGELOG.md | 1 + docs/vmauth.md | 26 +++++++++++++++++++++++++- 4 files changed, 59 insertions(+), 10 deletions(-) diff --git a/app/vmauth/auth_config.go b/app/vmauth/auth_config.go index 53b47b42b..ce20beb85 100644 --- a/app/vmauth/auth_config.go +++ b/app/vmauth/auth_config.go @@ -73,8 +73,11 @@ type UserInfo struct { RetryStatusCodes []int `yaml:"retry_status_codes,omitempty"` LoadBalancingPolicy string `yaml:"load_balancing_policy,omitempty"` DropSrcPathPrefixParts *int `yaml:"drop_src_path_prefix_parts,omitempty"` - TLSInsecureSkipVerify *bool `yaml:"tls_insecure_skip_verify,omitempty"` TLSCAFile string `yaml:"tls_ca_file,omitempty"` + TLSCertFile string `yaml:"tls_cert_file,omitempty"` + TLSKeyFile string `yaml:"tls_key_file,omitempty"` + TLSServerName string `yaml:"tls_server_name,omitempty"` + TLSInsecureSkipVerify *bool `yaml:"tls_insecure_skip_verify,omitempty"` MetricLabels map[string]string `yaml:"metric_labels,omitempty"` @@ -729,7 +732,7 @@ func parseAuthConfig(data []byte) (*AuthConfig, error) { return float64(len(ui.concurrencyLimitCh)) }) - rt, err := newRoundTripper(ui.TLSInsecureSkipVerify, ui.TLSCAFile) + rt, err := newRoundTripper(ui.TLSCAFile, ui.TLSCertFile, ui.TLSKeyFile, ui.TLSServerName, ui.TLSInsecureSkipVerify) if err != nil { return nil, fmt.Errorf("cannot initialize HTTP RoundTripper: %w", err) } @@ -777,7 +780,7 @@ func parseAuthConfigUsers(ac *AuthConfig) (map[string]*UserInfo, error) { return float64(len(ui.concurrencyLimitCh)) }) - rt, err := newRoundTripper(ui.TLSInsecureSkipVerify, ui.TLSCAFile) + rt, err := newRoundTripper(ui.TLSCAFile, ui.TLSCertFile, ui.TLSKeyFile, ui.TLSServerName, ui.TLSInsecureSkipVerify) if err != nil { return nil, fmt.Errorf("cannot initialize HTTP RoundTripper: %w", err) } diff --git a/app/vmauth/main.go b/app/vmauth/main.go index 0743dc079..bf8e18b68 100644 --- a/app/vmauth/main.go +++ b/app/vmauth/main.go @@ -53,6 +53,12 @@ var ( "See https://docs.victoriametrics.com/vmauth.html#backend-tls-setup") backendTLSCAFile = flag.String("backend.TLSCAFile", "", "Optional path to TLS root CA file, which is used for TLS verification when connecting to backends over HTTPS. "+ "See https://docs.victoriametrics.com/vmauth.html#backend-tls-setup") + backendTLSCertFile = flag.String("backend.TLSCertFile", "", "Optional path to TLS client certificate file, which must be sent to HTTPS backend. "+ + "See https://docs.victoriametrics.com/vmauth.html#backend-tls-setup") + backendTLSKeyFile = flag.String("backend.TLSKeyFile", "", "Optional path to TLS client key file, which must be sent to HTTPS backend. "+ + "See https://docs.victoriametrics.com/vmauth.html#backend-tls-setup") + backendTLSServerName = flag.String("backend.TLSServerName", "", "Optional TLS ServerName, which must be sent to HTTPS backend. "+ + "See https://docs.victoriametrics.com/vmauth.html#backend-tls-setup") ) func main() { @@ -389,19 +395,34 @@ var ( missingRouteRequests = metrics.NewCounter(`vmauth_http_request_errors_total{reason="missing_route"}`) ) -func newRoundTripper(insecureSkipVerifyP *bool, caFileP string) (http.RoundTripper, error) { +func newRoundTripper(caFileOpt, certFileOpt, keyFileOpt, serverNameOpt string, insecureSkipVerifyP *bool) (http.RoundTripper, error) { + caFile := *backendTLSCAFile + if caFileOpt != "" { + caFile = caFileOpt + } + certFile := *backendTLSCertFile + if certFileOpt != "" { + certFile = certFileOpt + } + keyFile := *backendTLSKeyFile + if keyFileOpt != "" { + keyFile = keyFileOpt + } + serverName := *backendTLSServerName + if serverNameOpt != "" { + serverName = serverNameOpt + } insecureSkipVerify := *backendTLSInsecureSkipVerify if p := insecureSkipVerifyP; p != nil { insecureSkipVerify = *p } - caFile := *backendTLSCAFile - if caFileP != "" { - caFile = caFileP - } opts := &promauth.Options{ TLSConfig: &promauth.TLSConfig{ - InsecureSkipVerify: insecureSkipVerify, CAFile: caFile, + CertFile: certFile, + KeyFile: keyFile, + ServerName: serverName, + InsecureSkipVerify: insecureSkipVerify, }, } cfg, err := opts.NewConfig() diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index d09ef6583..a40bd5a4d 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -32,6 +32,7 @@ See also [LTS releases](https://docs.victoriametrics.com/lts-releases/). * FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): in the Select component, user-entered values are now preserved on blur if they match options in the list. * FEATURE: [vmauth](https://docs.victoriametrics.com/vmauth/): support regex matching when routing incoming requests based on HTTP [query args](https://en.wikipedia.org/wiki/Query_string) via `src_query_args` option at `url_map`. See [these docs](https://docs.victoriametrics.com/vmauth/#generic-http-proxy-for-different-backends) and [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6070). +* FEATURE: [vmauth](https://docs.victoriametrics.com/vmauth/): support specifying client TLS certificates and TLS ServerName for requests to HTTPS backends. See [these docs](https://docs.victoriametrics.com/vmauth/#backend-tls-setup). * BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert.html): supported any status codes from the range 200-299 from alertmanager. Previously, only 200 status code considered a successful action. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6110). * BUGFIX: [vmauth](https://docs.victoriametrics.com/vmauth/): don't treat concurrency limit hit as an error of the backend. Previously, hitting the concurrency limit would increment both `vmauth_concurrent_requests_limit_reached_total` and `vmauth_user_request_backend_errors_total` counters. Now, only concurrency limit counter is incremented. Updates [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5565). diff --git a/docs/vmauth.md b/docs/vmauth.md index 4925acfea..e3ae21972 100644 --- a/docs/vmauth.md +++ b/docs/vmauth.md @@ -691,7 +691,6 @@ in the [`-auth.config`](#auth-config). These settings can be overridden with the ``` - `-backend.tlsCAFile` allows specifying the path to TLS Root CA, which will be used for TLS verification when connecting to HTTPS backends. - The `-backend.tlsCAFile` may point either to local file or to `http` / `https` url. This global setting can be overridden at per-user level inside [`-auth.config`](#auth-config) via `tls_ca_file` option. For example: @@ -701,6 +700,31 @@ in the [`-auth.config`](#auth-config). These settings can be overridden with the tls_ca_file: "/path/to/tls/root/ca" ``` +- `-backend.tlsCertFile` and `-backend.tlsKeyFile` allows specifying client TLS certificate, which will be passed in requests to HTTPS backends. + This global setting can be overridden at per-user level inside [`-auth.config`](#auth-config) + via `tls_cert_file` and `tls_key_file` options. For example: + + ```yaml + - username: "foo" + url_prefix: "https://localhost" + tls_cert_file: "/path/to/tls/cert" + tls_key_file: "/path/to/tls/key" + ``` + +- `-backend.tlsServerName` allows specifying optional TLS ServerName, which will be passed in requests to HTTPS backends. + This global setting can be overridden at per-user level inside [`-auth.config`](#auth-config) + via `tls_server_name` option. For example: + + ```yaml + - username: "foo" + url_prefix: "https://localhost" + tls_server_name: "foo.bar.com" + ``` + +The `-backend.tlsCAFile`, `-backend.tlsCertFile`, `-backend.tlsKeyFile`, `tls_ca_file`, `tls_cert_file` and `tls_key_file` may point either to local file or to `http` / `https` url. +The file is automatically re-read when it is updated. + + ## IP filters [Enterprise version](https://docs.victoriametrics.com/enterprise/) of `vmauth` can be configured to allow / deny incoming requests via global and per-user IP filters.