From e5227216c0796d725c695e36cfc1d54e7631d3a6 Mon Sep 17 00:00:00 2001 From: Mike Danese Date: Mon, 15 Oct 2018 15:17:36 -0700 Subject: [PATCH] rebase authenticators onto new interface. --- pkg/kubelet/server/BUILD | 1 + pkg/kubelet/server/server.go | 8 +-- pkg/kubelet/server/server_test.go | 23 ++++---- .../authentication/tokenreview/storage.go | 16 +++--- pkg/serviceaccount/claims.go | 4 +- pkg/serviceaccount/claims_test.go | 4 +- pkg/serviceaccount/jwt.go | 12 ++--- pkg/serviceaccount/jwt_test.go | 17 +++--- pkg/serviceaccount/legacy.go | 6 +-- .../auth/authenticator/token/bootstrap/BUILD | 1 + .../token/bootstrap/bootstrap.go | 12 +++-- .../token/bootstrap/bootstrap_test.go | 6 +-- .../group/authenticated_group_adder.go | 25 ++++----- .../pkg/authentication/group/group_adder.go | 17 +++--- .../authentication/group/group_adder_test.go | 20 +++---- .../authentication/group/token_group_adder.go | 19 ++++--- .../group/token_group_adder_test.go | 11 ++-- .../request/anonymous/anonymous.go | 9 +++- .../request/anonymous/anonymous_test.go | 10 ++-- .../authentication/request/bearertoken/BUILD | 5 +- .../request/bearertoken/bearertoken.go | 7 ++- .../request/bearertoken/bearertoken_test.go | 49 +++++++++-------- .../request/headerrequest/requestheader.go | 12 +++-- .../headerrequest/requestheader_test.go | 30 ++++++----- .../pkg/authentication/request/union/BUILD | 6 ++- .../pkg/authentication/request/union/union.go | 9 ++-- .../request/union/unionauth_test.go | 23 ++++---- .../authentication/request/websocket/BUILD | 1 - .../request/websocket/protocol.go | 7 ++- .../request/websocket/protocol_test.go | 53 ++++++++++--------- .../pkg/authentication/request/x509/x509.go | 20 +++---- .../authentication/request/x509/x509_test.go | 24 ++++----- .../pkg/authentication/token/cache/BUILD | 1 - .../authentication/token/cache/cache_test.go | 10 ++-- .../token/cache/cached_token_authenticator.go | 18 ++++--- .../cache/cached_token_authenticator_test.go | 35 ++++++------ .../pkg/authentication/token/tokenfile/BUILD | 1 + .../token/tokenfile/tokenfile.go | 6 ++- .../token/tokenfile/tokenfile_test.go | 11 ++-- .../pkg/authentication/token/union/BUILD | 6 ++- .../pkg/authentication/token/union/union.go | 7 +-- .../token/union/unionauth_test.go | 32 +++++------ .../pkg/endpoints/filters/authentication.go | 9 ++-- .../endpoints/filters/authentication_test.go | 8 +-- .../pkg/server/deprecated_insecure_serving.go | 11 ++-- .../authenticator/password/passwordfile/BUILD | 1 + .../password/passwordfile/passwordfile.go | 6 ++- .../passwordfile/passwordfile_test.go | 11 ++-- .../pkg/authenticator/request/basicauth/BUILD | 5 +- .../request/basicauth/basicauth.go | 7 ++- .../request/basicauth/basicauth_test.go | 11 ++-- .../plugin/pkg/authenticator/token/oidc/BUILD | 1 + .../pkg/authenticator/token/oidc/oidc.go | 7 +-- .../pkg/authenticator/token/oidc/oidc_test.go | 5 +- .../pkg/authenticator/token/tokentest/BUILD | 5 +- .../token/tokentest/tokentest.go | 12 +++-- .../authenticator/token/webhook/webhook.go | 15 +++--- .../token/webhook/webhook_test.go | 17 +++--- test/integration/auth/accessreview_test.go | 14 +++-- test/integration/framework/master_utils.go | 8 +-- .../serviceaccount/service_account_test.go | 5 +- 61 files changed, 415 insertions(+), 337 deletions(-) diff --git a/pkg/kubelet/server/BUILD b/pkg/kubelet/server/BUILD index bd7fc020a1..2a9fd9efee 100644 --- a/pkg/kubelet/server/BUILD +++ b/pkg/kubelet/server/BUILD @@ -77,6 +77,7 @@ go_test( "//staging/src/k8s.io/apimachinery/pkg/util/httpstream:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/httpstream/spdy:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library", "//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", "//staging/src/k8s.io/client-go/tools/remotecommand:go_default_library", diff --git a/pkg/kubelet/server/server.go b/pkg/kubelet/server/server.go index 375149a441..4c8a3c3cdf 100644 --- a/pkg/kubelet/server/server.go +++ b/pkg/kubelet/server/server.go @@ -221,7 +221,7 @@ func NewServer( func (s *Server) InstallAuthFilter() { s.restfulCont.Filter(func(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) { // Authenticate - u, ok, err := s.auth.AuthenticateRequest(req.Request) + info, ok, err := s.auth.AuthenticateRequest(req.Request) if err != nil { glog.Errorf("Unable to authenticate the request due to an error: %v", err) resp.WriteErrorString(http.StatusUnauthorized, "Unauthorized") @@ -233,18 +233,18 @@ func (s *Server) InstallAuthFilter() { } // Get authorization attributes - attrs := s.auth.GetRequestAttributes(u, req.Request) + attrs := s.auth.GetRequestAttributes(info.User, req.Request) // Authorize decision, _, err := s.auth.Authorize(attrs) if err != nil { - msg := fmt.Sprintf("Authorization error (user=%s, verb=%s, resource=%s, subresource=%s)", u.GetName(), attrs.GetVerb(), attrs.GetResource(), attrs.GetSubresource()) + msg := fmt.Sprintf("Authorization error (user=%s, verb=%s, resource=%s, subresource=%s)", attrs.GetUser().GetName(), attrs.GetVerb(), attrs.GetResource(), attrs.GetSubresource()) glog.Errorf(msg, err) resp.WriteErrorString(http.StatusInternalServerError, msg) return } if decision != authorizer.DecisionAllow { - msg := fmt.Sprintf("Forbidden (user=%s, verb=%s, resource=%s, subresource=%s)", u.GetName(), attrs.GetVerb(), attrs.GetResource(), attrs.GetSubresource()) + msg := fmt.Sprintf("Forbidden (user=%s, verb=%s, resource=%s, subresource=%s)", attrs.GetUser().GetName(), attrs.GetVerb(), attrs.GetResource(), attrs.GetSubresource()) glog.V(2).Info(msg) resp.WriteErrorString(http.StatusForbidden, msg) return diff --git a/pkg/kubelet/server/server_test.go b/pkg/kubelet/server/server_test.go index dc8ba6e46a..4f4401f7a9 100644 --- a/pkg/kubelet/server/server_test.go +++ b/pkg/kubelet/server/server_test.go @@ -44,6 +44,7 @@ import ( "k8s.io/apimachinery/pkg/util/httpstream" "k8s.io/apimachinery/pkg/util/httpstream/spdy" "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/client-go/tools/remotecommand" @@ -269,12 +270,12 @@ func (_ *fakeKubelet) GetCgroupCPUAndMemoryStats(cgroupName string, updateStats } type fakeAuth struct { - authenticateFunc func(*http.Request) (user.Info, bool, error) + authenticateFunc func(*http.Request) (*authenticator.Response, bool, error) attributesFunc func(user.Info, *http.Request) authorizer.Attributes authorizeFunc func(authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) } -func (f *fakeAuth) AuthenticateRequest(req *http.Request) (user.Info, bool, error) { +func (f *fakeAuth) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) { return f.authenticateFunc(req) } func (f *fakeAuth) GetRequestAttributes(u user.Info, req *http.Request) authorizer.Attributes { @@ -317,8 +318,8 @@ func newServerTestWithDebug(enableDebugging, redirectContainerStreaming bool, st streamingRuntime: streamingServer, } fw.fakeAuth = &fakeAuth{ - authenticateFunc: func(req *http.Request) (user.Info, bool, error) { - return &user.DefaultInfo{Name: "test"}, true, nil + authenticateFunc: func(req *http.Request) (*authenticator.Response, bool, error) { + return &authenticator.Response{User: &user.DefaultInfo{Name: "test"}}, true, nil }, attributesFunc: func(u user.Info, req *http.Request) authorizer.Attributes { return &authorizer.AttributesRecord{User: u} @@ -768,9 +769,9 @@ Otherwise, add it to the expected list of paths that map to the "proxy" subresou calledAttributes = false ) - fw.fakeAuth.authenticateFunc = func(req *http.Request) (user.Info, bool, error) { + fw.fakeAuth.authenticateFunc = func(req *http.Request) (*authenticator.Response, bool, error) { calledAuthenticate = true - return expectedUser, true, nil + return &authenticator.Response{User: expectedUser}, true, nil } fw.fakeAuth.attributesFunc = func(u user.Info, req *http.Request) authorizer.Attributes { calledAttributes = true @@ -830,9 +831,9 @@ func TestAuthenticationError(t *testing.T) { fw := newServerTest() defer fw.testHTTPServer.Close() - fw.fakeAuth.authenticateFunc = func(req *http.Request) (user.Info, bool, error) { + fw.fakeAuth.authenticateFunc = func(req *http.Request) (*authenticator.Response, bool, error) { calledAuthenticate = true - return expectedUser, true, nil + return &authenticator.Response{User: expectedUser}, true, nil } fw.fakeAuth.attributesFunc = func(u user.Info, req *http.Request) authorizer.Attributes { calledAttributes = true @@ -868,7 +869,7 @@ func TestAuthenticationFailure(t *testing.T) { fw := newServerTest() defer fw.testHTTPServer.Close() - fw.fakeAuth.authenticateFunc = func(req *http.Request) (user.Info, bool, error) { + fw.fakeAuth.authenticateFunc = func(req *http.Request) (*authenticator.Response, bool, error) { calledAuthenticate = true return nil, false, nil } @@ -906,9 +907,9 @@ func TestAuthorizationSuccess(t *testing.T) { fw := newServerTest() defer fw.testHTTPServer.Close() - fw.fakeAuth.authenticateFunc = func(req *http.Request) (user.Info, bool, error) { + fw.fakeAuth.authenticateFunc = func(req *http.Request) (*authenticator.Response, bool, error) { calledAuthenticate = true - return expectedUser, true, nil + return &authenticator.Response{User: expectedUser}, true, nil } fw.fakeAuth.attributesFunc = func(u user.Info, req *http.Request) authorizer.Attributes { calledAttributes = true diff --git a/pkg/registry/authentication/tokenreview/storage.go b/pkg/registry/authentication/tokenreview/storage.go index cfd7f8ec2c..3150b2afd1 100644 --- a/pkg/registry/authentication/tokenreview/storage.go +++ b/pkg/registry/authentication/tokenreview/storage.go @@ -68,19 +68,23 @@ func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation fakeReq := &http.Request{Header: http.Header{}} fakeReq.Header.Add("Authorization", "Bearer "+tokenReview.Spec.Token) - tokenUser, ok, err := r.tokenAuthenticator.AuthenticateRequest(fakeReq) + resp, ok, err := r.tokenAuthenticator.AuthenticateRequest(fakeReq) tokenReview.Status.Authenticated = ok if err != nil { tokenReview.Status.Error = err.Error() } - if tokenUser != nil { + + // TODO(mikedanese): verify the response audience matches one of apiAuds if + // non-empty + + if resp != nil && resp.User != nil { tokenReview.Status.User = authentication.UserInfo{ - Username: tokenUser.GetName(), - UID: tokenUser.GetUID(), - Groups: tokenUser.GetGroups(), + Username: resp.User.GetName(), + UID: resp.User.GetUID(), + Groups: resp.User.GetGroups(), Extra: map[string]authentication.ExtraValue{}, } - for k, v := range tokenUser.GetExtra() { + for k, v := range resp.User.GetExtra() { tokenReview.Status.User.Extra[k] = authentication.ExtraValue(v) } } diff --git a/pkg/serviceaccount/claims.go b/pkg/serviceaccount/claims.go index 070418ffc8..7e36d39cc2 100644 --- a/pkg/serviceaccount/claims.go +++ b/pkg/serviceaccount/claims.go @@ -22,10 +22,10 @@ import ( "time" "github.com/golang/glog" + "gopkg.in/square/go-jose.v2/jwt" + apiserverserviceaccount "k8s.io/apiserver/pkg/authentication/serviceaccount" "k8s.io/kubernetes/pkg/apis/core" - - "gopkg.in/square/go-jose.v2/jwt" ) // time.Now stubbed out to allow testing diff --git a/pkg/serviceaccount/claims_test.go b/pkg/serviceaccount/claims_test.go index aec036f8d6..91ed25ed0d 100644 --- a/pkg/serviceaccount/claims_test.go +++ b/pkg/serviceaccount/claims_test.go @@ -22,10 +22,10 @@ import ( "testing" "time" + "gopkg.in/square/go-jose.v2/jwt" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/apis/core" - - "gopkg.in/square/go-jose.v2/jwt" ) func init() { diff --git a/pkg/serviceaccount/jwt.go b/pkg/serviceaccount/jwt.go index 76deae2f34..23c8934fbf 100644 --- a/pkg/serviceaccount/jwt.go +++ b/pkg/serviceaccount/jwt.go @@ -17,6 +17,7 @@ limitations under the License. package serviceaccount import ( + "context" "crypto/ecdsa" "crypto/elliptic" "crypto/rsa" @@ -25,13 +26,12 @@ import ( "fmt" "strings" + jose "gopkg.in/square/go-jose.v2" + "gopkg.in/square/go-jose.v2/jwt" + "k8s.io/api/core/v1" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apiserver/pkg/authentication/authenticator" - "k8s.io/apiserver/pkg/authentication/user" - - jose "gopkg.in/square/go-jose.v2" - "gopkg.in/square/go-jose.v2/jwt" ) // ServiceAccountTokenGetter defines functions to retrieve a named service account and secret @@ -140,7 +140,7 @@ type Validator interface { NewPrivateClaims() interface{} } -func (j *jwtTokenAuthenticator) AuthenticateToken(tokenData string) (user.Info, bool, error) { +func (j *jwtTokenAuthenticator) AuthenticateToken(ctx context.Context, tokenData string) (*authenticator.Response, bool, error) { if !j.hasCorrectIssuer(tokenData) { return nil, false, nil } @@ -177,7 +177,7 @@ func (j *jwtTokenAuthenticator) AuthenticateToken(tokenData string) (user.Info, return nil, false, err } - return sa.UserInfo(), true, nil + return &authenticator.Response{User: sa.UserInfo()}, true, nil } // hasCorrectIssuer returns true if tokenData is a valid JWT in compact diff --git a/pkg/serviceaccount/jwt_test.go b/pkg/serviceaccount/jwt_test.go index 4f7d82e288..61cca23e12 100644 --- a/pkg/serviceaccount/jwt_test.go +++ b/pkg/serviceaccount/jwt_test.go @@ -17,6 +17,7 @@ limitations under the License. package serviceaccount_test import ( + "context" "reflect" "testing" @@ -278,12 +279,12 @@ func TestTokenGenerateAndValidate(t *testing.T) { authenticator := serviceaccount.JWTTokenAuthenticator(serviceaccount.LegacyIssuer, tc.Keys, serviceaccount.NewLegacyValidator(tc.Client != nil, getter)) // An invalid, non-JWT token should always fail - if _, ok, err := authenticator.AuthenticateToken("invalid token"); err != nil || ok { + if _, ok, err := authenticator.AuthenticateToken(context.Background(), "invalid token"); err != nil || ok { t.Errorf("%s: Expected err=nil, ok=false for non-JWT token", k) continue } - user, ok, err := authenticator.AuthenticateToken(tc.Token) + resp, ok, err := authenticator.AuthenticateToken(context.Background(), tc.Token) if (err != nil) != tc.ExpectedErr { t.Errorf("%s: Expected error=%v, got %v", k, tc.ExpectedErr, err) continue @@ -298,16 +299,16 @@ func TestTokenGenerateAndValidate(t *testing.T) { continue } - if user.GetName() != tc.ExpectedUserName { - t.Errorf("%s: Expected username=%v, got %v", k, tc.ExpectedUserName, user.GetName()) + if resp.User.GetName() != tc.ExpectedUserName { + t.Errorf("%s: Expected username=%v, got %v", k, tc.ExpectedUserName, resp.User.GetName()) continue } - if user.GetUID() != tc.ExpectedUserUID { - t.Errorf("%s: Expected userUID=%v, got %v", k, tc.ExpectedUserUID, user.GetUID()) + if resp.User.GetUID() != tc.ExpectedUserUID { + t.Errorf("%s: Expected userUID=%v, got %v", k, tc.ExpectedUserUID, resp.User.GetUID()) continue } - if !reflect.DeepEqual(user.GetGroups(), tc.ExpectedGroups) { - t.Errorf("%s: Expected groups=%v, got %v", k, tc.ExpectedGroups, user.GetGroups()) + if !reflect.DeepEqual(resp.User.GetGroups(), tc.ExpectedGroups) { + t.Errorf("%s: Expected groups=%v, got %v", k, tc.ExpectedGroups, resp.User.GetGroups()) continue } } diff --git a/pkg/serviceaccount/legacy.go b/pkg/serviceaccount/legacy.go index 79ca8f1b85..4d0a32c2cd 100644 --- a/pkg/serviceaccount/legacy.go +++ b/pkg/serviceaccount/legacy.go @@ -21,11 +21,11 @@ import ( "errors" "fmt" - "k8s.io/api/core/v1" - apiserverserviceaccount "k8s.io/apiserver/pkg/authentication/serviceaccount" - "github.com/golang/glog" "gopkg.in/square/go-jose.v2/jwt" + + "k8s.io/api/core/v1" + apiserverserviceaccount "k8s.io/apiserver/pkg/authentication/serviceaccount" ) func LegacyClaims(serviceAccount v1.ServiceAccount, secret v1.Secret) (*jwt.Claims, interface{}) { diff --git a/plugin/pkg/auth/authenticator/token/bootstrap/BUILD b/plugin/pkg/auth/authenticator/token/bootstrap/BUILD index 917ed1192d..5ef48a9f56 100644 --- a/plugin/pkg/auth/authenticator/token/bootstrap/BUILD +++ b/plugin/pkg/auth/authenticator/token/bootstrap/BUILD @@ -30,6 +30,7 @@ go_library( "//pkg/client/listers/core/internalversion:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library", "//staging/src/k8s.io/cluster-bootstrap/token/api:go_default_library", "//staging/src/k8s.io/cluster-bootstrap/token/util:go_default_library", diff --git a/plugin/pkg/auth/authenticator/token/bootstrap/bootstrap.go b/plugin/pkg/auth/authenticator/token/bootstrap/bootstrap.go index 5f6cad1670..163d758c45 100644 --- a/plugin/pkg/auth/authenticator/token/bootstrap/bootstrap.go +++ b/plugin/pkg/auth/authenticator/token/bootstrap/bootstrap.go @@ -20,6 +20,7 @@ Package bootstrap provides a token authenticator for TLS bootstrap secrets. package bootstrap import ( + "context" "crypto/subtle" "fmt" "regexp" @@ -30,6 +31,7 @@ import ( "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authentication/user" bootstrapapi "k8s.io/cluster-bootstrap/token/api" bootstraputil "k8s.io/cluster-bootstrap/token/util" @@ -89,7 +91,7 @@ func tokenErrorf(s *api.Secret, format string, i ...interface{}) { // // ( token-id ).( token-secret ) // -func (t *TokenAuthenticator) AuthenticateToken(token string) (user.Info, bool, error) { +func (t *TokenAuthenticator) AuthenticateToken(ctx context.Context, token string) (*authenticator.Response, bool, error) { tokenID, tokenSecret, err := parseToken(token) if err != nil { // Token isn't of the correct form, ignore it. @@ -144,9 +146,11 @@ func (t *TokenAuthenticator) AuthenticateToken(token string) (user.Info, bool, e return nil, false, nil } - return &user.DefaultInfo{ - Name: bootstrapapi.BootstrapUserPrefix + string(id), - Groups: groups, + return &authenticator.Response{ + User: &user.DefaultInfo{ + Name: bootstrapapi.BootstrapUserPrefix + string(id), + Groups: groups, + }, }, true, nil } diff --git a/plugin/pkg/auth/authenticator/token/bootstrap/bootstrap_test.go b/plugin/pkg/auth/authenticator/token/bootstrap/bootstrap_test.go index efd345e4c8..ae408e8a9d 100644 --- a/plugin/pkg/auth/authenticator/token/bootstrap/bootstrap_test.go +++ b/plugin/pkg/auth/authenticator/token/bootstrap/bootstrap_test.go @@ -17,6 +17,7 @@ limitations under the License. package bootstrap import ( + "context" "reflect" "testing" @@ -262,7 +263,7 @@ func TestTokenAuthenticator(t *testing.T) { for _, test := range tests { func() { a := NewTokenAuthenticator(&lister{test.secrets}) - u, found, err := a.AuthenticateToken(test.token) + resp, found, err := a.AuthenticateToken(context.Background(), test.token) if err != nil { t.Errorf("test %q returned an error: %v", test.name, err) return @@ -280,8 +281,7 @@ func TestTokenAuthenticator(t *testing.T) { return } - gotUser := u.(*user.DefaultInfo) - + gotUser := resp.User.(*user.DefaultInfo) if !reflect.DeepEqual(gotUser, test.wantUser) { t.Errorf("test %q want user=%#v, got=%#v", test.name, test.wantUser, gotUser) } diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/group/authenticated_group_adder.go b/staging/src/k8s.io/apiserver/pkg/authentication/group/authenticated_group_adder.go index 9f0453b15f..5ac6b2ddf9 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/group/authenticated_group_adder.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/group/authenticated_group_adder.go @@ -36,25 +36,26 @@ func NewAuthenticatedGroupAdder(auth authenticator.Request) authenticator.Reques return &AuthenticatedGroupAdder{auth} } -func (g *AuthenticatedGroupAdder) AuthenticateRequest(req *http.Request) (user.Info, bool, error) { - u, ok, err := g.Authenticator.AuthenticateRequest(req) +func (g *AuthenticatedGroupAdder) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) { + r, ok, err := g.Authenticator.AuthenticateRequest(req) if err != nil || !ok { return nil, ok, err } - if u.GetName() == user.Anonymous { - return u, true, nil + if r.User.GetName() == user.Anonymous { + return r, true, nil } - for _, group := range u.GetGroups() { + for _, group := range r.User.GetGroups() { if group == user.AllAuthenticated || group == user.AllUnauthenticated { - return u, true, nil + return r, true, nil } } - return &user.DefaultInfo{ - Name: u.GetName(), - UID: u.GetUID(), - Groups: append(u.GetGroups(), user.AllAuthenticated), - Extra: u.GetExtra(), - }, true, nil + r.User = &user.DefaultInfo{ + Name: r.User.GetName(), + UID: r.User.GetUID(), + Groups: append(r.User.GetGroups(), user.AllAuthenticated), + Extra: r.User.GetExtra(), + } + return r, true, nil } diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/group/group_adder.go b/staging/src/k8s.io/apiserver/pkg/authentication/group/group_adder.go index 1f71429b4e..3079dad625 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/group/group_adder.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/group/group_adder.go @@ -36,15 +36,16 @@ func NewGroupAdder(auth authenticator.Request, groups []string) authenticator.Re return &GroupAdder{auth, groups} } -func (g *GroupAdder) AuthenticateRequest(req *http.Request) (user.Info, bool, error) { - u, ok, err := g.Authenticator.AuthenticateRequest(req) +func (g *GroupAdder) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) { + r, ok, err := g.Authenticator.AuthenticateRequest(req) if err != nil || !ok { return nil, ok, err } - return &user.DefaultInfo{ - Name: u.GetName(), - UID: u.GetUID(), - Groups: append(u.GetGroups(), g.Groups...), - Extra: u.GetExtra(), - }, true, nil + r.User = &user.DefaultInfo{ + Name: r.User.GetName(), + UID: r.User.GetUID(), + Groups: append(r.User.GetGroups(), g.Groups...), + Extra: r.User.GetExtra(), + } + return r, true, nil } diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/group/group_adder_test.go b/staging/src/k8s.io/apiserver/pkg/authentication/group/group_adder_test.go index da16c154a7..b84f07b903 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/group/group_adder_test.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/group/group_adder_test.go @@ -28,16 +28,16 @@ import ( func TestGroupAdder(t *testing.T) { adder := authenticator.Request( NewGroupAdder( - authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) { - return &user.DefaultInfo{Name: "user", Groups: []string{"original"}}, true, nil + authenticator.RequestFunc(func(req *http.Request) (*authenticator.Response, bool, error) { + return &authenticator.Response{User: &user.DefaultInfo{Name: "user", Groups: []string{"original"}}}, true, nil }), []string{"added"}, ), ) - user, _, _ := adder.AuthenticateRequest(nil) - if !reflect.DeepEqual(user.GetGroups(), []string{"original", "added"}) { - t.Errorf("Expected original,added groups, got %#v", user.GetGroups()) + r, _, _ := adder.AuthenticateRequest(nil) + if want := []string{"original", "added"}; !reflect.DeepEqual(r.User.GetGroups(), want) { + t.Errorf("Unexpected groups\ngot:\t%#v\nwant:\t%#v", r.User.GetGroups(), want) } } @@ -96,15 +96,15 @@ func TestAuthenticatedGroupAdder(t *testing.T) { for _, test := range tests { adder := authenticator.Request( NewAuthenticatedGroupAdder( - authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) { - return test.inputUser, true, nil + authenticator.RequestFunc(func(req *http.Request) (*authenticator.Response, bool, error) { + return &authenticator.Response{User: test.inputUser}, true, nil }), ), ) - user, _, _ := adder.AuthenticateRequest(nil) - if !reflect.DeepEqual(user, test.expectedUser) { - t.Errorf("got %#v", user) + r, _, _ := adder.AuthenticateRequest(nil) + if !reflect.DeepEqual(r.User, test.expectedUser) { + t.Errorf("Unexpected user\ngot:\t%#v\nwant:\t%#v", r.User, test.expectedUser) } } diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/group/token_group_adder.go b/staging/src/k8s.io/apiserver/pkg/authentication/group/token_group_adder.go index 4f60d522f7..0ed5ee5596 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/group/token_group_adder.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/group/token_group_adder.go @@ -17,6 +17,8 @@ limitations under the License. package group import ( + "context" + "k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authentication/user" ) @@ -34,15 +36,16 @@ func NewTokenGroupAdder(auth authenticator.Token, groups []string) authenticator return &TokenGroupAdder{auth, groups} } -func (g *TokenGroupAdder) AuthenticateToken(token string) (user.Info, bool, error) { - u, ok, err := g.Authenticator.AuthenticateToken(token) +func (g *TokenGroupAdder) AuthenticateToken(ctx context.Context, token string) (*authenticator.Response, bool, error) { + r, ok, err := g.Authenticator.AuthenticateToken(ctx, token) if err != nil || !ok { return nil, ok, err } - return &user.DefaultInfo{ - Name: u.GetName(), - UID: u.GetUID(), - Groups: append(u.GetGroups(), g.Groups...), - Extra: u.GetExtra(), - }, true, nil + r.User = &user.DefaultInfo{ + Name: r.User.GetName(), + UID: r.User.GetUID(), + Groups: append(r.User.GetGroups(), g.Groups...), + Extra: r.User.GetExtra(), + } + return r, true, nil } diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/group/token_group_adder_test.go b/staging/src/k8s.io/apiserver/pkg/authentication/group/token_group_adder_test.go index cb5a0a65ef..e9565a21c5 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/group/token_group_adder_test.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/group/token_group_adder_test.go @@ -17,6 +17,7 @@ limitations under the License. package group import ( + "context" "reflect" "testing" @@ -27,15 +28,15 @@ import ( func TestTokenGroupAdder(t *testing.T) { adder := authenticator.Token( NewTokenGroupAdder( - authenticator.TokenFunc(func(token string) (user.Info, bool, error) { - return &user.DefaultInfo{Name: "user", Groups: []string{"original"}}, true, nil + authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { + return &authenticator.Response{User: &user.DefaultInfo{Name: "user", Groups: []string{"original"}}}, true, nil }), []string{"added"}, ), ) - user, _, _ := adder.AuthenticateToken("") - if !reflect.DeepEqual(user.GetGroups(), []string{"original", "added"}) { - t.Errorf("Expected original,added groups, got %#v", user.GetGroups()) + r, _, _ := adder.AuthenticateToken(context.Background(), "") + if !reflect.DeepEqual(r.User.GetGroups(), []string{"original", "added"}) { + t.Errorf("Expected original,added groups, got %#v", r.User.GetGroups()) } } diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/request/anonymous/anonymous.go b/staging/src/k8s.io/apiserver/pkg/authentication/request/anonymous/anonymous.go index a6d22942a3..651832fd3f 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/request/anonymous/anonymous.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/request/anonymous/anonymous.go @@ -30,7 +30,12 @@ const ( ) func NewAuthenticator() authenticator.Request { - return authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) { - return &user.DefaultInfo{Name: anonymousUser, Groups: []string{unauthenticatedGroup}}, true, nil + return authenticator.RequestFunc(func(req *http.Request) (*authenticator.Response, bool, error) { + return &authenticator.Response{ + User: &user.DefaultInfo{ + Name: anonymousUser, + Groups: []string{unauthenticatedGroup}, + }, + }, true, nil }) } diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/request/anonymous/anonymous_test.go b/staging/src/k8s.io/apiserver/pkg/authentication/request/anonymous/anonymous_test.go index 55485e2b8c..7b27ff20e1 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/request/anonymous/anonymous_test.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/request/anonymous/anonymous_test.go @@ -26,17 +26,17 @@ import ( func TestAnonymous(t *testing.T) { var a authenticator.Request = NewAuthenticator() - u, ok, err := a.AuthenticateRequest(nil) + r, ok, err := a.AuthenticateRequest(nil) if err != nil { t.Fatalf("Unexpected error %v", err) } if !ok { t.Fatalf("Unexpectedly unauthenticated") } - if u.GetName() != user.Anonymous { - t.Fatalf("Expected username %s, got %s", user.Anonymous, u.GetName()) + if r.User.GetName() != user.Anonymous { + t.Fatalf("Expected username %s, got %s", user.Anonymous, r.User.GetName()) } - if !sets.NewString(u.GetGroups()...).Equal(sets.NewString(user.AllUnauthenticated)) { - t.Fatalf("Expected group %s, got %v", user.AllUnauthenticated, u.GetGroups()) + if !sets.NewString(r.User.GetGroups()...).Equal(sets.NewString(user.AllUnauthenticated)) { + t.Fatalf("Expected group %s, got %v", user.AllUnauthenticated, r.User.GetGroups()) } } diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/request/bearertoken/BUILD b/staging/src/k8s.io/apiserver/pkg/authentication/request/bearertoken/BUILD index b88082fbbd..83f4f5dcca 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/request/bearertoken/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/authentication/request/bearertoken/BUILD @@ -21,10 +21,7 @@ go_library( srcs = ["bearertoken.go"], importmap = "k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/authentication/request/bearertoken", importpath = "k8s.io/apiserver/pkg/authentication/request/bearertoken", - deps = [ - "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library", - ], + deps = ["//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library"], ) filegroup( diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/request/bearertoken/bearertoken.go b/staging/src/k8s.io/apiserver/pkg/authentication/request/bearertoken/bearertoken.go index 5ca22f38ba..2de796b723 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/request/bearertoken/bearertoken.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/request/bearertoken/bearertoken.go @@ -22,7 +22,6 @@ import ( "strings" "k8s.io/apiserver/pkg/authentication/authenticator" - "k8s.io/apiserver/pkg/authentication/user" ) type Authenticator struct { @@ -35,7 +34,7 @@ func New(auth authenticator.Token) *Authenticator { var invalidToken = errors.New("invalid bearer token") -func (a *Authenticator) AuthenticateRequest(req *http.Request) (user.Info, bool, error) { +func (a *Authenticator) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) { auth := strings.TrimSpace(req.Header.Get("Authorization")) if auth == "" { return nil, false, nil @@ -52,7 +51,7 @@ func (a *Authenticator) AuthenticateRequest(req *http.Request) (user.Info, bool, return nil, false, nil } - user, ok, err := a.auth.AuthenticateToken(token) + resp, ok, err := a.auth.AuthenticateToken(req.Context(), token) // if we authenticated successfully, go ahead and remove the bearer token so that no one // is ever tempted to use it inside of the API server if ok { @@ -64,5 +63,5 @@ func (a *Authenticator) AuthenticateRequest(req *http.Request) (user.Info, bool, err = invalidToken } - return user, ok, err + return resp, ok, err } diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/request/bearertoken/bearertoken_test.go b/staging/src/k8s.io/apiserver/pkg/authentication/request/bearertoken/bearertoken_test.go index 7b61f4314a..b18bed9c59 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/request/bearertoken/bearertoken_test.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/request/bearertoken/bearertoken_test.go @@ -17,6 +17,7 @@ limitations under the License. package bearertoken import ( + "context" "errors" "net/http" "reflect" @@ -27,28 +28,28 @@ import ( ) func TestAuthenticateRequest(t *testing.T) { - auth := New(authenticator.TokenFunc(func(token string) (user.Info, bool, error) { + auth := New(authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { if token != "token" { t.Errorf("unexpected token: %s", token) } - return &user.DefaultInfo{Name: "user"}, true, nil + return &authenticator.Response{User: &user.DefaultInfo{Name: "user"}}, true, nil })) - user, ok, err := auth.AuthenticateRequest(&http.Request{ + resp, ok, err := auth.AuthenticateRequest(&http.Request{ Header: http.Header{"Authorization": []string{"Bearer token"}}, }) - if !ok || user == nil || err != nil { + if !ok || resp == nil || err != nil { t.Errorf("expected valid user") } } func TestAuthenticateRequestTokenInvalid(t *testing.T) { - auth := New(authenticator.TokenFunc(func(token string) (user.Info, bool, error) { + auth := New(authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { return nil, false, nil })) - user, ok, err := auth.AuthenticateRequest(&http.Request{ + resp, ok, err := auth.AuthenticateRequest(&http.Request{ Header: http.Header{"Authorization": []string{"Bearer token"}}, }) - if ok || user != nil { + if ok || resp != nil { t.Errorf("expected not authenticated user") } if err != invalidToken { @@ -58,13 +59,13 @@ func TestAuthenticateRequestTokenInvalid(t *testing.T) { func TestAuthenticateRequestTokenInvalidCustomError(t *testing.T) { customError := errors.New("custom") - auth := New(authenticator.TokenFunc(func(token string) (user.Info, bool, error) { + auth := New(authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { return nil, false, customError })) - user, ok, err := auth.AuthenticateRequest(&http.Request{ + resp, ok, err := auth.AuthenticateRequest(&http.Request{ Header: http.Header{"Authorization": []string{"Bearer token"}}, }) - if ok || user != nil { + if ok || resp != nil { t.Errorf("expected not authenticated user") } if err != customError { @@ -73,13 +74,13 @@ func TestAuthenticateRequestTokenInvalidCustomError(t *testing.T) { } func TestAuthenticateRequestTokenError(t *testing.T) { - auth := New(authenticator.TokenFunc(func(token string) (user.Info, bool, error) { + auth := New(authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { return nil, false, errors.New("error") })) - user, ok, err := auth.AuthenticateRequest(&http.Request{ + resp, ok, err := auth.AuthenticateRequest(&http.Request{ Header: http.Header{"Authorization": []string{"Bearer token"}}, }) - if ok || user != nil || err == nil { + if ok || resp != nil || err == nil { t.Errorf("expected error") } } @@ -94,7 +95,7 @@ func TestAuthenticateRequestBadValue(t *testing.T) { {Req: &http.Request{Header: http.Header{"Authorization": []string{"Bearer: token"}}}}, } for i, testCase := range testCases { - auth := New(authenticator.TokenFunc(func(token string) (user.Info, bool, error) { + auth := New(authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { t.Errorf("authentication should not have been called") return nil, false, nil })) @@ -144,8 +145,10 @@ func TestBearerToken(t *testing.T) { ExpectedAuthorizationHeaders: []string{"Bearer "}, }, "valid bearer token removing header": { - AuthorizationHeaders: []string{"Bearer 123"}, - TokenAuth: authenticator.TokenFunc(func(t string) (user.Info, bool, error) { return &user.DefaultInfo{Name: "myuser"}, true, nil }), + AuthorizationHeaders: []string{"Bearer 123"}, + TokenAuth: authenticator.TokenFunc(func(ctx context.Context, t string) (*authenticator.Response, bool, error) { + return &authenticator.Response{User: &user.DefaultInfo{Name: "myuser"}}, true, nil + }), ExpectedUserName: "myuser", ExpectedOK: true, ExpectedErr: false, @@ -153,15 +156,17 @@ func TestBearerToken(t *testing.T) { }, "invalid bearer token": { AuthorizationHeaders: []string{"Bearer 123"}, - TokenAuth: authenticator.TokenFunc(func(t string) (user.Info, bool, error) { return nil, false, nil }), + TokenAuth: authenticator.TokenFunc(func(ctx context.Context, t string) (*authenticator.Response, bool, error) { return nil, false, nil }), ExpectedUserName: "", ExpectedOK: false, ExpectedErr: true, ExpectedAuthorizationHeaders: []string{"Bearer 123"}, }, "error bearer token": { - AuthorizationHeaders: []string{"Bearer 123"}, - TokenAuth: authenticator.TokenFunc(func(t string) (user.Info, bool, error) { return nil, false, errors.New("error") }), + AuthorizationHeaders: []string{"Bearer 123"}, + TokenAuth: authenticator.TokenFunc(func(ctx context.Context, t string) (*authenticator.Response, bool, error) { + return nil, false, errors.New("error") + }), ExpectedUserName: "", ExpectedOK: false, ExpectedErr: true, @@ -176,7 +181,7 @@ func TestBearerToken(t *testing.T) { } bearerAuth := New(tc.TokenAuth) - u, ok, err := bearerAuth.AuthenticateRequest(req) + resp, ok, err := bearerAuth.AuthenticateRequest(req) if tc.ExpectedErr != (err != nil) { t.Errorf("%s: Expected err=%v, got %v", k, tc.ExpectedErr, err) continue @@ -185,8 +190,8 @@ func TestBearerToken(t *testing.T) { t.Errorf("%s: Expected ok=%v, got %v", k, tc.ExpectedOK, ok) continue } - if ok && u.GetName() != tc.ExpectedUserName { - t.Errorf("%s: Expected username=%v, got %v", k, tc.ExpectedUserName, u.GetName()) + if ok && resp.User.GetName() != tc.ExpectedUserName { + t.Errorf("%s: Expected username=%v, got %v", k, tc.ExpectedUserName, resp.User.GetName()) continue } if !reflect.DeepEqual(req.Header["Authorization"], tc.ExpectedAuthorizationHeaders) { diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/request/headerrequest/requestheader.go b/staging/src/k8s.io/apiserver/pkg/authentication/request/headerrequest/requestheader.go index 948478b80e..70af861d8b 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/request/headerrequest/requestheader.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/request/headerrequest/requestheader.go @@ -105,7 +105,7 @@ func NewSecure(clientCA string, proxyClientNames []string, nameHeaders []string, return x509request.NewVerifier(opts, headerAuthenticator, sets.NewString(proxyClientNames...)), nil } -func (a *requestHeaderAuthRequestHandler) AuthenticateRequest(req *http.Request) (user.Info, bool, error) { +func (a *requestHeaderAuthRequestHandler) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) { name := headerValue(req.Header, a.nameHeaders) if len(name) == 0 { return nil, false, nil @@ -126,10 +126,12 @@ func (a *requestHeaderAuthRequestHandler) AuthenticateRequest(req *http.Request) } } - return &user.DefaultInfo{ - Name: name, - Groups: groups, - Extra: extra, + return &authenticator.Response{ + User: &user.DefaultInfo{ + Name: name, + Groups: groups, + Extra: extra, + }, }, true, nil } diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/request/headerrequest/requestheader_test.go b/staging/src/k8s.io/apiserver/pkg/authentication/request/headerrequest/requestheader_test.go index 28876dbc43..ccccbc6ffc 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/request/headerrequest/requestheader_test.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/request/headerrequest/requestheader_test.go @@ -186,19 +186,23 @@ func TestRequestHeader(t *testing.T) { } for k, testcase := range testcases { - auth, err := New(testcase.nameHeaders, testcase.groupHeaders, testcase.extraPrefixHeaders) - if err != nil { - t.Fatal(err) - } - req := &http.Request{Header: testcase.requestHeaders} + t.Run(k, func(t *testing.T) { + auth, err := New(testcase.nameHeaders, testcase.groupHeaders, testcase.extraPrefixHeaders) + if err != nil { + t.Fatal(err) + } + req := &http.Request{Header: testcase.requestHeaders} - user, ok, _ := auth.AuthenticateRequest(req) - if testcase.expectedOk != ok { - t.Errorf("%v: expected %v, got %v", k, testcase.expectedOk, ok) - } - if e, a := testcase.expectedUser, user; !reflect.DeepEqual(e, a) { - t.Errorf("%v: expected %#v, got %#v", k, e, a) - - } + resp, ok, _ := auth.AuthenticateRequest(req) + if testcase.expectedOk != ok { + t.Errorf("%v: expected %v, got %v", k, testcase.expectedOk, ok) + } + if !ok { + return + } + if e, a := testcase.expectedUser, resp.User; !reflect.DeepEqual(e, a) { + t.Errorf("%v: expected %#v, got %#v", k, e, a) + } + }) } } diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/request/union/BUILD b/staging/src/k8s.io/apiserver/pkg/authentication/request/union/BUILD index 75e741dec7..86f585b52e 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/request/union/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/authentication/request/union/BUILD @@ -10,7 +10,10 @@ go_test( name = "go_default_test", srcs = ["unionauth_test.go"], embed = [":go_default_library"], - deps = ["//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library"], + deps = [ + "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library", + ], ) go_library( @@ -21,7 +24,6 @@ go_library( deps = [ "//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library", ], ) diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/request/union/union.go b/staging/src/k8s.io/apiserver/pkg/authentication/request/union/union.go index 1613940981..512063beea 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/request/union/union.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/request/union/union.go @@ -21,7 +21,6 @@ import ( utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apiserver/pkg/authentication/authenticator" - "k8s.io/apiserver/pkg/authentication/user" ) // unionAuthRequestHandler authenticates requests using a chain of authenticator.Requests @@ -51,20 +50,20 @@ func NewFailOnError(authRequestHandlers ...authenticator.Request) authenticator. } // AuthenticateRequest authenticates the request using a chain of authenticator.Request objects. -func (authHandler *unionAuthRequestHandler) AuthenticateRequest(req *http.Request) (user.Info, bool, error) { +func (authHandler *unionAuthRequestHandler) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) { var errlist []error for _, currAuthRequestHandler := range authHandler.Handlers { - info, ok, err := currAuthRequestHandler.AuthenticateRequest(req) + resp, ok, err := currAuthRequestHandler.AuthenticateRequest(req) if err != nil { if authHandler.FailOnError { - return info, ok, err + return resp, ok, err } errlist = append(errlist, err) continue } if ok { - return info, ok, err + return resp, ok, err } } diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/request/union/unionauth_test.go b/staging/src/k8s.io/apiserver/pkg/authentication/request/union/unionauth_test.go index 0d3f1a7cf2..38847b6e9a 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/request/union/unionauth_test.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/request/union/unionauth_test.go @@ -23,6 +23,7 @@ import ( "strings" "testing" + "k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authentication/user" ) @@ -37,8 +38,8 @@ var ( user2 = &user.DefaultInfo{Name: "elegant_sheep", UID: "bravo"} ) -func (mock *mockAuthRequestHandler) AuthenticateRequest(req *http.Request) (user.Info, bool, error) { - return mock.returnUser, mock.isAuthenticated, mock.err +func (mock *mockAuthRequestHandler) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) { + return &authenticator.Response{User: mock.returnUser}, mock.isAuthenticated, mock.err } func TestAuthenticateRequestSecondPasses(t *testing.T) { @@ -47,15 +48,15 @@ func TestAuthenticateRequestSecondPasses(t *testing.T) { authRequestHandler := New(handler1, handler2) req, _ := http.NewRequest("GET", "http://example.org", nil) - authenticatedUser, isAuthenticated, err := authRequestHandler.AuthenticateRequest(req) + resp, isAuthenticated, err := authRequestHandler.AuthenticateRequest(req) if err != nil { t.Errorf("Unexpected error: %v", err) } if !isAuthenticated { t.Errorf("Unexpectedly unauthenticated: %v", isAuthenticated) } - if !reflect.DeepEqual(user2, authenticatedUser) { - t.Errorf("Expected %v, got %v", user2, authenticatedUser) + if !reflect.DeepEqual(user2, resp.User) { + t.Errorf("Expected %v, got %v", user2, resp.User) } } @@ -65,15 +66,15 @@ func TestAuthenticateRequestFirstPasses(t *testing.T) { authRequestHandler := New(handler1, handler2) req, _ := http.NewRequest("GET", "http://example.org", nil) - authenticatedUser, isAuthenticated, err := authRequestHandler.AuthenticateRequest(req) + resp, isAuthenticated, err := authRequestHandler.AuthenticateRequest(req) if err != nil { t.Errorf("Unexpected error: %v", err) } if !isAuthenticated { t.Errorf("Unexpectedly unauthenticated: %v", isAuthenticated) } - if !reflect.DeepEqual(user1, authenticatedUser) { - t.Errorf("Expected %v, got %v", user1, authenticatedUser) + if !reflect.DeepEqual(user1, resp.User) { + t.Errorf("Expected %v, got %v", user2, resp.User) } } @@ -96,15 +97,15 @@ func TestAuthenticateRequestNoAuthenticators(t *testing.T) { authRequestHandler := New() req, _ := http.NewRequest("GET", "http://example.org", nil) - authenticatedUser, isAuthenticated, err := authRequestHandler.AuthenticateRequest(req) + resp, isAuthenticated, err := authRequestHandler.AuthenticateRequest(req) if err != nil { t.Errorf("Unexpected error: %v", err) } if isAuthenticated { t.Errorf("Unexpectedly authenticated: %v", isAuthenticated) } - if authenticatedUser != nil { - t.Errorf("Unexpected authenticatedUser: %v", authenticatedUser) + if resp != nil { + t.Errorf("Unexpected authenticatedUser: %v", resp) } } diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/request/websocket/BUILD b/staging/src/k8s.io/apiserver/pkg/authentication/request/websocket/BUILD index dbfbb8337e..53b8e0f463 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/request/websocket/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/authentication/request/websocket/BUILD @@ -13,7 +13,6 @@ go_library( importpath = "k8s.io/apiserver/pkg/authentication/request/websocket", deps = [ "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/wsstream:go_default_library", ], ) diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/request/websocket/protocol.go b/staging/src/k8s.io/apiserver/pkg/authentication/request/websocket/protocol.go index 4a30bb6359..11afa84cbd 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/request/websocket/protocol.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/request/websocket/protocol.go @@ -25,7 +25,6 @@ import ( "unicode/utf8" "k8s.io/apiserver/pkg/authentication/authenticator" - "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/util/wsstream" ) @@ -46,7 +45,7 @@ func NewProtocolAuthenticator(auth authenticator.Token) *ProtocolAuthenticator { return &ProtocolAuthenticator{auth} } -func (a *ProtocolAuthenticator) AuthenticateRequest(req *http.Request) (user.Info, bool, error) { +func (a *ProtocolAuthenticator) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) { // Only accept websocket connections if !wsstream.IsWebSocketRequest(req) { return nil, false, nil @@ -91,7 +90,7 @@ func (a *ProtocolAuthenticator) AuthenticateRequest(req *http.Request) (user.Inf return nil, false, nil } - user, ok, err := a.auth.AuthenticateToken(token) + resp, ok, err := a.auth.AuthenticateToken(req.Context(), token) // on success, remove the protocol with the token if ok { @@ -105,5 +104,5 @@ func (a *ProtocolAuthenticator) AuthenticateRequest(req *http.Request) (user.Inf err = errInvalidToken } - return user, ok, err + return resp, ok, err } diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/request/websocket/protocol_test.go b/staging/src/k8s.io/apiserver/pkg/authentication/request/websocket/protocol_test.go index 62800a40d9..9428d8ec81 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/request/websocket/protocol_test.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/request/websocket/protocol_test.go @@ -17,6 +17,7 @@ limitations under the License. package websocket import ( + "context" "errors" "net/http" "reflect" @@ -27,36 +28,36 @@ import ( ) func TestAuthenticateRequest(t *testing.T) { - auth := NewProtocolAuthenticator(authenticator.TokenFunc(func(token string) (user.Info, bool, error) { + auth := NewProtocolAuthenticator(authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { if token != "token" { t.Errorf("unexpected token: %s", token) } - return &user.DefaultInfo{Name: "user"}, true, nil + return &authenticator.Response{User: &user.DefaultInfo{Name: "user"}}, true, nil })) - user, ok, err := auth.AuthenticateRequest(&http.Request{ + resp, ok, err := auth.AuthenticateRequest(&http.Request{ Header: http.Header{ "Connection": []string{"upgrade"}, "Upgrade": []string{"websocket"}, "Sec-Websocket-Protocol": []string{"base64url.bearer.authorization.k8s.io.dG9rZW4,dummy"}, }, }) - if !ok || user == nil || err != nil { + if !ok || resp == nil || err != nil { t.Errorf("expected valid user") } } func TestAuthenticateRequestTokenInvalid(t *testing.T) { - auth := NewProtocolAuthenticator(authenticator.TokenFunc(func(token string) (user.Info, bool, error) { + auth := NewProtocolAuthenticator(authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { return nil, false, nil })) - user, ok, err := auth.AuthenticateRequest(&http.Request{ + resp, ok, err := auth.AuthenticateRequest(&http.Request{ Header: http.Header{ "Connection": []string{"upgrade"}, "Upgrade": []string{"websocket"}, "Sec-Websocket-Protocol": []string{"base64url.bearer.authorization.k8s.io.dG9rZW4,dummy"}, }, }) - if ok || user != nil { + if ok || resp != nil { t.Errorf("expected not authenticated user") } if err != errInvalidToken { @@ -66,17 +67,17 @@ func TestAuthenticateRequestTokenInvalid(t *testing.T) { func TestAuthenticateRequestTokenInvalidCustomError(t *testing.T) { customError := errors.New("custom") - auth := NewProtocolAuthenticator(authenticator.TokenFunc(func(token string) (user.Info, bool, error) { + auth := NewProtocolAuthenticator(authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { return nil, false, customError })) - user, ok, err := auth.AuthenticateRequest(&http.Request{ + resp, ok, err := auth.AuthenticateRequest(&http.Request{ Header: http.Header{ "Connection": []string{"upgrade"}, "Upgrade": []string{"websocket"}, "Sec-Websocket-Protocol": []string{"base64url.bearer.authorization.k8s.io.dG9rZW4,dummy"}, }, }) - if ok || user != nil { + if ok || resp != nil { t.Errorf("expected not authenticated user") } if err != customError { @@ -85,17 +86,17 @@ func TestAuthenticateRequestTokenInvalidCustomError(t *testing.T) { } func TestAuthenticateRequestTokenError(t *testing.T) { - auth := NewProtocolAuthenticator(authenticator.TokenFunc(func(token string) (user.Info, bool, error) { + auth := NewProtocolAuthenticator(authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { return nil, false, errors.New("error") })) - user, ok, err := auth.AuthenticateRequest(&http.Request{ + resp, ok, err := auth.AuthenticateRequest(&http.Request{ Header: http.Header{ "Connection": []string{"upgrade"}, "Upgrade": []string{"websocket"}, "Sec-Websocket-Protocol": []string{"base64url.bearer.authorization.k8s.io.dG9rZW4,dummy"}, }, }) - if ok || user != nil || err == nil { + if ok || resp != nil || err == nil { t.Errorf("expected error") } } @@ -117,12 +118,12 @@ func TestAuthenticateRequestBadValue(t *testing.T) { }, } for i, testCase := range testCases { - auth := NewProtocolAuthenticator(authenticator.TokenFunc(func(token string) (user.Info, bool, error) { + auth := NewProtocolAuthenticator(authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { t.Errorf("authentication should not have been called") return nil, false, nil })) - user, ok, err := auth.AuthenticateRequest(testCase.Req) - if ok || user != nil || err != nil { + resp, ok, err := auth.AuthenticateRequest(testCase.Req) + if ok || resp != nil || err != nil { t.Errorf("%d: expected not authenticated (no token)", i) } } @@ -167,8 +168,10 @@ func TestBearerToken(t *testing.T) { ExpectedProtocolHeaders: []string{"base64url.bearer.authorization.k8s.io."}, }, "valid bearer token removing header": { - ProtocolHeaders: []string{"base64url.bearer.authorization.k8s.io.dG9rZW4", "dummy, dummy2"}, - TokenAuth: authenticator.TokenFunc(func(t string) (user.Info, bool, error) { return &user.DefaultInfo{Name: "myuser"}, true, nil }), + ProtocolHeaders: []string{"base64url.bearer.authorization.k8s.io.dG9rZW4", "dummy, dummy2"}, + TokenAuth: authenticator.TokenFunc(func(ctx context.Context, t string) (*authenticator.Response, bool, error) { + return &authenticator.Response{User: &user.DefaultInfo{Name: "myuser"}}, true, nil + }), ExpectedUserName: "myuser", ExpectedOK: true, ExpectedErr: false, @@ -176,15 +179,17 @@ func TestBearerToken(t *testing.T) { }, "invalid bearer token": { ProtocolHeaders: []string{"base64url.bearer.authorization.k8s.io.dG9rZW4,dummy"}, - TokenAuth: authenticator.TokenFunc(func(t string) (user.Info, bool, error) { return nil, false, nil }), + TokenAuth: authenticator.TokenFunc(func(ctx context.Context, t string) (*authenticator.Response, bool, error) { return nil, false, nil }), ExpectedUserName: "", ExpectedOK: false, ExpectedErr: true, ExpectedProtocolHeaders: []string{"base64url.bearer.authorization.k8s.io.dG9rZW4,dummy"}, }, "error bearer token": { - ProtocolHeaders: []string{"base64url.bearer.authorization.k8s.io.dG9rZW4,dummy"}, - TokenAuth: authenticator.TokenFunc(func(t string) (user.Info, bool, error) { return nil, false, errors.New("error") }), + ProtocolHeaders: []string{"base64url.bearer.authorization.k8s.io.dG9rZW4,dummy"}, + TokenAuth: authenticator.TokenFunc(func(ctx context.Context, t string) (*authenticator.Response, bool, error) { + return nil, false, errors.New("error") + }), ExpectedUserName: "", ExpectedOK: false, ExpectedErr: true, @@ -201,7 +206,7 @@ func TestBearerToken(t *testing.T) { } bearerAuth := NewProtocolAuthenticator(tc.TokenAuth) - u, ok, err := bearerAuth.AuthenticateRequest(req) + resp, ok, err := bearerAuth.AuthenticateRequest(req) if tc.ExpectedErr != (err != nil) { t.Errorf("%s: Expected err=%v, got %v", k, tc.ExpectedErr, err) continue @@ -210,8 +215,8 @@ func TestBearerToken(t *testing.T) { t.Errorf("%s: Expected ok=%v, got %v", k, tc.ExpectedOK, ok) continue } - if ok && u.GetName() != tc.ExpectedUserName { - t.Errorf("%s: Expected username=%v, got %v", k, tc.ExpectedUserName, u.GetName()) + if ok && resp.User.GetName() != tc.ExpectedUserName { + t.Errorf("%s: Expected username=%v, got %v", k, tc.ExpectedUserName, resp.User.GetName()) continue } if !reflect.DeepEqual(req.Header["Sec-Websocket-Protocol"], tc.ExpectedProtocolHeaders) { diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/request/x509/x509.go b/staging/src/k8s.io/apiserver/pkg/authentication/request/x509/x509.go index 5c4e5a56b0..bc875adacf 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/request/x509/x509.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/request/x509/x509.go @@ -59,14 +59,14 @@ func init() { // UserConversion defines an interface for extracting user info from a client certificate chain type UserConversion interface { - User(chain []*x509.Certificate) (user.Info, bool, error) + User(chain []*x509.Certificate) (*authenticator.Response, bool, error) } // UserConversionFunc is a function that implements the UserConversion interface. -type UserConversionFunc func(chain []*x509.Certificate) (user.Info, bool, error) +type UserConversionFunc func(chain []*x509.Certificate) (*authenticator.Response, bool, error) // User implements x509.UserConversion -func (f UserConversionFunc) User(chain []*x509.Certificate) (user.Info, bool, error) { +func (f UserConversionFunc) User(chain []*x509.Certificate) (*authenticator.Response, bool, error) { return f(chain) } @@ -83,7 +83,7 @@ func New(opts x509.VerifyOptions, user UserConversion) *Authenticator { } // AuthenticateRequest authenticates the request using presented client certificates -func (a *Authenticator) AuthenticateRequest(req *http.Request) (user.Info, bool, error) { +func (a *Authenticator) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) { if req.TLS == nil || len(req.TLS.PeerCertificates) == 0 { return nil, false, nil } @@ -135,7 +135,7 @@ func NewVerifier(opts x509.VerifyOptions, auth authenticator.Request, allowedCom } // AuthenticateRequest verifies the presented client certificate, then delegates to the wrapped auth -func (a *Verifier) AuthenticateRequest(req *http.Request) (user.Info, bool, error) { +func (a *Verifier) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) { if req.TLS == nil || len(req.TLS.PeerCertificates) == 0 { return nil, false, nil } @@ -179,12 +179,14 @@ func DefaultVerifyOptions() x509.VerifyOptions { } // CommonNameUserConversion builds user info from a certificate chain using the subject's CommonName -var CommonNameUserConversion = UserConversionFunc(func(chain []*x509.Certificate) (user.Info, bool, error) { +var CommonNameUserConversion = UserConversionFunc(func(chain []*x509.Certificate) (*authenticator.Response, bool, error) { if len(chain[0].Subject.CommonName) == 0 { return nil, false, nil } - return &user.DefaultInfo{ - Name: chain[0].Subject.CommonName, - Groups: chain[0].Subject.Organization, + return &authenticator.Response{ + User: &user.DefaultInfo{ + Name: chain[0].Subject.CommonName, + Groups: chain[0].Subject.Organization, + }, }, true, nil }) diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/request/x509/x509_test.go b/staging/src/k8s.io/apiserver/pkg/authentication/request/x509/x509_test.go index 95a6da084f..2628d532f2 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/request/x509/x509_test.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/request/x509/x509_test.go @@ -590,7 +590,7 @@ func TestX509(t *testing.T) { "custom conversion error": { Opts: getDefaultVerifyOptions(t), Certs: getCerts(t, clientCNCert), - User: UserConversionFunc(func(chain []*x509.Certificate) (user.Info, bool, error) { + User: UserConversionFunc(func(chain []*x509.Certificate) (*authenticator.Response, bool, error) { return nil, false, errors.New("custom error") }), @@ -600,8 +600,8 @@ func TestX509(t *testing.T) { "custom conversion success": { Opts: getDefaultVerifyOptions(t), Certs: getCerts(t, clientCNCert), - User: UserConversionFunc(func(chain []*x509.Certificate) (user.Info, bool, error) { - return &user.DefaultInfo{Name: "custom"}, true, nil + User: UserConversionFunc(func(chain []*x509.Certificate) (*authenticator.Response, bool, error) { + return &authenticator.Response{User: &user.DefaultInfo{Name: "custom"}}, true, nil }), ExpectUserName: "custom", @@ -659,7 +659,7 @@ func TestX509(t *testing.T) { a := New(testCase.Opts, testCase.User) - user, ok, err := a.AuthenticateRequest(req) + resp, ok, err := a.AuthenticateRequest(req) if testCase.ExpectErr && err == nil { t.Errorf("%s: Expected error, got none", k) @@ -676,11 +676,11 @@ func TestX509(t *testing.T) { } if testCase.ExpectOK { - if testCase.ExpectUserName != user.GetName() { - t.Errorf("%s: Expected user.name=%v, got %v", k, testCase.ExpectUserName, user.GetName()) + if testCase.ExpectUserName != resp.User.GetName() { + t.Errorf("%s: Expected user.name=%v, got %v", k, testCase.ExpectUserName, resp.User.GetName()) } - groups := user.GetGroups() + groups := resp.User.GetGroups() sort.Strings(testCase.ExpectGroups) sort.Strings(groups) if !reflect.DeepEqual(testCase.ExpectGroups, groups) { @@ -807,14 +807,14 @@ func TestX509Verifier(t *testing.T) { } authCall := false - auth := authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) { + auth := authenticator.RequestFunc(func(req *http.Request) (*authenticator.Response, bool, error) { authCall = true - return &user.DefaultInfo{Name: "innerauth"}, true, nil + return &authenticator.Response{User: &user.DefaultInfo{Name: "innerauth"}}, true, nil }) a := NewVerifier(testCase.Opts, auth, testCase.AllowedCNs) - user, ok, err := a.AuthenticateRequest(req) + resp, ok, err := a.AuthenticateRequest(req) if testCase.ExpectErr && err == nil { t.Errorf("%s: Expected error, got none", k) @@ -835,8 +835,8 @@ func TestX509Verifier(t *testing.T) { t.Errorf("%s: Expected inner auth called, wasn't", k) continue } - if "innerauth" != user.GetName() { - t.Errorf("%s: Expected user.name=%v, got %v", k, "innerauth", user.GetName()) + if "innerauth" != resp.User.GetName() { + t.Errorf("%s: Expected user.name=%v, got %v", k, "innerauth", resp.User.GetName()) continue } } else { diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/BUILD b/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/BUILD index b795f531d1..66c09d4484 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/BUILD @@ -34,7 +34,6 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/util/cache:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library", "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library", ], ) diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/cache_test.go b/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/cache_test.go index d1ae1fc827..96c794583b 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/cache_test.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/cache_test.go @@ -21,10 +21,10 @@ import ( "testing" "time" - "k8s.io/apimachinery/pkg/util/clock" - "k8s.io/apiserver/pkg/authentication/user" - "github.com/pborman/uuid" + "k8s.io/apimachinery/pkg/util/clock" + "k8s.io/apiserver/pkg/authentication/authenticator" + "k8s.io/apiserver/pkg/authentication/user" ) func TestSimpleCache(t *testing.T) { @@ -71,8 +71,8 @@ func testCache(cache cache, t *testing.T) { t.Errorf("Expected null, false, got %#v, %v", result, ok) } - record1 := &cacheRecord{user: &user.DefaultInfo{Name: "bob"}} - record2 := &cacheRecord{user: &user.DefaultInfo{Name: "alice"}} + record1 := &cacheRecord{resp: &authenticator.Response{User: &user.DefaultInfo{Name: "bob"}}} + record2 := &cacheRecord{resp: &authenticator.Response{User: &user.DefaultInfo{Name: "alice"}}} // when empty, record is stored cache.set("foo", record1, time.Hour) diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/cached_token_authenticator.go b/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/cached_token_authenticator.go index d2fd28d234..40243290bc 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/cached_token_authenticator.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/cached_token_authenticator.go @@ -17,16 +17,16 @@ limitations under the License. package cache import ( + "context" "time" utilclock "k8s.io/apimachinery/pkg/util/clock" "k8s.io/apiserver/pkg/authentication/authenticator" - "k8s.io/apiserver/pkg/authentication/user" ) // cacheRecord holds the three return values of the authenticator.Token AuthenticateToken method type cacheRecord struct { - user user.Info + resp *authenticator.Response ok bool err error } @@ -64,19 +64,21 @@ func newWithClock(authenticator authenticator.Token, successTTL, failureTTL time } // AuthenticateToken implements authenticator.Token -func (a *cachedTokenAuthenticator) AuthenticateToken(token string) (user.Info, bool, error) { +func (a *cachedTokenAuthenticator) AuthenticateToken(ctx context.Context, token string) (*authenticator.Response, bool, error) { + // TODO(mikedanese): The key needs to incorporate any relevant data in the + // context. if record, ok := a.cache.get(token); ok { - return record.user, record.ok, record.err + return record.resp, record.ok, record.err } - user, ok, err := a.authenticator.AuthenticateToken(token) + resp, ok, err := a.authenticator.AuthenticateToken(ctx, token) switch { case ok && a.successTTL > 0: - a.cache.set(token, &cacheRecord{user: user, ok: ok, err: err}, a.successTTL) + a.cache.set(token, &cacheRecord{resp: resp, ok: ok, err: err}, a.successTTL) case !ok && a.failureTTL > 0: - a.cache.set(token, &cacheRecord{user: user, ok: ok, err: err}, a.failureTTL) + a.cache.set(token, &cacheRecord{resp: resp, ok: ok, err: err}, a.failureTTL) } - return user, ok, err + return resp, ok, err } diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/cached_token_authenticator_test.go b/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/cached_token_authenticator_test.go index 200d114784..eb993888e1 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/cached_token_authenticator_test.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/cached_token_authenticator_test.go @@ -17,6 +17,7 @@ limitations under the License. package cache import ( + "context" "reflect" "testing" "time" @@ -34,21 +35,21 @@ func TestCachedTokenAuthenticator(t *testing.T) { resultOk bool resultErr error ) - fakeAuth := authenticator.TokenFunc(func(token string) (user.Info, bool, error) { + fakeAuth := authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { calledWithToken = append(calledWithToken, token) - return resultUsers[token], resultOk, resultErr + return &authenticator.Response{User: resultUsers[token]}, resultOk, resultErr }) fakeClock := utilclock.NewFakeClock(time.Now()) a := newWithClock(fakeAuth, time.Minute, 0, fakeClock) calledWithToken, resultUsers, resultOk, resultErr = []string{}, nil, false, nil - a.AuthenticateToken("bad1") - a.AuthenticateToken("bad2") - a.AuthenticateToken("bad3") - a.AuthenticateToken("bad1") - a.AuthenticateToken("bad2") - a.AuthenticateToken("bad3") + a.AuthenticateToken(context.Background(), "bad1") + a.AuthenticateToken(context.Background(), "bad2") + a.AuthenticateToken(context.Background(), "bad3") + a.AuthenticateToken(context.Background(), "bad1") + a.AuthenticateToken(context.Background(), "bad2") + a.AuthenticateToken(context.Background(), "bad3") if !reflect.DeepEqual(calledWithToken, []string{"bad1", "bad2", "bad3", "bad1", "bad2", "bad3"}) { t.Errorf("Expected failing calls to bypass cache, got %v", calledWithToken) } @@ -61,13 +62,13 @@ func TestCachedTokenAuthenticator(t *testing.T) { resultUsers["usertoken3"] = &user.DefaultInfo{Name: "user3"} // populate cache - if user, ok, err := a.AuthenticateToken("usertoken1"); err != nil || !ok || user.GetName() != "user1" { + if resp, ok, err := a.AuthenticateToken(context.Background(), "usertoken1"); err != nil || !ok || resp.User.GetName() != "user1" { t.Errorf("Expected user1") } - if user, ok, err := a.AuthenticateToken("usertoken2"); err != nil || !ok || user.GetName() != "user2" { + if resp, ok, err := a.AuthenticateToken(context.Background(), "usertoken2"); err != nil || !ok || resp.User.GetName() != "user2" { t.Errorf("Expected user2") } - if user, ok, err := a.AuthenticateToken("usertoken3"); err != nil || !ok || user.GetName() != "user3" { + if resp, ok, err := a.AuthenticateToken(context.Background(), "usertoken3"); err != nil || !ok || resp.User.GetName() != "user3" { t.Errorf("Expected user3") } if !reflect.DeepEqual(calledWithToken, []string{"usertoken1", "usertoken2", "usertoken3"}) { @@ -79,13 +80,13 @@ func TestCachedTokenAuthenticator(t *testing.T) { resultUsers, resultOk, resultErr = nil, false, nil // authenticate calls still succeed and backend is not hit - if user, ok, err := a.AuthenticateToken("usertoken1"); err != nil || !ok || user.GetName() != "user1" { + if resp, ok, err := a.AuthenticateToken(context.Background(), "usertoken1"); err != nil || !ok || resp.User.GetName() != "user1" { t.Errorf("Expected user1") } - if user, ok, err := a.AuthenticateToken("usertoken2"); err != nil || !ok || user.GetName() != "user2" { + if resp, ok, err := a.AuthenticateToken(context.Background(), "usertoken2"); err != nil || !ok || resp.User.GetName() != "user2" { t.Errorf("Expected user2") } - if user, ok, err := a.AuthenticateToken("usertoken3"); err != nil || !ok || user.GetName() != "user3" { + if resp, ok, err := a.AuthenticateToken(context.Background(), "usertoken3"); err != nil || !ok || resp.User.GetName() != "user3" { t.Errorf("Expected user3") } if !reflect.DeepEqual(calledWithToken, []string{}) { @@ -96,9 +97,9 @@ func TestCachedTokenAuthenticator(t *testing.T) { fakeClock.Step(2 * time.Minute) // backend is consulted again and fails - a.AuthenticateToken("usertoken1") - a.AuthenticateToken("usertoken2") - a.AuthenticateToken("usertoken3") + a.AuthenticateToken(context.Background(), "usertoken1") + a.AuthenticateToken(context.Background(), "usertoken2") + a.AuthenticateToken(context.Background(), "usertoken3") if !reflect.DeepEqual(calledWithToken, []string{"usertoken1", "usertoken2", "usertoken3"}) { t.Errorf("Expected token calls, got %v", calledWithToken) } diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/token/tokenfile/BUILD b/staging/src/k8s.io/apiserver/pkg/authentication/token/tokenfile/BUILD index 00b19d4806..172e0fedf6 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/token/tokenfile/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/authentication/token/tokenfile/BUILD @@ -19,6 +19,7 @@ go_library( importmap = "k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/authentication/token/tokenfile", importpath = "k8s.io/apiserver/pkg/authentication/token/tokenfile", deps = [ + "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library", "//vendor/github.com/golang/glog:go_default_library", ], diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/token/tokenfile/tokenfile.go b/staging/src/k8s.io/apiserver/pkg/authentication/token/tokenfile/tokenfile.go index 57bb6c596d..4735357f9a 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/token/tokenfile/tokenfile.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/token/tokenfile/tokenfile.go @@ -17,6 +17,7 @@ limitations under the License. package tokenfile import ( + "context" "encoding/csv" "fmt" "io" @@ -24,6 +25,7 @@ import ( "strings" "github.com/golang/glog" + "k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authentication/user" ) @@ -88,10 +90,10 @@ func NewCSV(path string) (*TokenAuthenticator, error) { }, nil } -func (a *TokenAuthenticator) AuthenticateToken(value string) (user.Info, bool, error) { +func (a *TokenAuthenticator) AuthenticateToken(ctx context.Context, value string) (*authenticator.Response, bool, error) { user, ok := a.tokens[value] if !ok { return nil, false, nil } - return user, true, nil + return &authenticator.Response{User: user}, true, nil } diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/token/tokenfile/tokenfile_test.go b/staging/src/k8s.io/apiserver/pkg/authentication/token/tokenfile/tokenfile_test.go index c02d4f1b69..bbe90c9992 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/token/tokenfile/tokenfile_test.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/token/tokenfile/tokenfile_test.go @@ -17,6 +17,7 @@ limitations under the License. package tokenfile import ( + "context" "io/ioutil" "os" "reflect" @@ -85,13 +86,13 @@ token7,user7,uid7,"group1,group2",otherdata }, } for i, testCase := range testCases { - user, ok, err := auth.AuthenticateToken(testCase.Token) + resp, ok, err := auth.AuthenticateToken(context.Background(), testCase.Token) if testCase.User == nil { - if user != nil { - t.Errorf("%d: unexpected non-nil user %#v", i, user) + if resp != nil { + t.Errorf("%d: unexpected non-nil user %#v", i, resp.User) } - } else if !reflect.DeepEqual(testCase.User, user) { - t.Errorf("%d: expected user %#v, got %#v", i, testCase.User, user) + } else if !reflect.DeepEqual(testCase.User, resp.User) { + t.Errorf("%d: expected user %#v, got %#v", i, testCase.User, resp.User) } if testCase.Ok != ok { diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/token/union/BUILD b/staging/src/k8s.io/apiserver/pkg/authentication/token/union/BUILD index 46ec919e1e..ccdb9cf109 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/token/union/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/authentication/token/union/BUILD @@ -10,7 +10,10 @@ go_test( name = "go_default_test", srcs = ["unionauth_test.go"], embed = [":go_default_library"], - deps = ["//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library"], + deps = [ + "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library", + ], ) go_library( @@ -21,7 +24,6 @@ go_library( deps = [ "//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library", ], ) diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/token/union/union.go b/staging/src/k8s.io/apiserver/pkg/authentication/token/union/union.go index 7cc391bc48..80fdd89b2e 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/token/union/union.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/token/union/union.go @@ -17,9 +17,10 @@ limitations under the License. package union import ( + "context" + utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apiserver/pkg/authentication/authenticator" - "k8s.io/apiserver/pkg/authentication/user" ) // unionAuthTokenHandler authenticates tokens using a chain of authenticator.Token objects @@ -49,10 +50,10 @@ func NewFailOnError(authTokenHandlers ...authenticator.Token) authenticator.Toke } // AuthenticateToken authenticates the token using a chain of authenticator.Token objects. -func (authHandler *unionAuthTokenHandler) AuthenticateToken(token string) (user.Info, bool, error) { +func (authHandler *unionAuthTokenHandler) AuthenticateToken(ctx context.Context, token string) (*authenticator.Response, bool, error) { var errlist []error for _, currAuthRequestHandler := range authHandler.Handlers { - info, ok, err := currAuthRequestHandler.AuthenticateToken(token) + info, ok, err := currAuthRequestHandler.AuthenticateToken(ctx, token) if err != nil { if authHandler.FailOnError { return info, ok, err diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/token/union/unionauth_test.go b/staging/src/k8s.io/apiserver/pkg/authentication/token/union/unionauth_test.go index 1107c57546..6fb1b75eaa 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/token/union/unionauth_test.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/token/union/unionauth_test.go @@ -17,11 +17,13 @@ limitations under the License. package union import ( + "context" "errors" "reflect" "strings" "testing" + "k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authentication/user" ) @@ -36,8 +38,8 @@ var ( user2 = &user.DefaultInfo{Name: "elegant_sheep", UID: "bravo"} ) -func (mock *mockAuthRequestHandler) AuthenticateToken(token string) (user.Info, bool, error) { - return mock.returnUser, mock.isAuthenticated, mock.err +func (mock *mockAuthRequestHandler) AuthenticateToken(ctx context.Context, token string) (*authenticator.Response, bool, error) { + return &authenticator.Response{User: mock.returnUser}, mock.isAuthenticated, mock.err } func TestAuthenticateTokenSecondPasses(t *testing.T) { @@ -45,15 +47,15 @@ func TestAuthenticateTokenSecondPasses(t *testing.T) { handler2 := &mockAuthRequestHandler{returnUser: user2, isAuthenticated: true} authRequestHandler := New(handler1, handler2) - authenticatedUser, isAuthenticated, err := authRequestHandler.AuthenticateToken("foo") + resp, isAuthenticated, err := authRequestHandler.AuthenticateToken(context.Background(), "foo") if err != nil { t.Errorf("Unexpected error: %v", err) } if !isAuthenticated { t.Errorf("Unexpectedly unauthenticated: %v", isAuthenticated) } - if !reflect.DeepEqual(user2, authenticatedUser) { - t.Errorf("Expected %v, got %v", user2, authenticatedUser) + if !reflect.DeepEqual(user2, resp.User) { + t.Errorf("Expected %v, got %v", user2, resp.User) } } @@ -62,15 +64,15 @@ func TestAuthenticateTokenFirstPasses(t *testing.T) { handler2 := &mockAuthRequestHandler{returnUser: user2} authRequestHandler := New(handler1, handler2) - authenticatedUser, isAuthenticated, err := authRequestHandler.AuthenticateToken("foo") + resp, isAuthenticated, err := authRequestHandler.AuthenticateToken(context.Background(), "foo") if err != nil { t.Errorf("Unexpected error: %v", err) } if !isAuthenticated { t.Errorf("Unexpectedly unauthenticated: %v", isAuthenticated) } - if !reflect.DeepEqual(user1, authenticatedUser) { - t.Errorf("Expected %v, got %v", user1, authenticatedUser) + if !reflect.DeepEqual(user1, resp.User) { + t.Errorf("Expected %v, got %v", user1, resp.User) } } @@ -79,7 +81,7 @@ func TestAuthenticateTokenSuppressUnnecessaryErrors(t *testing.T) { handler2 := &mockAuthRequestHandler{isAuthenticated: true} authRequestHandler := New(handler1, handler2) - _, isAuthenticated, err := authRequestHandler.AuthenticateToken("foo") + _, isAuthenticated, err := authRequestHandler.AuthenticateToken(context.Background(), "foo") if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -91,15 +93,15 @@ func TestAuthenticateTokenSuppressUnnecessaryErrors(t *testing.T) { func TestAuthenticateTokenNoAuthenticators(t *testing.T) { authRequestHandler := New() - authenticatedUser, isAuthenticated, err := authRequestHandler.AuthenticateToken("foo") + resp, isAuthenticated, err := authRequestHandler.AuthenticateToken(context.Background(), "foo") if err != nil { t.Errorf("Unexpected error: %v", err) } if isAuthenticated { t.Errorf("Unexpectedly authenticated: %v", isAuthenticated) } - if authenticatedUser != nil { - t.Errorf("Unexpected authenticatedUser: %v", authenticatedUser) + if resp != nil { + t.Errorf("Unexpected authenticatedUser: %v", resp) } } @@ -108,7 +110,7 @@ func TestAuthenticateTokenNonePass(t *testing.T) { handler2 := &mockAuthRequestHandler{} authRequestHandler := New(handler1, handler2) - _, isAuthenticated, err := authRequestHandler.AuthenticateToken("foo") + _, isAuthenticated, err := authRequestHandler.AuthenticateToken(context.Background(), "foo") if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -122,7 +124,7 @@ func TestAuthenticateTokenAdditiveErrors(t *testing.T) { handler2 := &mockAuthRequestHandler{err: errors.New("second")} authRequestHandler := New(handler1, handler2) - _, isAuthenticated, err := authRequestHandler.AuthenticateToken("foo") + _, isAuthenticated, err := authRequestHandler.AuthenticateToken(context.Background(), "foo") if err == nil { t.Errorf("Expected an error") } @@ -142,7 +144,7 @@ func TestAuthenticateTokenFailEarly(t *testing.T) { handler2 := &mockAuthRequestHandler{err: errors.New("second")} authRequestHandler := NewFailOnError(handler1, handler2) - _, isAuthenticated, err := authRequestHandler.AuthenticateToken("foo") + _, isAuthenticated, err := authRequestHandler.AuthenticateToken(context.Background(), "foo") if err == nil { t.Errorf("Expected an error") } diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication.go b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication.go index ec3bbc274e..b9c6f6e51a 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication.go @@ -59,7 +59,7 @@ func WithAuthentication(handler http.Handler, auth authenticator.Request, failed if len(apiAuds) > 0 { req = req.WithContext(genericapirequest.WithAudiences(req.Context(), apiAuds)) } - user, ok, err := auth.AuthenticateRequest(req) + resp, ok, err := auth.AuthenticateRequest(req) if err != nil || !ok { if err != nil { glog.Errorf("Unable to authenticate the request due to an error: %v", err) @@ -68,12 +68,15 @@ func WithAuthentication(handler http.Handler, auth authenticator.Request, failed return } + // TODO(mikedanese): verify the response audience matches one of apiAuds if + // non-empty + // authorization header is not required anymore in case of a successful authentication. req.Header.Del("Authorization") - req = req.WithContext(genericapirequest.WithUser(req.Context(), user)) + req = req.WithContext(genericapirequest.WithUser(req.Context(), resp.User)) - authenticatedUserCounter.WithLabelValues(compressUsername(user.GetName())).Inc() + authenticatedUserCounter.WithLabelValues(compressUsername(resp.User.GetName())).Inc() handler.ServeHTTP(w, req) }) diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication_test.go b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication_test.go index a43119a995..887baebc93 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication_test.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication_test.go @@ -41,9 +41,9 @@ func TestAuthenticateRequest(t *testing.T) { } close(success) }), - authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) { + authenticator.RequestFunc(func(req *http.Request) (*authenticator.Response, bool, error) { if req.Header.Get("Authorization") == "Something" { - return &user.DefaultInfo{Name: "user"}, true, nil + return &authenticator.Response{User: &user.DefaultInfo{Name: "user"}}, true, nil } return nil, false, errors.New("Authorization header is missing.") }), @@ -64,7 +64,7 @@ func TestAuthenticateRequestFailed(t *testing.T) { http.HandlerFunc(func(_ http.ResponseWriter, req *http.Request) { t.Errorf("unexpected call to handler") }), - authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) { + authenticator.RequestFunc(func(req *http.Request) (*authenticator.Response, bool, error) { return nil, false, nil }), http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) { @@ -84,7 +84,7 @@ func TestAuthenticateRequestError(t *testing.T) { http.HandlerFunc(func(_ http.ResponseWriter, req *http.Request) { t.Errorf("unexpected call to handler") }), - authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) { + authenticator.RequestFunc(func(req *http.Request) (*authenticator.Response, bool, error) { return nil, false, errors.New("failure") }), http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) { diff --git a/staging/src/k8s.io/apiserver/pkg/server/deprecated_insecure_serving.go b/staging/src/k8s.io/apiserver/pkg/server/deprecated_insecure_serving.go index 2af16bf9b7..43fff06ec0 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/deprecated_insecure_serving.go +++ b/staging/src/k8s.io/apiserver/pkg/server/deprecated_insecure_serving.go @@ -23,6 +23,7 @@ import ( "github.com/golang/glog" + "k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/client-go/rest" ) @@ -77,9 +78,11 @@ func (s *DeprecatedInsecureServingInfo) NewLoopbackClientConfig() (*rest.Config, // but allows apiserver code to stop special-casing a nil user to skip authorization checks. type InsecureSuperuser struct{} -func (InsecureSuperuser) AuthenticateRequest(req *http.Request) (user.Info, bool, error) { - return &user.DefaultInfo{ - Name: "system:unsecured", - Groups: []string{user.SystemPrivilegedGroup, user.AllAuthenticated}, +func (InsecureSuperuser) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) { + return &authenticator.Response{ + User: &user.DefaultInfo{ + Name: "system:unsecured", + Groups: []string{user.SystemPrivilegedGroup, user.AllAuthenticated}, + }, }, true, nil } diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile/BUILD b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile/BUILD index 4cf94236c5..bb770700ad 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile/BUILD +++ b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile/BUILD @@ -19,6 +19,7 @@ go_library( importmap = "k8s.io/kubernetes/vendor/k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile", importpath = "k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile", deps = [ + "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library", "//vendor/github.com/golang/glog:go_default_library", ], diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile/passwordfile.go b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile/passwordfile.go index 9ce243fa71..8f291d191c 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile/passwordfile.go +++ b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile/passwordfile.go @@ -17,6 +17,7 @@ limitations under the License. package passwordfile import ( + "context" "encoding/csv" "fmt" "io" @@ -25,6 +26,7 @@ import ( "github.com/golang/glog" + "k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authentication/user" ) @@ -78,7 +80,7 @@ func NewCSV(path string) (*PasswordAuthenticator, error) { return &PasswordAuthenticator{users}, nil } -func (a *PasswordAuthenticator) AuthenticatePassword(username, password string) (user.Info, bool, error) { +func (a *PasswordAuthenticator) AuthenticatePassword(ctx context.Context, username, password string) (*authenticator.Response, bool, error) { user, ok := a.users[username] if !ok { return nil, false, nil @@ -86,5 +88,5 @@ func (a *PasswordAuthenticator) AuthenticatePassword(username, password string) if user.password != password { return nil, false, nil } - return user.info, true, nil + return &authenticator.Response{User: user.info}, true, nil } diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile/passwordfile_test.go b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile/passwordfile_test.go index 9a3a6350e3..e9f43d6dcb 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile/passwordfile_test.go +++ b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile/passwordfile_test.go @@ -17,6 +17,7 @@ limitations under the License. package passwordfile import ( + "context" "io/ioutil" "os" "reflect" @@ -110,16 +111,16 @@ password7,user7,uid7,"group1,group2",otherdata }, } for i, testCase := range testCases { - user, ok, err := auth.AuthenticatePassword(testCase.Username, testCase.Password) + resp, ok, err := auth.AuthenticatePassword(context.Background(), testCase.Username, testCase.Password) if err != nil { t.Errorf("%d: unexpected error: %v", i, err) } if testCase.User == nil { - if user != nil { - t.Errorf("%d: unexpected non-nil user %#v", i, user) + if resp != nil { + t.Errorf("%d: unexpected non-nil user %#v", i, resp.User) } - } else if !reflect.DeepEqual(testCase.User, user) { - t.Errorf("%d: expected user %#v, got %#v", i, testCase.User, user) + } else if !reflect.DeepEqual(testCase.User, resp.User) { + t.Errorf("%d: expected user %#v, got %#v", i, testCase.User, resp.User) } if testCase.Ok != ok { t.Errorf("%d: expected auth %v, got %v", i, testCase.Ok, ok) diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth/BUILD b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth/BUILD index faf589ef46..4d6a346ba8 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth/BUILD +++ b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth/BUILD @@ -21,10 +21,7 @@ go_library( srcs = ["basicauth.go"], importmap = "k8s.io/kubernetes/vendor/k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth", importpath = "k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth", - deps = [ - "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library", - ], + deps = ["//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library"], ) filegroup( diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth/basicauth.go b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth/basicauth.go index d5b39ce175..7b8894a915 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth/basicauth.go +++ b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth/basicauth.go @@ -21,7 +21,6 @@ import ( "net/http" "k8s.io/apiserver/pkg/authentication/authenticator" - "k8s.io/apiserver/pkg/authentication/user" ) // Authenticator authenticates requests using basic auth @@ -37,18 +36,18 @@ func New(auth authenticator.Password) *Authenticator { var errInvalidAuth = errors.New("invalid username/password combination") // AuthenticateRequest authenticates the request using the "Authorization: Basic" header in the request -func (a *Authenticator) AuthenticateRequest(req *http.Request) (user.Info, bool, error) { +func (a *Authenticator) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) { username, password, found := req.BasicAuth() if !found { return nil, false, nil } - user, ok, err := a.auth.AuthenticatePassword(username, password) + resp, ok, err := a.auth.AuthenticatePassword(req.Context(), username, password) // If the password authenticator didn't error, provide a default error if !ok && err == nil { err = errInvalidAuth } - return user, ok, err + return resp, ok, err } diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth/basicauth_test.go b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth/basicauth_test.go index 2d59e0edef..c23e0ce082 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth/basicauth_test.go +++ b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth/basicauth_test.go @@ -17,6 +17,7 @@ limitations under the License. package basicauth import ( + "context" "errors" "net/http" "testing" @@ -35,11 +36,11 @@ type testPassword struct { Err error } -func (t *testPassword) AuthenticatePassword(user, password string) (user.Info, bool, error) { +func (t *testPassword) AuthenticatePassword(ctx context.Context, user, password string) (*authenticator.Response, bool, error) { t.Called = true t.Username = user t.Password = password - return t.User, t.OK, t.Err + return &authenticator.Response{User: t.User}, t.OK, t.Err } func TestBasicAuth(t *testing.T) { @@ -94,7 +95,7 @@ func TestBasicAuth(t *testing.T) { req.SetBasicAuth(testCase.ExpectedUsername, testCase.ExpectedPassword) } - user, ok, err := auth.AuthenticateRequest(req) + resp, ok, err := auth.AuthenticateRequest(req) if testCase.ExpectedCalled != password.Called { t.Errorf("%s: Expected called=%v, got %v", k, testCase.ExpectedCalled, password.Called) @@ -117,8 +118,8 @@ func TestBasicAuth(t *testing.T) { t.Errorf("%s: Expected ok=%v, got ok=%v", k, testCase.ExpectedOK, ok) continue } - if testCase.ExpectedUser != "" && testCase.ExpectedUser != user.GetName() { - t.Errorf("%s: Expected user.GetName()=%v, got %v", k, testCase.ExpectedUser, user.GetName()) + if testCase.ExpectedUser != "" && testCase.ExpectedUser != resp.User.GetName() { + t.Errorf("%s: Expected user.GetName()=%v, got %v", k, testCase.ExpectedUser, resp.User.GetName()) continue } } diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/BUILD b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/BUILD index dc5b6690da..3863bb823f 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/BUILD +++ b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/BUILD @@ -28,6 +28,7 @@ go_library( deps = [ "//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library", "//staging/src/k8s.io/client-go/util/cert:go_default_library", "//vendor/github.com/coreos/go-oidc:go_default_library", diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc.go b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc.go index 551f769d23..12a46a57d8 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc.go +++ b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc.go @@ -44,8 +44,10 @@ import ( oidc "github.com/coreos/go-oidc" "github.com/golang/glog" + "k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authentication/user" certutil "k8s.io/client-go/util/cert" ) @@ -529,7 +531,7 @@ func (r *claimResolver) resolve(endpoint endpoint, allClaims claims) error { return nil } -func (a *Authenticator) AuthenticateToken(token string) (user.Info, bool, error) { +func (a *Authenticator) AuthenticateToken(ctx context.Context, token string) (*authenticator.Response, bool, error) { if !hasCorrectIssuer(a.issuerURL, token) { return nil, false, nil } @@ -539,7 +541,6 @@ func (a *Authenticator) AuthenticateToken(token string) (user.Info, bool, error) return nil, false, fmt.Errorf("oidc: authenticator not initialized") } - ctx := context.Background() idToken, err := verifier.Verify(ctx, token) if err != nil { return nil, false, fmt.Errorf("oidc: verify token: %v", err) @@ -617,7 +618,7 @@ func (a *Authenticator) AuthenticateToken(token string) (user.Info, bool, error) } } - return info, true, nil + return &authenticator.Response{User: info}, true, nil } // getClaimJWT gets a distributed claim JWT from url, using the supplied access diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc_test.go b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc_test.go index fc055af642..0ceb72e83b 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc_test.go +++ b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc_test.go @@ -296,7 +296,8 @@ func (c *claimsTest) run(t *testing.T) { t.Fatalf("serialize token: %v", err) } - got, ok, err := a.AuthenticateToken(token) + got, ok, err := a.AuthenticateToken(context.Background(), token) + if err != nil { if !c.wantErr { t.Fatalf("authenticate token: %v", err) @@ -318,7 +319,7 @@ func (c *claimsTest) run(t *testing.T) { t.Fatalf("expected authenticator to skip token") } - gotUser := got.(*user.DefaultInfo) + gotUser := got.User.(*user.DefaultInfo) if !reflect.DeepEqual(gotUser, c.want) { t.Fatalf("wanted user=%#v, got=%#v", c.want, gotUser) } diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/tokentest/BUILD b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/tokentest/BUILD index 8bd6147c83..00b36669fd 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/tokentest/BUILD +++ b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/tokentest/BUILD @@ -11,7 +11,10 @@ go_library( srcs = ["tokentest.go"], importmap = "k8s.io/kubernetes/vendor/k8s.io/apiserver/plugin/pkg/authenticator/token/tokentest", importpath = "k8s.io/apiserver/plugin/pkg/authenticator/token/tokentest", - deps = ["//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library"], + deps = [ + "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library", + ], ) filegroup( diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/tokentest/tokentest.go b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/tokentest/tokentest.go index 7ce2221d25..9b1a663efb 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/tokentest/tokentest.go +++ b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/tokentest/tokentest.go @@ -16,7 +16,12 @@ limitations under the License. package tokentest -import "k8s.io/apiserver/pkg/authentication/user" +import ( + "context" + + "k8s.io/apiserver/pkg/authentication/authenticator" + "k8s.io/apiserver/pkg/authentication/user" +) type TokenAuthenticator struct { Tokens map[string]*user.DefaultInfo @@ -27,10 +32,11 @@ func New() *TokenAuthenticator { Tokens: make(map[string]*user.DefaultInfo), } } -func (a *TokenAuthenticator) AuthenticateToken(value string) (user.Info, bool, error) { + +func (a *TokenAuthenticator) AuthenticateToken(ctx context.Context, value string) (*authenticator.Response, bool, error) { user, ok := a.Tokens[value] if !ok { return nil, false, nil } - return user, true, nil + return &authenticator.Response{User: user}, true, nil } diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook/webhook.go b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook/webhook.go index feb55f91d3..90104df549 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook/webhook.go +++ b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook/webhook.go @@ -18,6 +18,7 @@ limitations under the License. package webhook import ( + "context" "time" "github.com/golang/glog" @@ -69,7 +70,7 @@ func newWithBackoff(tokenReview authenticationclient.TokenReviewInterface, ttl, } // AuthenticateToken implements the authenticator.Token interface. -func (w *WebhookTokenAuthenticator) AuthenticateToken(token string) (user.Info, bool, error) { +func (w *WebhookTokenAuthenticator) AuthenticateToken(ctx context.Context, token string) (*authenticator.Response, bool, error) { r := &authentication.TokenReview{ Spec: authentication.TokenReviewSpec{Token: token}, } @@ -104,11 +105,13 @@ func (w *WebhookTokenAuthenticator) AuthenticateToken(token string) (user.Info, } } - return &user.DefaultInfo{ - Name: r.Status.User.Username, - UID: r.Status.User.UID, - Groups: r.Status.User.Groups, - Extra: extra, + return &authenticator.Response{ + User: &user.DefaultInfo{ + Name: r.Status.User.Username, + UID: r.Status.User.UID, + Groups: r.Status.User.Groups, + Extra: extra, + }, }, true, nil } diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook/webhook_test.go b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook/webhook_test.go index 8019b82dab..bd2d00bf72 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook/webhook_test.go +++ b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook/webhook_test.go @@ -17,6 +17,7 @@ limitations under the License. package webhook import ( + "context" "crypto/tls" "crypto/x509" "encoding/json" @@ -257,7 +258,7 @@ func TestTLSConfig(t *testing.T) { // Allow all and see if we get an error. service.Allow() - _, authenticated, err := wh.AuthenticateToken("t0k3n") + _, authenticated, err := wh.AuthenticateToken(context.Background(), "t0k3n") if tt.wantErr { if err == nil { t.Errorf("expected error making authorization request: %v", err) @@ -270,7 +271,7 @@ func TestTLSConfig(t *testing.T) { } service.Deny() - _, authenticated, err = wh.AuthenticateToken("t0k3n") + _, authenticated, err = wh.AuthenticateToken(context.Background(), "t0k3n") if err != nil { t.Errorf("%s: unexpectedly failed AuthenticateToken", tt.test) } @@ -374,7 +375,7 @@ func TestWebhookTokenAuthenticator(t *testing.T) { token := "my-s3cr3t-t0ken" for i, tt := range tests { serv.response = tt.serverResponse - user, authenticated, err := wh.AuthenticateToken(token) + resp, authenticated, err := wh.AuthenticateToken(context.Background(), token) if err != nil { t.Errorf("case %d: authentication failed: %v", i, err) continue @@ -391,9 +392,9 @@ func TestWebhookTokenAuthenticator(t *testing.T) { t.Errorf("case %d: Plugin returned incorrect authentication response. Got %t, expected %t.", i, authenticated, tt.expectedAuthenticated) } - if user != nil && tt.expectedUser != nil && !reflect.DeepEqual(user, tt.expectedUser) { + if resp != nil && tt.expectedUser != nil && !reflect.DeepEqual(resp.User, tt.expectedUser) { t.Errorf("case %d: Plugin returned incorrect user. Got %#v, expected %#v", - i, user, tt.expectedUser) + i, resp.User, tt.expectedUser) } } } @@ -540,12 +541,12 @@ func TestWebhookCacheAndRetry(t *testing.T) { } for _, testcase := range testcases { - func() { + t.Run(testcase.description, func(t *testing.T) { serv.allow = testcase.allow serv.statusCode = testcase.code serv.called = 0 - _, ok, err := wh.AuthenticateToken(testcase.token) + _, ok, err := wh.AuthenticateToken(context.Background(), testcase.token) hasError := err != nil if hasError != testcase.expectError { t.Log(testcase.description) @@ -559,6 +560,6 @@ func TestWebhookCacheAndRetry(t *testing.T) { t.Log(testcase.description) t.Errorf("Expected ok=%v, got %v", testcase.expectOk, ok) } - }() + }) } } diff --git a/test/integration/auth/accessreview_test.go b/test/integration/auth/accessreview_test.go index 4880e354d7..df7d1c96f9 100644 --- a/test/integration/auth/accessreview_test.go +++ b/test/integration/auth/accessreview_test.go @@ -46,9 +46,11 @@ func (sarAuthorizer) Authorize(a authorizer.Attributes) (authorizer.Decision, st return authorizer.DecisionAllow, "you're not dave", nil } -func alwaysAlice(req *http.Request) (user.Info, bool, error) { - return &user.DefaultInfo{ - Name: "alice", +func alwaysAlice(req *http.Request) (*authenticator.Response, bool, error) { + return &authenticator.Response{ + User: &user.DefaultInfo{ + Name: "alice", + }, }, true, nil } @@ -145,8 +147,10 @@ func TestSubjectAccessReview(t *testing.T) { func TestSelfSubjectAccessReview(t *testing.T) { username := "alice" masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authentication.Authenticator = authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) { - return &user.DefaultInfo{Name: username}, true, nil + masterConfig.GenericConfig.Authentication.Authenticator = authenticator.RequestFunc(func(req *http.Request) (*authenticator.Response, bool, error) { + return &authenticator.Response{ + User: &user.DefaultInfo{Name: username}, + }, true, nil }) masterConfig.GenericConfig.Authorization.Authorizer = sarAuthorizer{} _, s, closeFn := framework.RunAMaster(masterConfig) diff --git a/test/integration/framework/master_utils.go b/test/integration/framework/master_utils.go index ad46408298..52df5c97b4 100644 --- a/test/integration/framework/master_utils.go +++ b/test/integration/framework/master_utils.go @@ -83,9 +83,11 @@ func (alwaysAllow) Authorize(requestAttributes authorizer.Attributes) (authorize } // alwaysEmpty simulates "no authentication" for old tests -func alwaysEmpty(req *http.Request) (user.Info, bool, error) { - return &user.DefaultInfo{ - Name: "", +func alwaysEmpty(req *http.Request) (*authauthenticator.Response, bool, error) { + return &authauthenticator.Response{ + User: &user.DefaultInfo{ + Name: "", + }, }, true, nil } diff --git a/test/integration/serviceaccount/service_account_test.go b/test/integration/serviceaccount/service_account_test.go index 10e3cb8f80..c554597a8d 100644 --- a/test/integration/serviceaccount/service_account_test.go +++ b/test/integration/serviceaccount/service_account_test.go @@ -21,6 +21,7 @@ package serviceaccount // to work for any client of the HTTP interface. import ( + "context" "crypto/rand" "crypto/rsa" "fmt" @@ -365,9 +366,9 @@ func startServiceAccountTestServer(t *testing.T) (*clientset.Clientset, restclie // Set up two authenticators: // 1. A token authenticator that maps the rootToken to the "root" user // 2. A ServiceAccountToken authenticator that validates ServiceAccount tokens - rootTokenAuth := authenticator.TokenFunc(func(token string) (user.Info, bool, error) { + rootTokenAuth := authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { if token == rootToken { - return &user.DefaultInfo{Name: rootUserName}, true, nil + return &authenticator.Response{User: &user.DefaultInfo{Name: rootUserName}}, true, nil } return nil, false, nil })