@@ -52,6 +52,21 @@ func (a *BasicAuth) SetDirectory(dir string) {
5252 a .PasswordFile = JoinDir (dir , a .PasswordFile )
5353}
5454
55+ // Authorization contains HTTP authorization credentials.
56+ type Authorization struct {
57+ Type string `yaml:"type,omitempty"`
58+ Credentials Secret `yaml:"credentials,omitempty"`
59+ CredentialsFile string `yaml:"credentials_file,omitempty"`
60+ }
61+
62+ // SetDirectory joins any relative file paths with dir.
63+ func (a * Authorization ) SetDirectory (dir string ) {
64+ if a == nil {
65+ return
66+ }
67+ a .CredentialsFile = JoinDir (dir , a .CredentialsFile )
68+ }
69+
5570// URL is a custom URL type that allows validation at configuration load time.
5671type URL struct {
5772 * url.URL
@@ -84,14 +99,21 @@ func (u URL) MarshalYAML() (interface{}, error) {
8499type HTTPClientConfig struct {
85100 // The HTTP basic authentication credentials for the targets.
86101 BasicAuth * BasicAuth `yaml:"basic_auth,omitempty"`
87- // The bearer token for the targets.
102+ // The HTTP authorization credentials for the targets.
103+ Authorization * Authorization `yaml:"authorization,omitempty"`
104+ // The bearer token for the targets. Deprecated in favour of
105+ // Authorization.Credentials.
88106 BearerToken Secret `yaml:"bearer_token,omitempty"`
89- // The bearer token file for the targets.
107+ // The bearer token file for the targets. Deprecated in favour of
108+ // Authorization.CredentialsFile.
90109 BearerTokenFile string `yaml:"bearer_token_file,omitempty"`
91110 // HTTP proxy server to use to connect to the targets.
92111 ProxyURL URL `yaml:"proxy_url,omitempty"`
93112 // TLSConfig to use to connect to the targets.
94113 TLSConfig TLSConfig `yaml:"tls_config,omitempty"`
114+ // Used to make sure that the configuration is valid and that BearerToken to
115+ // Authorization.Credentials change has been handled.
116+ valid bool
95117}
96118
97119// SetDirectory joins any relative file paths with dir.
@@ -101,12 +123,14 @@ func (c *HTTPClientConfig) SetDirectory(dir string) {
101123 }
102124 c .TLSConfig .SetDirectory (dir )
103125 c .BasicAuth .SetDirectory (dir )
126+ c .Authorization .SetDirectory (dir )
104127 c .BearerTokenFile = JoinDir (dir , c .BearerTokenFile )
105128}
106129
107130// Validate validates the HTTPClientConfig to check only one of BearerToken,
108131// BasicAuth and BearerTokenFile is configured.
109132func (c * HTTPClientConfig ) Validate () error {
133+ // Backwards compatibility with the bearer_token field.
110134 if len (c .BearerToken ) > 0 && len (c .BearerTokenFile ) > 0 {
111135 return fmt .Errorf ("at most one of bearer_token & bearer_token_file must be configured" )
112136 }
@@ -116,6 +140,37 @@ func (c *HTTPClientConfig) Validate() error {
116140 if c .BasicAuth != nil && (string (c .BasicAuth .Password ) != "" && c .BasicAuth .PasswordFile != "" ) {
117141 return fmt .Errorf ("at most one of basic_auth password & password_file must be configured" )
118142 }
143+ if c .Authorization != nil {
144+ if len (c .BearerToken ) > 0 || len (c .BearerTokenFile ) > 0 {
145+ return fmt .Errorf ("authorization is not compatible with bearer_token & bearer_token_file" )
146+ }
147+ if string (c .Authorization .Credentials ) != "" && c .Authorization .CredentialsFile != "" {
148+ return fmt .Errorf ("at most one of authorization credentials & credentials_file must be configured" )
149+ }
150+ c .Authorization .Type = strings .TrimSpace (c .Authorization .Type )
151+ if len (c .Authorization .Type ) == 0 {
152+ c .Authorization .Type = "Bearer"
153+ }
154+ if strings .ToLower (c .Authorization .Type ) == "basic" {
155+ return fmt .Errorf (`authorization type cannot be set to "basic", use "basic_auth" instead` )
156+ }
157+ if c .BasicAuth != nil {
158+ return fmt .Errorf ("at most one of basic_auth & authorization must be configured" )
159+ }
160+ } else {
161+ if len (c .BearerToken ) > 0 {
162+ c .Authorization = & Authorization {Credentials : c .BearerToken }
163+ c .Authorization .Type = "Bearer"
164+ c .BearerToken = ""
165+ }
166+ if len (c .BearerTokenFile ) > 0 {
167+ c .Authorization = & Authorization {CredentialsFile : c .BearerTokenFile }
168+ c .Authorization .Type = "Bearer"
169+ c .BearerTokenFile = ""
170+ }
171+ }
172+
173+ c .valid = true
119174 return nil
120175}
121176
@@ -152,6 +207,12 @@ func NewClientFromConfig(cfg HTTPClientConfig, name string, disableKeepAlives, e
152207// NewRoundTripperFromConfig returns a new HTTP RoundTripper configured for the
153208// given config.HTTPClientConfig. The name is used as go-conntrack metric label.
154209func NewRoundTripperFromConfig (cfg HTTPClientConfig , name string , disableKeepAlives , enableHTTP2 bool ) (http.RoundTripper , error ) {
210+ // Make sure that the configuration is valid.
211+ if ! cfg .valid {
212+ if err := cfg .Validate (); err != nil {
213+ return nil , err
214+ }
215+ }
155216 newRT := func (tlsConfig * tls.Config ) (http.RoundTripper , error ) {
156217 // The only timeout we care about is the configured scrape timeout.
157218 // It is applied on request. So we leave out any timings here.
@@ -186,12 +247,12 @@ func NewRoundTripperFromConfig(cfg HTTPClientConfig, name string, disableKeepAli
186247 }
187248 }
188249
189- // If a bearer token is provided, create a round tripper that will set the
250+ // If a authorization_credentials is provided, create a round tripper that will set the
190251 // Authorization header correctly on each request.
191- if len (cfg .BearerToken ) > 0 {
192- rt = NewBearerAuthRoundTripper (cfg .BearerToken , rt )
193- } else if len (cfg .BearerTokenFile ) > 0 {
194- rt = NewBearerAuthFileRoundTripper (cfg .BearerTokenFile , rt )
252+ if cfg . Authorization != nil && len (cfg .Authorization . Credentials ) > 0 {
253+ rt = NewAuthorizationCredentialsRoundTripper (cfg .Authorization . Type , cfg . Authorization . Credentials , rt )
254+ } else if cfg . Authorization != nil && len (cfg .Authorization . CredentialsFile ) > 0 {
255+ rt = NewAuthorizationCredentialsFileRoundTripper (cfg .Authorization . Type , cfg . Authorization . CredentialsFile , rt )
195256 }
196257
197258 if cfg .BasicAuth != nil {
@@ -214,58 +275,61 @@ func NewRoundTripperFromConfig(cfg HTTPClientConfig, name string, disableKeepAli
214275 return newTLSRoundTripper (tlsConfig , cfg .TLSConfig .CAFile , newRT )
215276}
216277
217- type bearerAuthRoundTripper struct {
218- bearerToken Secret
219- rt http.RoundTripper
278+ type authorizationCredentialsRoundTripper struct {
279+ authType string
280+ authCredentials Secret
281+ rt http.RoundTripper
220282}
221283
222- // NewBearerAuthRoundTripper adds the provided bearer token to a request unless the authorization
223- // header has already been set.
224- func NewBearerAuthRoundTripper ( token Secret , rt http.RoundTripper ) http.RoundTripper {
225- return & bearerAuthRoundTripper { token , rt }
284+ // NewAuthorizationCredentialsRoundTripper adds the provided credentials to a
285+ // request unless the authorization header has already been set.
286+ func NewAuthorizationCredentialsRoundTripper ( authType string , authCredentials Secret , rt http.RoundTripper ) http.RoundTripper {
287+ return & authorizationCredentialsRoundTripper { authType , authCredentials , rt }
226288}
227289
228- func (rt * bearerAuthRoundTripper ) RoundTrip (req * http.Request ) (* http.Response , error ) {
290+ func (rt * authorizationCredentialsRoundTripper ) RoundTrip (req * http.Request ) (* http.Response , error ) {
229291 if len (req .Header .Get ("Authorization" )) == 0 {
230292 req = cloneRequest (req )
231- req .Header .Set ("Authorization" , fmt .Sprintf ("Bearer %s" , string (rt .bearerToken )))
293+ req .Header .Set ("Authorization" , fmt .Sprintf ("%s %s" , rt . authType , string (rt .authCredentials )))
232294 }
233295 return rt .rt .RoundTrip (req )
234296}
235297
236- func (rt * bearerAuthRoundTripper ) CloseIdleConnections () {
298+ func (rt * authorizationCredentialsRoundTripper ) CloseIdleConnections () {
237299 if ci , ok := rt .rt .(closeIdler ); ok {
238300 ci .CloseIdleConnections ()
239301 }
240302}
241303
242- type bearerAuthFileRoundTripper struct {
243- bearerFile string
244- rt http.RoundTripper
304+ type authorizationCredentialsFileRoundTripper struct {
305+ authType string
306+ authCredentialsFile string
307+ rt http.RoundTripper
245308}
246309
247- // NewBearerAuthFileRoundTripper adds the bearer token read from the provided file to a request unless
248- // the authorization header has already been set. This file is read for every request.
249- func NewBearerAuthFileRoundTripper (bearerFile string , rt http.RoundTripper ) http.RoundTripper {
250- return & bearerAuthFileRoundTripper {bearerFile , rt }
310+ // NewAuthorizationCredentialsFileRoundTripper adds the authorization
311+ // credentials read from the provided file to a request unless the authorization
312+ // header has already been set. This file is read for every request.
313+ func NewAuthorizationCredentialsFileRoundTripper (authType , authCredentialsFile string , rt http.RoundTripper ) http.RoundTripper {
314+ return & authorizationCredentialsFileRoundTripper {authType , authCredentialsFile , rt }
251315}
252316
253- func (rt * bearerAuthFileRoundTripper ) RoundTrip (req * http.Request ) (* http.Response , error ) {
317+ func (rt * authorizationCredentialsFileRoundTripper ) RoundTrip (req * http.Request ) (* http.Response , error ) {
254318 if len (req .Header .Get ("Authorization" )) == 0 {
255- b , err := ioutil .ReadFile (rt .bearerFile )
319+ b , err := ioutil .ReadFile (rt .authCredentialsFile )
256320 if err != nil {
257- return nil , fmt .Errorf ("unable to read bearer token file %s: %s" , rt .bearerFile , err )
321+ return nil , fmt .Errorf ("unable to read authorization credentials file %s: %s" , rt .authCredentialsFile , err )
258322 }
259- bearerToken := strings .TrimSpace (string (b ))
323+ authCredentials := strings .TrimSpace (string (b ))
260324
261325 req = cloneRequest (req )
262- req .Header .Set ("Authorization" , "Bearer " + bearerToken )
326+ req .Header .Set ("Authorization" , fmt . Sprintf ( "%s %s" , rt . authType , authCredentials ) )
263327 }
264328
265329 return rt .rt .RoundTrip (req )
266330}
267331
268- func (rt * bearerAuthFileRoundTripper ) CloseIdleConnections () {
332+ func (rt * authorizationCredentialsFileRoundTripper ) CloseIdleConnections () {
269333 if ci , ok := rt .rt .(closeIdler ); ok {
270334 ci .CloseIdleConnections ()
271335 }
0 commit comments