@@ -32,6 +32,8 @@ import (
32
32
33
33
"github.com/mwitkow/go-conntrack"
34
34
"golang.org/x/net/http2"
35
+ "golang.org/x/oauth2"
36
+ "golang.org/x/oauth2/clientcredentials"
35
37
"gopkg.in/yaml.v2"
36
38
)
37
39
@@ -108,12 +110,23 @@ func (u URL) MarshalYAML() (interface{}, error) {
108
110
return nil , nil
109
111
}
110
112
113
+ // OAuth2 is the oauth2 client configuration.
114
+ type OAuth2 struct {
115
+ ClientID string `yaml:"client_id"`
116
+ ClientSecret Secret `yaml:"client_secret"`
117
+ Scopes []string `yaml:"scopes,omitempty"`
118
+ TokenURL string `yaml:"token_url"`
119
+ EndpointParams map [string ]string `yaml:"endpoint_params,omitempty"`
120
+ }
121
+
111
122
// HTTPClientConfig configures an HTTP client.
112
123
type HTTPClientConfig struct {
113
124
// The HTTP basic authentication credentials for the targets.
114
125
BasicAuth * BasicAuth `yaml:"basic_auth,omitempty"`
115
126
// The HTTP authorization credentials for the targets.
116
127
Authorization * Authorization `yaml:"authorization,omitempty"`
128
+ // The OAuth2 client credentials used to fetch a token for the targets.
129
+ OAuth2 * OAuth2 `yaml:"oauth2,omitempty"`
117
130
// The bearer token for the targets. Deprecated in favour of
118
131
// Authorization.Credentials.
119
132
BearerToken Secret `yaml:"bearer_token,omitempty"`
@@ -148,8 +161,8 @@ func (c *HTTPClientConfig) Validate() error {
148
161
if len (c .BearerToken ) > 0 && len (c .BearerTokenFile ) > 0 {
149
162
return fmt .Errorf ("at most one of bearer_token & bearer_token_file must be configured" )
150
163
}
151
- if c .BasicAuth != nil && (len (c .BearerToken ) > 0 || len (c .BearerTokenFile ) > 0 ) {
152
- return fmt .Errorf ("at most one of basic_auth, bearer_token & bearer_token_file must be configured" )
164
+ if ( c .BasicAuth != nil || c . OAuth2 != nil ) && (len (c .BearerToken ) > 0 || len (c .BearerTokenFile ) > 0 ) {
165
+ return fmt .Errorf ("at most one of basic_auth, oauth2, bearer_token & bearer_token_file must be configured" )
153
166
}
154
167
if c .BasicAuth != nil && (string (c .BasicAuth .Password ) != "" && c .BasicAuth .PasswordFile != "" ) {
155
168
return fmt .Errorf ("at most one of basic_auth password & password_file must be configured" )
@@ -168,8 +181,8 @@ func (c *HTTPClientConfig) Validate() error {
168
181
if strings .ToLower (c .Authorization .Type ) == "basic" {
169
182
return fmt .Errorf (`authorization type cannot be set to "basic", use "basic_auth" instead` )
170
183
}
171
- if c .BasicAuth != nil {
172
- return fmt .Errorf ("at most one of basic_auth & authorization must be configured" )
184
+ if c .BasicAuth != nil || c . OAuth2 != nil {
185
+ return fmt .Errorf ("at most one of basic_auth, oauth2 & authorization must be configured" )
173
186
}
174
187
} else {
175
188
if len (c .BearerToken ) > 0 {
@@ -183,6 +196,9 @@ func (c *HTTPClientConfig) Validate() error {
183
196
c .BearerTokenFile = ""
184
197
}
185
198
}
199
+ if c .BasicAuth != nil && c .OAuth2 != nil {
200
+ return fmt .Errorf ("at most one of basic_auth, oauth2 & authorization must be configured" )
201
+ }
186
202
return nil
187
203
}
188
204
@@ -329,6 +345,10 @@ func NewRoundTripperFromConfig(cfg HTTPClientConfig, name string, optFuncs ...HT
329
345
if cfg .BasicAuth != nil {
330
346
rt = NewBasicAuthRoundTripper (cfg .BasicAuth .Username , cfg .BasicAuth .Password , cfg .BasicAuth .PasswordFile , rt )
331
347
}
348
+
349
+ if cfg .OAuth2 != nil {
350
+ rt = cfg .OAuth2 .NewOAuth2RoundTripper (context .Background (), rt )
351
+ }
332
352
// Return a new configured RoundTripper.
333
353
return rt , nil
334
354
}
@@ -442,6 +462,32 @@ func (rt *basicAuthRoundTripper) CloseIdleConnections() {
442
462
}
443
463
}
444
464
465
+ func (c * OAuth2 ) NewOAuth2RoundTripper (ctx context.Context , next http.RoundTripper ) http.RoundTripper {
466
+ config := & clientcredentials.Config {
467
+ ClientID : c .ClientID ,
468
+ ClientSecret : string (c .ClientSecret ),
469
+ Scopes : c .Scopes ,
470
+ TokenURL : c .TokenURL ,
471
+ EndpointParams : mapToValues (c .EndpointParams ),
472
+ }
473
+
474
+ tokenSource := config .TokenSource (ctx )
475
+
476
+ return & oauth2.Transport {
477
+ Base : next ,
478
+ Source : tokenSource ,
479
+ }
480
+ }
481
+
482
+ func mapToValues (m map [string ]string ) url.Values {
483
+ v := url.Values {}
484
+ for name , value := range m {
485
+ v .Set (name , value )
486
+ }
487
+
488
+ return v
489
+ }
490
+
445
491
// cloneRequest returns a clone of the provided *http.Request.
446
492
// The clone is a shallow copy of the struct and its Header map.
447
493
func cloneRequest (r * http.Request ) * http.Request {
0 commit comments