diff --git a/app/vmagent/remotewrite/client.go b/app/vmagent/remotewrite/client.go index 94e6ad3ffb..af7fe4d39e 100644 --- a/app/vmagent/remotewrite/client.go +++ b/app/vmagent/remotewrite/client.go @@ -58,6 +58,7 @@ var ( oauth2ClientID = flagutil.NewArrayString("remoteWrite.oauth2.clientID", "Optional OAuth2 clientID to use for the corresponding -remoteWrite.url") oauth2ClientSecret = flagutil.NewArrayString("remoteWrite.oauth2.clientSecret", "Optional OAuth2 clientSecret to use for the corresponding -remoteWrite.url") oauth2ClientSecretFile = flagutil.NewArrayString("remoteWrite.oauth2.clientSecretFile", "Optional OAuth2 clientSecretFile to use for the corresponding -remoteWrite.url") + oauth2EndpointParams = flagutil.NewMapString("remoteWrite.oauth2.endpointParams", "Optional OAuth2 endpoint parameters to use for the corresponding -remoteWrite.url") oauth2TokenURL = flagutil.NewArrayString("remoteWrite.oauth2.tokenUrl", "Optional OAuth2 tokenURL to use for the corresponding -remoteWrite.url") oauth2Scopes = flagutil.NewArrayString("remoteWrite.oauth2.scopes", "Optional OAuth2 scopes to use for the corresponding -remoteWrite.url. Scopes must be delimited by ';'") @@ -238,6 +239,7 @@ func getAuthConfig(argIdx int) (*promauth.Config, error) { ClientID: oauth2ClientID.GetOptionalArg(argIdx), ClientSecret: promauth.NewSecret(clientSecret), ClientSecretFile: clientSecretFile, + EndpointParams: *oauth2EndpointParams, TokenURL: oauth2TokenURL.GetOptionalArg(argIdx), Scopes: strings.Split(oauth2Scopes.GetOptionalArg(argIdx), ";"), } diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index bdb5a470cc..ae4d4d6481 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -28,6 +28,7 @@ The sandbox cluster installation is running under the constant load generated by ## tip +* FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent.html): expose ability to set additional endpoint parameters when requesting an OAuth2 token via a the flag `remoteWrite.oauth2.endpointParams`. See [these docs](https://docs.victoriametrics.com/vmagent.html#advanced-usage). * FEATURE: [vmauth](https://docs.victoriametrics.com/vmauth.html): add ability to proxy incoming requests to different backends based on the requested host via `src_hosts` option at `url_map`. See [these docs](https://docs.victoriametrics.com/vmauth.html#generic-http-proxy-for-different-backends). * FEATURE: [vmctl](https://docs.victoriametrics.com/vmctl.html): rename cmd-line flag `vm-native-disable-retries` to `vm-native-disable-per-metric-migration` to better reflect its meaning. * FEATURE: all VictoriaMetrics components: add ability to specify arbitrary HTTP headers to send with every request to `-pushmetrics.url`. See [`push metrics` docs](https://docs.victoriametrics.com/#push-metrics). diff --git a/docs/vmagent.md b/docs/vmagent.md index c28ba2b0b4..d7f3cc5316 100644 --- a/docs/vmagent.md +++ b/docs/vmagent.md @@ -1921,6 +1921,9 @@ See the docs at https://docs.victoriametrics.com/vmagent.html . -remoteWrite.oauth2.clientSecretFile array Optional OAuth2 clientSecretFile to use for the corresponding -remoteWrite.url Supports an array of values separated by comma or specified via multiple flags. + -remoteWrite.oauth2.endpointParams array + Optional OAuth2 endpointParams to use for the corresponding -remoteWrite.url. Keys and values must be seperated by ':'. + Supports and array of key:value pairs seperated by comma or specified via multiple flags. -remoteWrite.oauth2.scopes array Optional OAuth2 scopes to use for the corresponding -remoteWrite.url. Scopes must be delimited by ';' Supports an array of values separated by comma or specified via multiple flags. diff --git a/lib/flagutil/map.go b/lib/flagutil/map.go new file mode 100644 index 0000000000..2ba97f88dc --- /dev/null +++ b/lib/flagutil/map.go @@ -0,0 +1,49 @@ +package flagutil + +import ( + "flag" + "fmt" + "strings" +) + +type MapString map[string]string + +// String returns a string representation of the map. +func (m *MapString) String() string { + if m == nil { + return "" + } + return fmt.Sprintf("%v", *m) +} + +// Set parses the given value into a map. +func (m *MapString) Set(value string) error { + if *m == nil { + *m = make(map[string]string) + } + for _, pair := range parseArrayValues(value) { + key, value, err := parseMapValue(pair) + if err != nil { + return err + } + (*m)[key] = value + } + return nil +} + +func parseMapValue(s string) (string, string, error) { + kv := strings.SplitN(s, ":", 2) + if len(kv) != 2 { + return "", "", fmt.Errorf("invalid map value '%s' values must be 'key:value'", s) + } + + return kv[0], kv[1], nil +} + +// NewMapString returns a new MapString with the given name and description. +func NewMapString(name, description string) *MapString { + description += fmt.Sprintf("\nSupports multiple flags with the following syntax: -%s=key:value", name) + var m MapString + flag.Var(&m, name, description) + return &m +}