Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ruler: Support OAuth2 and proxies in Alertmanager client #9945

Merged
merged 13 commits into from
Nov 26, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
* [ENHANCEMENT] Distributor: Initialize ha_tracker cache before ha_tracker and distributor reach running state and begin serving writes. #9826 #9976
* [ENHANCEMENT] Ingester: `-ingest-storage.kafka.max-buffered-bytes` to limit the memory for buffered records when using concurrent fetching. #9892
* [ENHANCEMENT] Querier: improve performance and memory consumption of queries that select many series. #9914
* [ENHANCEMENT] Ruler: Support OAuth2 and proxies in Alertmanager client #9945
* [BUGFIX] Fix issue where functions such as `rate()` over native histograms could return incorrect values if a float stale marker was present in the selected range. #9508
* [BUGFIX] Fix issue where negation of native histograms (eg. `-some_native_histogram_series`) did nothing. #9508
* [BUGFIX] Fix issue where `metric might not be a counter, name does not end in _total/_sum/_count/_bucket` annotation would be emitted even if `rate` or `increase` did not have enough samples to compute a result. #9508
Expand Down
61 changes: 61 additions & 0 deletions cmd/mimir/config-descriptor.json
Original file line number Diff line number Diff line change
Expand Up @@ -12347,6 +12347,67 @@
"fieldDefaultValue": "",
"fieldFlag": "ruler.alertmanager-client.basic-auth-password",
"fieldType": "string"
},
{
"kind": "block",
"name": "oauth2",
"required": false,
"desc": "",
"blockEntries": [
{
"kind": "field",
"name": "client_id",
"required": false,
"desc": "OAuth2 client ID. Enables the use of OAuth2 for authenticating with Alertmanager.",
"fieldValue": null,
"fieldDefaultValue": "",
"fieldFlag": "ruler.alertmanager-client.oauth.client_id",
"fieldType": "string"
},
{
"kind": "field",
"name": "client_secret",
"required": false,
"desc": "OAuth2 client secret.",
"fieldValue": null,
"fieldDefaultValue": "",
"fieldFlag": "ruler.alertmanager-client.oauth.client_secret",
"fieldType": "string"
},
{
"kind": "field",
"name": "token_url",
"required": false,
"desc": "Endpoint used to fetch access token.",
"fieldValue": null,
"fieldDefaultValue": "",
"fieldFlag": "ruler.alertmanager-client.oauth.token_url",
"fieldType": "string"
},
{
"kind": "field",
"name": "scopes",
"required": false,
"desc": "Optional scopes to include with the token request.",
"fieldValue": null,
"fieldDefaultValue": "",
"fieldFlag": "ruler.alertmanager-client.oauth.scopes",
"fieldType": "string"
}
],
"fieldValue": null,
"fieldDefaultValue": null
},
{
"kind": "field",
"name": "proxy_url",
"required": false,
"desc": "Optional HTTP, HTTPS via CONNECT, or SOCKS5 proxy URL to route requests through. Applies to all requests, including auxiliary traffic, such as OAuth token requests.",
"fieldValue": null,
"fieldDefaultValue": "",
"fieldFlag": "ruler.alertmanager-client.proxy-url",
"fieldType": "string",
"fieldCategory": "advanced"
}
],
"fieldValue": null,
Expand Down
10 changes: 10 additions & 0 deletions cmd/mimir/help-all.txt.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -2821,6 +2821,16 @@ Usage of ./cmd/mimir/mimir:
HTTP Basic authentication password. It overrides the password set in the URL (if any).
-ruler.alertmanager-client.basic-auth-username string
HTTP Basic authentication username. It overrides the username set in the URL (if any).
-ruler.alertmanager-client.oauth.client_id string
OAuth2 client ID. Enables the use of OAuth2 for authenticating with Alertmanager.
-ruler.alertmanager-client.oauth.client_secret string
OAuth2 client secret.
-ruler.alertmanager-client.oauth.scopes comma-separated-list-of-strings
Optional scopes to include with the token request.
-ruler.alertmanager-client.oauth.token_url string
Endpoint used to fetch access token.
-ruler.alertmanager-client.proxy-url string
Optional HTTP, HTTPS via CONNECT, or SOCKS5 proxy URL to route requests through. Applies to all requests, including auxiliary traffic, such as OAuth token requests.
-ruler.alertmanager-client.tls-ca-path string
Path to the CA certificates to validate server certificate against. If not set, the host's root CA certificates are used.
-ruler.alertmanager-client.tls-cert-path string
Expand Down
8 changes: 8 additions & 0 deletions cmd/mimir/help.txt.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,14 @@ Usage of ./cmd/mimir/mimir:
HTTP Basic authentication password. It overrides the password set in the URL (if any).
-ruler.alertmanager-client.basic-auth-username string
HTTP Basic authentication username. It overrides the username set in the URL (if any).
-ruler.alertmanager-client.oauth.client_id string
OAuth2 client ID. Enables the use of OAuth2 for authenticating with Alertmanager.
-ruler.alertmanager-client.oauth.client_secret string
OAuth2 client secret.
-ruler.alertmanager-client.oauth.scopes comma-separated-list-of-strings
Optional scopes to include with the token request.
-ruler.alertmanager-client.oauth.token_url string
Endpoint used to fetch access token.
-ruler.alertmanager-url string
Comma-separated list of URL(s) of the Alertmanager(s) to send notifications to. Each URL is treated as a separate group. Multiple Alertmanagers in HA per group can be supported by using DNS service discovery format, comprehensive of the scheme. Basic auth is supported as part of the URL.
-ruler.enable-api
Expand Down
24 changes: 24 additions & 0 deletions docs/sources/mimir/configure/configuration-parameters/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1951,6 +1951,30 @@ alertmanager_client:
# CLI flag: -ruler.alertmanager-client.basic-auth-password
[basic_auth_password: <string> | default = ""]

oauth2:
# OAuth2 client ID. Enables the use of OAuth2 for authenticating with
# Alertmanager.
# CLI flag: -ruler.alertmanager-client.oauth.client_id
[client_id: <string> | default = ""]

# OAuth2 client secret.
# CLI flag: -ruler.alertmanager-client.oauth.client_secret
[client_secret: <string> | default = ""]

# Endpoint used to fetch access token.
# CLI flag: -ruler.alertmanager-client.oauth.token_url
[token_url: <string> | default = ""]

# Optional scopes to include with the token request.
# CLI flag: -ruler.alertmanager-client.oauth.scopes
[scopes: <string> | default = ""]

# (advanced) Optional HTTP, HTTPS via CONNECT, or SOCKS5 proxy URL to route
# requests through. Applies to all requests, including auxiliary traffic, such
# as OAuth token requests.
# CLI flag: -ruler.alertmanager-client.proxy-url
[proxy_url: <string> | default = ""]

# (advanced) Max time to tolerate outage for restoring "for" state of alert.
# CLI flag: -ruler.for-outage-tolerance
[for_outage_tolerance: <duration> | default = 1h]
Expand Down
59 changes: 58 additions & 1 deletion pkg/ruler/notifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/grafana/dskit/cache"
"github.com/grafana/dskit/cancellation"
"github.com/grafana/dskit/crypto/tls"
"github.com/grafana/dskit/flagext"
config_util "github.com/prometheus/common/config"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/config"
Expand All @@ -27,18 +28,43 @@ import (
"github.com/grafana/mimir/pkg/util"
)

var errRulerNotifierStopped = cancellation.NewErrorf("rulerNotifier stopped")
var (
errRulerNotifierStopped = cancellation.NewErrorf("rulerNotifier stopped")
errRulerSimultaneousBasicAuthAndOAuth = errors.New("cannot use both Basic Auth and OAuth2 simultaneously")
)

type NotifierConfig struct {
TLSEnabled bool `yaml:"tls_enabled" category:"advanced"`
TLS tls.ClientConfig `yaml:",inline"`
BasicAuth util.BasicAuth `yaml:",inline"`
OAuth2 OAuth2Config `yaml:"oauth2"`
ProxyURL string `yaml:"proxy_url" category:"advanced"`
}

func (cfg *NotifierConfig) RegisterFlags(f *flag.FlagSet) {
f.BoolVar(&cfg.TLSEnabled, "ruler.alertmanager-client.tls-enabled", true, "Enable TLS for gRPC client connecting to alertmanager.")
cfg.TLS.RegisterFlagsWithPrefix("ruler.alertmanager-client", f)
cfg.BasicAuth.RegisterFlagsWithPrefix("ruler.alertmanager-client.", f)
cfg.OAuth2.RegisterFlagsWithPrefix("ruler.alertmanager-client.oauth.", f)
f.StringVar(&cfg.ProxyURL, "ruler.alertmanager-client.proxy-url", "", "Optional HTTP, HTTPS via CONNECT, or SOCKS5 proxy URL to route requests through. Applies to all requests, including auxiliary traffic, such as OAuth token requests.")
}

type OAuth2Config struct {
ClientID string `yaml:"client_id"`
ClientSecret flagext.Secret `yaml:"client_secret"`
TokenURL string `yaml:"token_url"`
Scopes flagext.StringSliceCSV `yaml:"scopes,omitempty"`
}

func (cfg *OAuth2Config) RegisterFlagsWithPrefix(prefix string, f *flag.FlagSet) {
f.StringVar(&cfg.ClientID, prefix+"client_id", "", "OAuth2 client ID. Enables the use of OAuth2 for authenticating with Alertmanager.")
f.Var(&cfg.ClientSecret, prefix+"client_secret", "OAuth2 client secret.")
f.StringVar(&cfg.TokenURL, prefix+"token_url", "", "Endpoint used to fetch access token.")
f.Var(&cfg.Scopes, prefix+"scopes", "Optional scopes to include with the token request.")
}

func (cfg *OAuth2Config) IsEnabled() bool {
return cfg.ClientID != "" || cfg.TokenURL != ""
}

// rulerNotifier bundles a notifier.Manager together with an associated
Expand Down Expand Up @@ -176,6 +202,37 @@ func amConfigWithSD(rulerConfig *Config, url *url.URL, sdConfig discovery.Config
}
}

// Whether to use an optional HTTP, HTTP+CONNECT, or SOCKS5 proxy.
if rulerConfig.Notifier.ProxyURL != "" {
url, err := url.Parse(rulerConfig.Notifier.ProxyURL)
if err != nil {
return nil, err
}
amConfig.HTTPClientConfig.ProxyURL = config_util.URL{URL: url}
}

// Whether to use OAuth2 or not.
if rulerConfig.Notifier.OAuth2.IsEnabled() {
if amConfig.HTTPClientConfig.BasicAuth != nil {
return nil, errRulerSimultaneousBasicAuthAndOAuth
}

amConfig.HTTPClientConfig.OAuth2 = &config_util.OAuth2{
ClientID: rulerConfig.Notifier.OAuth2.ClientID,
ClientSecret: config_util.Secret(rulerConfig.Notifier.OAuth2.ClientSecret.String()),
TokenURL: rulerConfig.Notifier.OAuth2.TokenURL,
Scopes: rulerConfig.Notifier.OAuth2.Scopes,
}

if rulerConfig.Notifier.ProxyURL != "" {
url, err := url.Parse(rulerConfig.Notifier.ProxyURL)
if err != nil {
return nil, err
}
amConfig.HTTPClientConfig.OAuth2.ProxyURL = config_util.URL{URL: url}
}
}

// Whether to use TLS or not.
if rulerConfig.Notifier.TLSEnabled {
if rulerConfig.Notifier.TLS.Reader == nil {
Expand Down
Loading
Loading