vmauth: support for reading remote auth config file (#1898)

* add support for reading remote auth_config file via http

* fix lint

* fix defer on close body

Co-authored-by: Tiago Magalhães <tmagalhaes@wavecom.pt>
This commit is contained in:
Tiago Magalhães 2021-12-02 21:19:05 +00:00 committed by Aliaksandr Valialkin
parent 0f9aaf9cec
commit fd3c9730b0
No known key found for this signature in database
GPG key ID: A72BEC6CD3D0DED1
3 changed files with 38 additions and 10 deletions

View file

@ -4,7 +4,6 @@
It reads auth credentials from `Authorization` http header ([Basic Auth](https://en.wikipedia.org/wiki/Basic_access_authentication) and `Bearer token` is supported), It reads auth credentials from `Authorization` http header ([Basic Auth](https://en.wikipedia.org/wiki/Basic_access_authentication) and `Bearer token` is supported),
matches them against configs pointed by [-auth.config](#auth-config) command-line flag and proxies incoming HTTP requests to the configured per-user `url_prefix` on successful match. matches them against configs pointed by [-auth.config](#auth-config) command-line flag and proxies incoming HTTP requests to the configured per-user `url_prefix` on successful match.
## Quick start ## Quick start
Just download `vmutils-*` archive from [releases page](https://github.com/VictoriaMetrics/VictoriaMetrics/releases), unpack it Just download `vmutils-*` archive from [releases page](https://github.com/VictoriaMetrics/VictoriaMetrics/releases), unpack it
@ -26,12 +25,10 @@ Pass `-help` to `vmauth` in order to see all the supported command-line flags wi
Feel free [contacting us](mailto:info@victoriametrics.com) if you need customized auth proxy for VictoriaMetrics with the support of LDAP, SSO, RBAC, SAML, Feel free [contacting us](mailto:info@victoriametrics.com) if you need customized auth proxy for VictoriaMetrics with the support of LDAP, SSO, RBAC, SAML,
accounting and rate limiting such as [vmgateway](https://docs.victoriametrics.com/vmgateway.html). accounting and rate limiting such as [vmgateway](https://docs.victoriametrics.com/vmgateway.html).
## Load balancing ## Load balancing
Each `url_prefix` in the [-auth.config](#auth-config) may contain either a single url or a list of urls. In the latter case `vmauth` balances load among the configured urls in a round-robin manner. This feature is useful for balancing the load among multiple `vmselect` and/or `vminsert` nodes in [VictoriaMetrics cluster](https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html). Each `url_prefix` in the [-auth.config](#auth-config) may contain either a single url or a list of urls. In the latter case `vmauth` balances load among the configured urls in a round-robin manner. This feature is useful for balancing the load among multiple `vmselect` and/or `vminsert` nodes in [VictoriaMetrics cluster](https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html).
## Auth config ## Auth config
`-auth.config` is represented in the following simple `yml` format: `-auth.config` is represented in the following simple `yml` format:
@ -124,7 +121,6 @@ users:
The config may contain `%{ENV_VAR}` placeholders, which are substituted by the corresponding `ENV_VAR` environment variable values. The config may contain `%{ENV_VAR}` placeholders, which are substituted by the corresponding `ENV_VAR` environment variable values.
This may be useful for passing secrets to the config. This may be useful for passing secrets to the config.
## Security ## Security
Do not transfer Basic Auth headers in plaintext over untrusted networks. Enable https. This can be done by passing the following `-tls*` command-line flags to `vmauth`: Do not transfer Basic Auth headers in plaintext over untrusted networks. Enable https. This can be done by passing the following `-tls*` command-line flags to `vmauth`:
@ -142,7 +138,6 @@ Alternatively, [https termination proxy](https://en.wikipedia.org/wiki/TLS_termi
It is recommended protecting `/-/reload` endpoint with `-reloadAuthKey` command-line flag, so external users couldn't trigger config reload. It is recommended protecting `/-/reload` endpoint with `-reloadAuthKey` command-line flag, so external users couldn't trigger config reload.
## Monitoring ## Monitoring
`vmauth` exports various metrics in Prometheus exposition format at `http://vmauth-host:8427/metrics` page. It is recommended setting up regular scraping of this page `vmauth` exports various metrics in Prometheus exposition format at `http://vmauth-host:8427/metrics` page. It is recommended setting up regular scraping of this page
@ -161,7 +156,6 @@ users:
It is recommended using [binary releases](https://github.com/VictoriaMetrics/VictoriaMetrics/releases) - `vmauth` is located in `vmutils-*` archives there. It is recommended using [binary releases](https://github.com/VictoriaMetrics/VictoriaMetrics/releases) - `vmauth` is located in `vmutils-*` archives there.
### Development build ### Development build
1. [Install Go](https://golang.org/doc/install). The minimum supported version is Go 1.16. 1. [Install Go](https://golang.org/doc/install). The minimum supported version is Go 1.16.
@ -187,7 +181,6 @@ by setting it via `<ROOT_IMAGE>` environment variable. For example, the followin
ROOT_IMAGE=scratch make package-vmauth ROOT_IMAGE=scratch make package-vmauth
``` ```
## Profiling ## Profiling
`vmauth` provides handlers for collecting the following [Go profiles](https://blog.golang.org/profiling-go-programs): `vmauth` provides handlers for collecting the following [Go profiles](https://blog.golang.org/profiling-go-programs):
@ -208,7 +201,6 @@ The command for collecting CPU profile waits for 30 seconds before returning.
The collected profiles may be analyzed with [go tool pprof](https://github.com/google/pprof). The collected profiles may be analyzed with [go tool pprof](https://github.com/google/pprof).
## Advanced usage ## Advanced usage
Pass `-help` command-line arg to `vmauth` in order to see all the configuration options: Pass `-help` command-line arg to `vmauth` in order to see all the configuration options:
@ -221,7 +213,7 @@ vmauth authenticates and authorizes incoming requests and proxies them to Victor
See the docs at https://docs.victoriametrics.com/vmauth.html . See the docs at https://docs.victoriametrics.com/vmauth.html .
-auth.config string -auth.config string
Path to auth config. See https://docs.victoriametrics.com/vmauth.html for details on the format of this auth config Http URL or File Path to auth config. See https://docs.victoriametrics.com/vmauth.html for details on the format of this auth config
-enableTCP6 -enableTCP6
Whether to enable IPv6 for listening and dialing. By default only IPv4 TCP and UDP is used Whether to enable IPv6 for listening and dialing. By default only IPv4 TCP and UDP is used
-envflag.enable -envflag.enable

View file

@ -5,6 +5,7 @@ import (
"flag" "flag"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http"
"net/url" "net/url"
"os" "os"
"regexp" "regexp"
@ -237,7 +238,19 @@ var authConfigWG sync.WaitGroup
var stopCh chan struct{} var stopCh chan struct{}
func readAuthConfig(path string) (map[string]*UserInfo, error) { func readAuthConfig(path string) (map[string]*UserInfo, error) {
data, err := ioutil.ReadFile(path) var data []byte
var err error
// reads remote file via http, if url is given
if isHTTPURL(path) {
httpPath, err := http.Get(path)
if err != nil {
return nil, fmt.Errorf("cannot read %q: %w", path, err)
}
defer func() { _ = httpPath.Body.Close() }()
data, err = ioutil.ReadAll(httpPath.Body)
} else {
data, err = ioutil.ReadFile(path)
}
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot read %q: %w", path, err) return nil, fmt.Errorf("cannot read %q: %w", path, err)
} }
@ -372,3 +385,10 @@ func sanitizeURLPrefix(urlPrefix *url.URL) (*url.URL, error) {
} }
return urlPrefix, nil return urlPrefix, nil
} }
// isHTTPURL checks if a given targetURL is valid and contains a valid http scheme
func isHTTPURL(targetURL string) bool {
parsed, err := url.Parse(targetURL)
return err == nil && (parsed.Scheme == "http" || parsed.Scheme == "https") && parsed.Host != ""
}

View file

@ -368,3 +368,19 @@ func mustParseURLs(us []string) *URLPrefix {
urls: pus, urls: pus,
} }
} }
func TestIsHTTPURLSuccess(t *testing.T) {
assert := func(s string, expected bool) {
t.Helper()
res := isHTTPURL(s)
if res != expected {
t.Fatalf("expecting %t, got %t", expected, res)
}
}
assert("http://isvalid:8000/filepath", true) // test http
assert("https://isvalid:8000/filepath", true) // test https
assert("tcp://notvalid:8000/filepath", false) // test tcp
assert("0/filepath", false) // something invalid
assert("filepath.extension", false) // something invalid
}