@@ -52,6 +52,21 @@ func (a *BasicAuth) SetDirectory(dir string) {
52
52
a .PasswordFile = JoinDir (dir , a .PasswordFile )
53
53
}
54
54
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
+
55
70
// URL is a custom URL type that allows validation at configuration load time.
56
71
type URL struct {
57
72
* url.URL
@@ -84,14 +99,21 @@ func (u URL) MarshalYAML() (interface{}, error) {
84
99
type HTTPClientConfig struct {
85
100
// The HTTP basic authentication credentials for the targets.
86
101
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.
88
106
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.
90
109
BearerTokenFile string `yaml:"bearer_token_file,omitempty"`
91
110
// HTTP proxy server to use to connect to the targets.
92
111
ProxyURL URL `yaml:"proxy_url,omitempty"`
93
112
// TLSConfig to use to connect to the targets.
94
113
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
95
117
}
96
118
97
119
// SetDirectory joins any relative file paths with dir.
@@ -101,12 +123,14 @@ func (c *HTTPClientConfig) SetDirectory(dir string) {
101
123
}
102
124
c .TLSConfig .SetDirectory (dir )
103
125
c .BasicAuth .SetDirectory (dir )
126
+ c .Authorization .SetDirectory (dir )
104
127
c .BearerTokenFile = JoinDir (dir , c .BearerTokenFile )
105
128
}
106
129
107
130
// Validate validates the HTTPClientConfig to check only one of BearerToken,
108
131
// BasicAuth and BearerTokenFile is configured.
109
132
func (c * HTTPClientConfig ) Validate () error {
133
+ // Backwards compatibility with the bearer_token field.
110
134
if len (c .BearerToken ) > 0 && len (c .BearerTokenFile ) > 0 {
111
135
return fmt .Errorf ("at most one of bearer_token & bearer_token_file must be configured" )
112
136
}
@@ -116,6 +140,37 @@ func (c *HTTPClientConfig) Validate() error {
116
140
if c .BasicAuth != nil && (string (c .BasicAuth .Password ) != "" && c .BasicAuth .PasswordFile != "" ) {
117
141
return fmt .Errorf ("at most one of basic_auth password & password_file must be configured" )
118
142
}
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
119
174
return nil
120
175
}
121
176
@@ -152,6 +207,12 @@ func NewClientFromConfig(cfg HTTPClientConfig, name string, disableKeepAlives, e
152
207
// NewRoundTripperFromConfig returns a new HTTP RoundTripper configured for the
153
208
// given config.HTTPClientConfig. The name is used as go-conntrack metric label.
154
209
func 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
+ }
155
216
newRT := func (tlsConfig * tls.Config ) (http.RoundTripper , error ) {
156
217
// The only timeout we care about is the configured scrape timeout.
157
218
// It is applied on request. So we leave out any timings here.
@@ -186,12 +247,12 @@ func NewRoundTripperFromConfig(cfg HTTPClientConfig, name string, disableKeepAli
186
247
}
187
248
}
188
249
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
190
251
// 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 )
195
256
}
196
257
197
258
if cfg .BasicAuth != nil {
@@ -214,58 +275,61 @@ func NewRoundTripperFromConfig(cfg HTTPClientConfig, name string, disableKeepAli
214
275
return newTLSRoundTripper (tlsConfig , cfg .TLSConfig .CAFile , newRT )
215
276
}
216
277
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
220
282
}
221
283
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 }
226
288
}
227
289
228
- func (rt * bearerAuthRoundTripper ) RoundTrip (req * http.Request ) (* http.Response , error ) {
290
+ func (rt * authorizationCredentialsRoundTripper ) RoundTrip (req * http.Request ) (* http.Response , error ) {
229
291
if len (req .Header .Get ("Authorization" )) == 0 {
230
292
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 )))
232
294
}
233
295
return rt .rt .RoundTrip (req )
234
296
}
235
297
236
- func (rt * bearerAuthRoundTripper ) CloseIdleConnections () {
298
+ func (rt * authorizationCredentialsRoundTripper ) CloseIdleConnections () {
237
299
if ci , ok := rt .rt .(closeIdler ); ok {
238
300
ci .CloseIdleConnections ()
239
301
}
240
302
}
241
303
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
245
308
}
246
309
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 }
251
315
}
252
316
253
- func (rt * bearerAuthFileRoundTripper ) RoundTrip (req * http.Request ) (* http.Response , error ) {
317
+ func (rt * authorizationCredentialsFileRoundTripper ) RoundTrip (req * http.Request ) (* http.Response , error ) {
254
318
if len (req .Header .Get ("Authorization" )) == 0 {
255
- b , err := ioutil .ReadFile (rt .bearerFile )
319
+ b , err := ioutil .ReadFile (rt .authCredentialsFile )
256
320
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 )
258
322
}
259
- bearerToken := strings .TrimSpace (string (b ))
323
+ authCredentials := strings .TrimSpace (string (b ))
260
324
261
325
req = cloneRequest (req )
262
- req .Header .Set ("Authorization" , "Bearer " + bearerToken )
326
+ req .Header .Set ("Authorization" , fmt . Sprintf ( "%s %s" , rt . authType , authCredentials ) )
263
327
}
264
328
265
329
return rt .rt .RoundTrip (req )
266
330
}
267
331
268
- func (rt * bearerAuthFileRoundTripper ) CloseIdleConnections () {
332
+ func (rt * authorizationCredentialsFileRoundTripper ) CloseIdleConnections () {
269
333
if ci , ok := rt .rt .(closeIdler ); ok {
270
334
ci .CloseIdleConnections ()
271
335
}
0 commit comments