From fa184a5fc3bd83abe37854983e0f548ceaabb4e0 Mon Sep 17 00:00:00 2001 From: Levi Harrison Date: Wed, 28 Apr 2021 08:47:52 -0400 Subject: [PATCH] Add OAuth 2.0 Config (#8761) * Introduced oauth2 config into the codebase Signed-off-by: Levi Harrison --- config/config.go | 6 +-- config/config_test.go | 21 +++++--- config/testdata/conf.good.yml | 5 ++ docs/configuration/configuration.md | 83 ++++++++++++++++++++++++++++- go.mod | 2 +- go.sum | 4 +- 6 files changed, 107 insertions(+), 14 deletions(-) diff --git a/config/config.go b/config/config.go index 02d9f763d..56350e1be 100644 --- a/config/config.go +++ b/config/config.go @@ -663,10 +663,10 @@ func (c *RemoteWriteConfig) UnmarshalYAML(unmarshal func(interface{}) error) err } httpClientConfigAuthEnabled := c.HTTPClientConfig.BasicAuth != nil || - c.HTTPClientConfig.Authorization != nil + c.HTTPClientConfig.Authorization != nil || c.HTTPClientConfig.OAuth2 != nil if httpClientConfigAuthEnabled && c.SigV4Config != nil { - return fmt.Errorf("at most one of basic_auth, authorization, & sigv4 must be configured") + return fmt.Errorf("at most one of basic_auth, authorization, oauth2, & sigv4 must be configured") } return nil @@ -675,7 +675,7 @@ func (c *RemoteWriteConfig) UnmarshalYAML(unmarshal func(interface{}) error) err func validateHeaders(headers map[string]string) error { for header := range headers { if strings.ToLower(header) == "authorization" { - return errors.New("authorization header must be changed via the basic_auth or authorization parameter") + return errors.New("authorization header must be changed via the basic_auth, authorization, oauth2, or sigv4 parameter") } if _, ok := reservedHeaders[strings.ToLower(header)]; ok { return errors.Errorf("%s is a reserved header. It must not be changed", header) diff --git a/config/config_test.go b/config/config_test.go index de6ad8526..85e0a78fb 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -90,9 +90,16 @@ var expectedConf = &Config{ Action: relabel.Drop, }, }, - QueueConfig: DefaultQueueConfig, - MetadataConfig: DefaultMetadataConfig, - HTTPClientConfig: config.DefaultHTTPClientConfig, + QueueConfig: DefaultQueueConfig, + MetadataConfig: DefaultMetadataConfig, + HTTPClientConfig: config.HTTPClientConfig{ + OAuth2: &config.OAuth2{ + ClientID: "123", + ClientSecret: "456", + TokenURL: "http://remote1/auth", + }, + FollowRedirects: true, + }, }, { URL: mustParseURL("http://remote2/push"), @@ -1010,7 +1017,7 @@ var expectedErrors = []struct { errMsg: "at most one of bearer_token & bearer_token_file must be configured", }, { filename: "bearertoken_basicauth.bad.yml", - errMsg: "at most one of basic_auth, bearer_token & bearer_token_file must be configured", + errMsg: "at most one of basic_auth, oauth2, bearer_token & bearer_token_file must be configured", }, { filename: "kubernetes_http_config_without_api_server.bad.yml", errMsg: "to use custom HTTP client configuration please provide the 'api_server' URL explicitly", @@ -1046,10 +1053,10 @@ var expectedErrors = []struct { errMsg: "invalid selector: 'metadata.status-Running'; can't understand 'metadata.status-Running'", }, { filename: "kubernetes_bearertoken_basicauth.bad.yml", - errMsg: "at most one of basic_auth, bearer_token & bearer_token_file must be configured", + errMsg: "at most one of basic_auth, oauth2, bearer_token & bearer_token_file must be configured", }, { filename: "kubernetes_authorization_basicauth.bad.yml", - errMsg: "at most one of basic_auth & authorization must be configured", + errMsg: "at most one of basic_auth, oauth2 & authorization must be configured", }, { filename: "marathon_no_servers.bad.yml", errMsg: "marathon_sd: must contain at least one Marathon server", @@ -1094,7 +1101,7 @@ var expectedErrors = []struct { errMsg: `x-prometheus-remote-write-version is a reserved header. It must not be changed`, }, { filename: "remote_write_authorization_header.bad.yml", - errMsg: `authorization header must be changed via the basic_auth or authorization parameter`, + errMsg: `authorization header must be changed via the basic_auth, authorization, oauth2, or sigv4 parameter`, }, { filename: "remote_write_url_missing.bad.yml", errMsg: `url for remote_write is empty`, diff --git a/config/testdata/conf.good.yml b/config/testdata/conf.good.yml index 7163abbfe..d0f565d58 100644 --- a/config/testdata/conf.good.yml +++ b/config/testdata/conf.good.yml @@ -19,6 +19,11 @@ remote_write: - source_labels: [__name__] regex: expensive.* action: drop + oauth2: + client_id: "123" + client_secret: "456" + token_url: "http://remote1/auth" + - url: http://remote2/push name: rw_tls tls_config: diff --git a/docs/configuration/configuration.md b/docs/configuration/configuration.md index d2bc058cd..72135a270 100644 --- a/docs/configuration/configuration.md +++ b/docs/configuration/configuration.md @@ -180,6 +180,11 @@ authorization: # configured file. It is mutually exclusive with `credentials`. [ credentials_file: ] +# Optional OAuth 2.0 configuration. +# Cannot be used at the same time as basic_auth or authorization. +oauth2: + [ ] + # Configure whether scrape requests follow HTTP 3xx redirects. [ follow_redirects: | default = true ] @@ -313,6 +318,32 @@ A `tls_config` allows configuring TLS connections. [ insecure_skip_verify: ] ``` +### `oauth2` + +OAuth 2.0 authentication using the client credentials grant type. +Prometheus fetches an access token from the specified endpoint with +the given client access and secret keys. + +```yaml +client_id: +[ client_secret: ] + +# Read the client secret from a file. +# It is mutually exclusive with `client_secret`. +[ client_secret_file: ] + +# Scopes for the token request. +scopes: + [ - ... ] + +# The URL to fetch the token from. +token_url: + +# Optional parameters to append to the token URL. +endpoint_params: + [ : ... ] +``` + ### `` Azure SD configurations allow retrieving scrape targets from Azure VMs. @@ -477,6 +508,11 @@ authorization: # It is mutually exclusive with `credentials`. [ credentials_file: ] +# Optional OAuth 2.0 configuration. +# Cannot be used at the same time as basic_auth or authorization. +oauth2: + [ ] + # Optional proxy URL. [ proxy_url: ] @@ -569,6 +605,11 @@ authorization: # It is mutually exclusive with `credentials`. [ credentials_file: ] +# Optional OAuth 2.0 configuration. +# Cannot be used at the same time as basic_auth or authorization. +oauth2: + [ ] + # Configure whether HTTP requests follow HTTP 3xx redirects. [ follow_redirects: | default = true ] @@ -727,6 +768,11 @@ authorization: # It is mutually exclusive with `credentials`. [ credentials_file: ] +# Optional OAuth 2.0 configuration. +# Cannot be used at the same time as basic_auth or authorization. +oauth2: + [ ] + # Configure whether HTTP requests follow HTTP 3xx redirects. [ follow_redirects: | default = true ] @@ -1135,6 +1181,11 @@ authorization: # It is mutually exclusive with `credentials`. [ credentials_file: ] +# Optional OAuth 2.0 configuration. +# Cannot be used at the same time as basic_auth or authorization. +oauth2: + [ ] + # Optional proxy URL. [ proxy_url: ] @@ -1306,6 +1357,11 @@ authorization: # It is mutually exclusive with `credentials`. [ credentials_file: ] +# Optional OAuth 2.0 configuration. +# Cannot be used at the same time as basic_auth or authorization. +oauth2: + [ ] + # Optional proxy URL. [ proxy_url: ] @@ -1454,6 +1510,11 @@ authorization: # It is mutually exclusive with `credentials`. [ credentials_file: ] +# Optional OAuth 2.0 configuration. +# Cannot be used at the same time as basic_auth or authorization. +oauth2: + [ ] + # Configure whether HTTP requests follow HTTP 3xx redirects. [ follow_redirects: | default = true ] @@ -1652,6 +1713,11 @@ authorization: # It is mutually exclusive with `credentials`. [ credentials_file: ] +# Optional OAuth 2.0 configuration. +# Cannot be used at the same time as basic_auth or authorization. +oauth2: + [ ] + # Configures the scrape request's TLS settings. tls_config: [ ] @@ -1930,6 +1996,11 @@ authorization: # It is mutually exclusive with `credentials`. [ credentials_file: ] +# Optional OAuth 2.0 configuration. +# Cannot be used at the same time as basic_auth or authorization. +oauth2: + [ ] + # Configures the scrape request's TLS settings. tls_config: [ ] @@ -2075,7 +2146,7 @@ authorization: [ credentials_file: ] # Optionally configures AWS's Signature Verification 4 signing process to -# sign requests. Cannot be set at the same time as basic_auth or authorization. +# sign requests. Cannot be set at the same time as basic_auth, authorization, or oauth2. # To use the default credentials from the AWS SDK, use `sigv4: {}`. sigv4: # The AWS region. If blank, the region from the default credentials chain @@ -2093,6 +2164,11 @@ sigv4: # AWS Role ARN, an alternative to using AWS API keys. [ role_arn: ] +# Optional OAuth 2.0 configuration. +# Cannot be used at the same time as basic_auth, authorization, or sigv4. +oauth2: + [ ] + # Configures the remote write request's TLS settings. tls_config: [ ] @@ -2187,6 +2263,11 @@ authorization: # It is mutually exclusive with `credentials`. [ credentials_file: ] +# Optional OAuth 2.0 configuration. +# Cannot be used at the same time as basic_auth or authorization. +oauth2: + [ ] + # Configures the remote read request's TLS settings. tls_config: [ ] diff --git a/go.mod b/go.mod index b9fa5bdbb..62828efc6 100644 --- a/go.mod +++ b/go.mod @@ -48,7 +48,7 @@ require ( github.com/prometheus/alertmanager v0.21.0 github.com/prometheus/client_golang v1.10.0 github.com/prometheus/client_model v0.2.0 - github.com/prometheus/common v0.21.0 + github.com/prometheus/common v0.23.0 github.com/prometheus/exporter-toolkit v0.5.1 github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7.0.20210223165440-c65ae3540d44 github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 diff --git a/go.sum b/go.sum index aa7d9f835..5d8b1cb2b 100644 --- a/go.sum +++ b/go.sum @@ -722,8 +722,8 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.21.0 h1:SMvI2JVldvfUvRVlP64jkIJEC6WiGHJcN2e5tB+ztF8= -github.com/prometheus/common v0.21.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.23.0 h1:GXWvPYuTUenIa+BhOq/x+L/QZzCqASkVRny5KTlPDGM= +github.com/prometheus/common v0.23.0/go.mod h1:H6QK/N6XVT42whUeIdI3dp36w49c+/iMDk7UAI2qm7Q= github.com/prometheus/exporter-toolkit v0.5.1 h1:9eqgis5er9xN613ZSADjypCJaDGj9ZlcWBvsIHa8/3c= github.com/prometheus/exporter-toolkit v0.5.1/go.mod h1:OCkM4805mmisBhLmVFw858QYi3v0wKdY6/UxrT0pZVg= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=