Merge pull request #71713 from liggitt/tokenfile-reload

Plumb token and token file through rest.Config

Kubernetes-commit: 2bd14ea60e934f0d7a499a1a830a05262238605a
This commit is contained in:
Kubernetes Publisher 2018-12-04 11:41:03 -08:00
commit 77c598ed24
9 changed files with 117 additions and 84 deletions

102
Godeps/Godeps.json generated
View File

@ -404,207 +404,207 @@
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/api/apitesting", "ImportPath": "k8s.io/apimachinery/pkg/api/apitesting",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/api/apitesting/fuzzer", "ImportPath": "k8s.io/apimachinery/pkg/api/apitesting/fuzzer",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/api/apitesting/roundtrip", "ImportPath": "k8s.io/apimachinery/pkg/api/apitesting/roundtrip",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/api/equality", "ImportPath": "k8s.io/apimachinery/pkg/api/equality",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/api/errors", "ImportPath": "k8s.io/apimachinery/pkg/api/errors",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/api/meta", "ImportPath": "k8s.io/apimachinery/pkg/api/meta",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/api/resource", "ImportPath": "k8s.io/apimachinery/pkg/api/resource",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer", "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/internalversion", "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/internalversion",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1", "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured", "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1", "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/conversion", "ImportPath": "k8s.io/apimachinery/pkg/conversion",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams", "ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/fields", "ImportPath": "k8s.io/apimachinery/pkg/fields",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/labels", "ImportPath": "k8s.io/apimachinery/pkg/labels",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/runtime", "ImportPath": "k8s.io/apimachinery/pkg/runtime",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/runtime/schema", "ImportPath": "k8s.io/apimachinery/pkg/runtime/schema",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer", "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json", "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf", "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer", "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/streaming", "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/streaming",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning", "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/selection", "ImportPath": "k8s.io/apimachinery/pkg/selection",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/types", "ImportPath": "k8s.io/apimachinery/pkg/types",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/cache", "ImportPath": "k8s.io/apimachinery/pkg/util/cache",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/clock", "ImportPath": "k8s.io/apimachinery/pkg/util/clock",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/diff", "ImportPath": "k8s.io/apimachinery/pkg/util/diff",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/errors", "ImportPath": "k8s.io/apimachinery/pkg/util/errors",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/framer", "ImportPath": "k8s.io/apimachinery/pkg/util/framer",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream", "ImportPath": "k8s.io/apimachinery/pkg/util/httpstream",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream/spdy", "ImportPath": "k8s.io/apimachinery/pkg/util/httpstream/spdy",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/intstr", "ImportPath": "k8s.io/apimachinery/pkg/util/intstr",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/json", "ImportPath": "k8s.io/apimachinery/pkg/util/json",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch", "ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/naming", "ImportPath": "k8s.io/apimachinery/pkg/util/naming",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/net", "ImportPath": "k8s.io/apimachinery/pkg/util/net",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/remotecommand", "ImportPath": "k8s.io/apimachinery/pkg/util/remotecommand",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/runtime", "ImportPath": "k8s.io/apimachinery/pkg/util/runtime",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/sets", "ImportPath": "k8s.io/apimachinery/pkg/util/sets",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch", "ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/validation", "ImportPath": "k8s.io/apimachinery/pkg/util/validation",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/validation/field", "ImportPath": "k8s.io/apimachinery/pkg/util/validation/field",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/wait", "ImportPath": "k8s.io/apimachinery/pkg/util/wait",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/yaml", "ImportPath": "k8s.io/apimachinery/pkg/util/yaml",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/version", "ImportPath": "k8s.io/apimachinery/pkg/version",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/watch", "ImportPath": "k8s.io/apimachinery/pkg/watch",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json", "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/netutil", "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/netutil",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect", "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect",
"Rev": "18a5ff3097b4b189511742e39151a153ee16988b" "Rev": "eb8c8024849baa3681995b2b0bd4da7ea1734ace"
}, },
{ {
"ImportPath": "k8s.io/klog", "ImportPath": "k8s.io/klog",

View File

@ -70,6 +70,11 @@ type Config struct {
// TODO: demonstrate an OAuth2 compatible client. // TODO: demonstrate an OAuth2 compatible client.
BearerToken string BearerToken string
// Path to a file containing a BearerToken.
// If set, the contents are periodically read.
// The last successfully read value takes precedence over BearerToken.
BearerTokenFile string
// Impersonate is the configuration that RESTClient will use for impersonation. // Impersonate is the configuration that RESTClient will use for impersonation.
Impersonate ImpersonationConfig Impersonate ImpersonationConfig
@ -322,9 +327,8 @@ func InClusterConfig() (*Config, error) {
return nil, ErrNotInCluster return nil, ErrNotInCluster
} }
ts := NewCachedFileTokenSource(tokenFile) token, err := ioutil.ReadFile(tokenFile)
if err != nil {
if _, err := ts.Token(); err != nil {
return nil, err return nil, err
} }
@ -340,7 +344,8 @@ func InClusterConfig() (*Config, error) {
// TODO: switch to using cluster DNS. // TODO: switch to using cluster DNS.
Host: "https://" + net.JoinHostPort(host, port), Host: "https://" + net.JoinHostPort(host, port),
TLSClientConfig: tlsClientConfig, TLSClientConfig: tlsClientConfig,
WrapTransport: TokenSourceWrapTransport(ts), BearerToken: string(token),
BearerTokenFile: tokenFile,
}, nil }, nil
} }
@ -436,6 +441,7 @@ func CopyConfig(config *Config) *Config {
Username: config.Username, Username: config.Username,
Password: config.Password, Password: config.Password,
BearerToken: config.BearerToken, BearerToken: config.BearerToken,
BearerTokenFile: config.BearerTokenFile,
Impersonate: ImpersonationConfig{ Impersonate: ImpersonationConfig{
Groups: config.Impersonate.Groups, Groups: config.Impersonate.Groups,
Extra: config.Impersonate.Extra, Extra: config.Impersonate.Extra,

View File

@ -264,6 +264,7 @@ func TestAnonymousConfig(t *testing.T) {
// is added to Config, update AnonymousClientConfig to preserve the field otherwise. // is added to Config, update AnonymousClientConfig to preserve the field otherwise.
expected.Impersonate = ImpersonationConfig{} expected.Impersonate = ImpersonationConfig{}
expected.BearerToken = "" expected.BearerToken = ""
expected.BearerTokenFile = ""
expected.Username = "" expected.Username = ""
expected.Password = "" expected.Password = ""
expected.AuthProvider = nil expected.AuthProvider = nil

View File

@ -229,11 +229,12 @@ func (config *DirectClientConfig) getUserIdentificationPartialConfig(configAuthI
if len(configAuthInfo.Token) > 0 { if len(configAuthInfo.Token) > 0 {
mergedConfig.BearerToken = configAuthInfo.Token mergedConfig.BearerToken = configAuthInfo.Token
} else if len(configAuthInfo.TokenFile) > 0 { } else if len(configAuthInfo.TokenFile) > 0 {
ts := restclient.NewCachedFileTokenSource(configAuthInfo.TokenFile) tokenBytes, err := ioutil.ReadFile(configAuthInfo.TokenFile)
if _, err := ts.Token(); err != nil { if err != nil {
return nil, err return nil, err
} }
mergedConfig.WrapTransport = restclient.TokenSourceWrapTransport(ts) mergedConfig.BearerToken = string(tokenBytes)
mergedConfig.BearerTokenFile = configAuthInfo.TokenFile
} }
if len(configAuthInfo.Impersonate) > 0 { if len(configAuthInfo.Impersonate) > 0 {
mergedConfig.Impersonate = restclient.ImpersonationConfig{ mergedConfig.Impersonate = restclient.ImpersonationConfig{

View File

@ -18,7 +18,6 @@ package clientcmd
import ( import (
"io/ioutil" "io/ioutil"
"net/http"
"os" "os"
"reflect" "reflect"
"strings" "strings"
@ -334,19 +333,7 @@ func TestBasicTokenFile(t *testing.T) {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
var out *http.Request matchStringArg(token, clientConfig.BearerToken, t)
clientConfig.WrapTransport(fakeTransport(func(req *http.Request) (*http.Response, error) {
out = req
return &http.Response{}, nil
})).RoundTrip(&http.Request{})
matchStringArg(token, strings.TrimPrefix(out.Header.Get("Authorization"), "Bearer "), t)
}
type fakeTransport func(*http.Request) (*http.Response, error)
func (ft fakeTransport) RoundTrip(req *http.Request) (*http.Response, error) {
return ft(req)
} }
func TestPrecedenceTokenFile(t *testing.T) { func TestPrecedenceTokenFile(t *testing.T) {

View File

@ -39,6 +39,11 @@ type Config struct {
// Bearer token for authentication // Bearer token for authentication
BearerToken string BearerToken string
// Path to a file containing a BearerToken.
// If set, the contents are periodically read.
// The last successfully read value takes precedence over BearerToken.
BearerTokenFile string
// Impersonate is the config that this Config will impersonate using // Impersonate is the config that this Config will impersonate using
Impersonate ImpersonationConfig Impersonate ImpersonationConfig
@ -80,7 +85,7 @@ func (c *Config) HasBasicAuth() bool {
// HasTokenAuth returns whether the configuration has token authentication or not. // HasTokenAuth returns whether the configuration has token authentication or not.
func (c *Config) HasTokenAuth() bool { func (c *Config) HasTokenAuth() bool {
return len(c.BearerToken) != 0 return len(c.BearerToken) != 0 || len(c.BearerTokenFile) != 0
} }
// HasCertAuth returns whether the configuration has certificate authentication or not. // HasCertAuth returns whether the configuration has certificate authentication or not.

View File

@ -22,6 +22,7 @@ import (
"strings" "strings"
"time" "time"
"golang.org/x/oauth2"
"k8s.io/klog" "k8s.io/klog"
utilnet "k8s.io/apimachinery/pkg/util/net" utilnet "k8s.io/apimachinery/pkg/util/net"
@ -44,7 +45,11 @@ func HTTPWrappersForConfig(config *Config, rt http.RoundTripper) (http.RoundTrip
case config.HasBasicAuth() && config.HasTokenAuth(): case config.HasBasicAuth() && config.HasTokenAuth():
return nil, fmt.Errorf("username/password or bearer token may be set, but not both") return nil, fmt.Errorf("username/password or bearer token may be set, but not both")
case config.HasTokenAuth(): case config.HasTokenAuth():
rt = NewBearerAuthRoundTripper(config.BearerToken, rt) var err error
rt, err = NewBearerAuthWithRefreshRoundTripper(config.BearerToken, config.BearerTokenFile, rt)
if err != nil {
return nil, err
}
case config.HasBasicAuth(): case config.HasBasicAuth():
rt = NewBasicAuthRoundTripper(config.Username, config.Password, rt) rt = NewBasicAuthRoundTripper(config.Username, config.Password, rt)
} }
@ -265,13 +270,35 @@ func (rt *impersonatingRoundTripper) WrappedRoundTripper() http.RoundTripper { r
type bearerAuthRoundTripper struct { type bearerAuthRoundTripper struct {
bearer string bearer string
source oauth2.TokenSource
rt http.RoundTripper rt http.RoundTripper
} }
// NewBearerAuthRoundTripper adds the provided bearer token to a request // NewBearerAuthRoundTripper adds the provided bearer token to a request
// unless the authorization header has already been set. // unless the authorization header has already been set.
func NewBearerAuthRoundTripper(bearer string, rt http.RoundTripper) http.RoundTripper { func NewBearerAuthRoundTripper(bearer string, rt http.RoundTripper) http.RoundTripper {
return &bearerAuthRoundTripper{bearer, rt} return &bearerAuthRoundTripper{bearer, nil, rt}
}
// NewBearerAuthRoundTripper adds the provided bearer token to a request
// unless the authorization header has already been set.
// If tokenFile is non-empty, it is periodically read,
// and the last successfully read content is used as the bearer token.
// If tokenFile is non-empty and bearer is empty, the tokenFile is read
// immediately to populate the initial bearer token.
func NewBearerAuthWithRefreshRoundTripper(bearer string, tokenFile string, rt http.RoundTripper) (http.RoundTripper, error) {
if len(tokenFile) == 0 {
return &bearerAuthRoundTripper{bearer, nil, rt}, nil
}
source := NewCachedFileTokenSource(tokenFile)
if len(bearer) == 0 {
token, err := source.Token()
if err != nil {
return nil, err
}
bearer = token.AccessToken
}
return &bearerAuthRoundTripper{bearer, source, rt}, nil
} }
func (rt *bearerAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { func (rt *bearerAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
@ -280,7 +307,13 @@ func (rt *bearerAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response,
} }
req = utilnet.CloneRequest(req) req = utilnet.CloneRequest(req)
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", rt.bearer)) token := rt.bearer
if rt.source != nil {
if refreshedToken, err := rt.source.Token(); err == nil {
token = refreshedToken.AccessToken
}
}
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
return rt.rt.RoundTrip(req) return rt.rt.RoundTrip(req)
} }

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package rest package transport
import ( import (
"fmt" "fmt"

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package rest package transport
import ( import (
"fmt" "fmt"