mirror of https://github.com/k3s-io/k3s
Merge pull request #69582 from mikedanese/trev7
tokenreview: authenticator interface changespull/58/head
commit
baa8d800ad
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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{}) {
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -17,52 +17,64 @@ limitations under the License.
|
|||
package authenticator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
)
|
||||
|
||||
// Token checks a string value against a backing authentication store and returns
|
||||
// information about the current user and true if successful, false if not successful,
|
||||
// or an error if the token could not be checked.
|
||||
// Token checks a string value against a backing authentication store and
|
||||
// returns a Response or an error if the token could not be checked.
|
||||
type Token interface {
|
||||
AuthenticateToken(token string) (user.Info, bool, error)
|
||||
AuthenticateToken(ctx context.Context, token string) (*Response, bool, error)
|
||||
}
|
||||
|
||||
// Request attempts to extract authentication information from a request and returns
|
||||
// information about the current user and true if successful, false if not successful,
|
||||
// or an error if the request could not be checked.
|
||||
// Request attempts to extract authentication information from a request and
|
||||
// returns a Response or an error if the request could not be checked.
|
||||
type Request interface {
|
||||
AuthenticateRequest(req *http.Request) (user.Info, bool, error)
|
||||
AuthenticateRequest(req *http.Request) (*Response, bool, error)
|
||||
}
|
||||
|
||||
// Password checks a username and password against a backing authentication store and
|
||||
// returns information about the user and true if successful, false if not successful,
|
||||
// or an error if the username and password could not be checked
|
||||
// Password checks a username and password against a backing authentication
|
||||
// store and returns a Response or an error if the password could not be
|
||||
// checked.
|
||||
type Password interface {
|
||||
AuthenticatePassword(user, password string) (user.Info, bool, error)
|
||||
AuthenticatePassword(ctx context.Context, user, password string) (*Response, bool, error)
|
||||
}
|
||||
|
||||
// TokenFunc is a function that implements the Token interface.
|
||||
type TokenFunc func(token string) (user.Info, bool, error)
|
||||
type TokenFunc func(ctx context.Context, token string) (*Response, bool, error)
|
||||
|
||||
// AuthenticateToken implements authenticator.Token.
|
||||
func (f TokenFunc) AuthenticateToken(token string) (user.Info, bool, error) {
|
||||
return f(token)
|
||||
func (f TokenFunc) AuthenticateToken(ctx context.Context, token string) (*Response, bool, error) {
|
||||
return f(ctx, token)
|
||||
}
|
||||
|
||||
// RequestFunc is a function that implements the Request interface.
|
||||
type RequestFunc func(req *http.Request) (user.Info, bool, error)
|
||||
type RequestFunc func(req *http.Request) (*Response, bool, error)
|
||||
|
||||
// AuthenticateRequest implements authenticator.Request.
|
||||
func (f RequestFunc) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
|
||||
func (f RequestFunc) AuthenticateRequest(req *http.Request) (*Response, bool, error) {
|
||||
return f(req)
|
||||
}
|
||||
|
||||
// PasswordFunc is a function that implements the Password interface.
|
||||
type PasswordFunc func(user, password string) (user.Info, bool, error)
|
||||
type PasswordFunc func(ctx context.Context, user, password string) (*Response, bool, error)
|
||||
|
||||
// AuthenticatePassword implements authenticator.Password.
|
||||
func (f PasswordFunc) AuthenticatePassword(user, password string) (user.Info, bool, error) {
|
||||
return f(user, password)
|
||||
func (f PasswordFunc) AuthenticatePassword(ctx context.Context, user, password string) (*Response, bool, error) {
|
||||
return f(ctx, user, password)
|
||||
}
|
||||
|
||||
// Response is the struct returned by authenticator interfaces upon successful
|
||||
// authentication. It contains information about whether the authenticator
|
||||
// authenticated the request, information about the context of the
|
||||
// authentication, and information about the authenticated user.
|
||||
type Response struct {
|
||||
// Audiences is the set of audiences the authenticator was able to validate
|
||||
// the token against. If the authenticator is not audience aware, this field
|
||||
// will be empty.
|
||||
Audiences Audiences
|
||||
// User is the UserInfo associated with the authentication context.
|
||||
User user.Info
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
})
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -17,6 +17,7 @@ go_test(
|
|||
"//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",
|
||||
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
|
||||
"//vendor/github.com/pborman/uuid:go_default_library",
|
||||
],
|
||||
)
|
||||
|
@ -34,7 +35,7 @@ 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",
|
||||
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -24,36 +24,36 @@ import (
|
|||
// split cache lookups across N striped caches
|
||||
type stripedCache struct {
|
||||
stripeCount uint32
|
||||
keyFunc func(string) uint32
|
||||
hashFunc func(string) uint32
|
||||
caches []cache
|
||||
}
|
||||
|
||||
type keyFunc func(string) uint32
|
||||
type hashFunc func(string) uint32
|
||||
type newCacheFunc func() cache
|
||||
|
||||
func newStripedCache(stripeCount int, keyFunc keyFunc, newCacheFunc newCacheFunc) cache {
|
||||
func newStripedCache(stripeCount int, hash hashFunc, newCacheFunc newCacheFunc) cache {
|
||||
caches := []cache{}
|
||||
for i := 0; i < stripeCount; i++ {
|
||||
caches = append(caches, newCacheFunc())
|
||||
}
|
||||
return &stripedCache{
|
||||
stripeCount: uint32(stripeCount),
|
||||
keyFunc: keyFunc,
|
||||
hashFunc: hash,
|
||||
caches: caches,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *stripedCache) get(key string) (*cacheRecord, bool) {
|
||||
return c.caches[c.keyFunc(key)%c.stripeCount].get(key)
|
||||
return c.caches[c.hashFunc(key)%c.stripeCount].get(key)
|
||||
}
|
||||
func (c *stripedCache) set(key string, value *cacheRecord, ttl time.Duration) {
|
||||
c.caches[c.keyFunc(key)%c.stripeCount].set(key, value, ttl)
|
||||
c.caches[c.hashFunc(key)%c.stripeCount].set(key, value, ttl)
|
||||
}
|
||||
func (c *stripedCache) remove(key string) {
|
||||
c.caches[c.keyFunc(key)%c.stripeCount].remove(key)
|
||||
c.caches[c.hashFunc(key)%c.stripeCount].remove(key)
|
||||
}
|
||||
|
||||
func fnvKeyFunc(key string) uint32 {
|
||||
func fnvHashFunc(key string) uint32 {
|
||||
f := fnv.New32()
|
||||
f.Write([]byte(key))
|
||||
return f.Sum32()
|
||||
|
|
|
@ -21,10 +21,11 @@ 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) {
|
||||
|
@ -36,11 +37,11 @@ func BenchmarkSimpleCache(b *testing.B) {
|
|||
}
|
||||
|
||||
func TestStripedCache(t *testing.T) {
|
||||
testCache(newStripedCache(32, fnvKeyFunc, func() cache { return newSimpleCache(128, clock.RealClock{}) }), t)
|
||||
testCache(newStripedCache(32, fnvHashFunc, func() cache { return newSimpleCache(128, clock.RealClock{}) }), t)
|
||||
}
|
||||
|
||||
func BenchmarkStripedCache(b *testing.B) {
|
||||
benchmarkCache(newStripedCache(32, fnvKeyFunc, func() cache { return newSimpleCache(128, clock.RealClock{}) }), b)
|
||||
benchmarkCache(newStripedCache(32, fnvHashFunc, func() cache { return newSimpleCache(128, clock.RealClock{}) }), b)
|
||||
}
|
||||
|
||||
func benchmarkCache(cache cache, b *testing.B) {
|
||||
|
@ -71,8 +72,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)
|
||||
|
|
|
@ -17,16 +17,18 @@ limitations under the License.
|
|||
package cache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
utilclock "k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/apiserver/pkg/authentication/authenticator"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
)
|
||||
|
||||
// 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
|
||||
}
|
||||
|
@ -59,24 +61,31 @@ func newWithClock(authenticator authenticator.Token, successTTL, failureTTL time
|
|||
authenticator: authenticator,
|
||||
successTTL: successTTL,
|
||||
failureTTL: failureTTL,
|
||||
cache: newStripedCache(32, fnvKeyFunc, func() cache { return newSimpleCache(128, clock) }),
|
||||
cache: newStripedCache(32, fnvHashFunc, func() cache { return newSimpleCache(128, clock) }),
|
||||
}
|
||||
}
|
||||
|
||||
// AuthenticateToken implements authenticator.Token
|
||||
func (a *cachedTokenAuthenticator) AuthenticateToken(token string) (user.Info, bool, error) {
|
||||
if record, ok := a.cache.get(token); ok {
|
||||
return record.user, record.ok, record.err
|
||||
func (a *cachedTokenAuthenticator) AuthenticateToken(ctx context.Context, token string) (*authenticator.Response, bool, error) {
|
||||
auds, _ := request.AudiencesFrom(ctx)
|
||||
|
||||
key := keyFunc(auds, token)
|
||||
if record, ok := a.cache.get(key); ok {
|
||||
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(key, &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(key, &cacheRecord{resp: resp, ok: ok, err: err}, a.failureTTL)
|
||||
}
|
||||
|
||||
return user, ok, err
|
||||
return resp, ok, err
|
||||
}
|
||||
|
||||
func keyFunc(auds []string, token string) string {
|
||||
return fmt.Sprintf("%#v|%v", auds, token)
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
package cache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -24,6 +25,7 @@ import (
|
|||
utilclock "k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/apiserver/pkg/authentication/authenticator"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
)
|
||||
|
||||
func TestCachedTokenAuthenticator(t *testing.T) {
|
||||
|
@ -34,21 +36,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 +63,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 +81,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,10 +98,31 @@ 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)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCachedTokenAuthenticatorWithAudiences(t *testing.T) {
|
||||
resultUsers := make(map[string]user.Info)
|
||||
fakeAuth := authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) {
|
||||
auds, _ := request.AudiencesFrom(ctx)
|
||||
return &authenticator.Response{User: resultUsers[auds[0]+token]}, true, nil
|
||||
})
|
||||
fakeClock := utilclock.NewFakeClock(time.Now())
|
||||
|
||||
a := newWithClock(fakeAuth, time.Minute, 0, fakeClock)
|
||||
|
||||
resultUsers["audAusertoken1"] = &user.DefaultInfo{Name: "user1"}
|
||||
resultUsers["audBusertoken1"] = &user.DefaultInfo{Name: "user1-different"}
|
||||
|
||||
if u, ok, _ := a.AuthenticateToken(request.WithAudiences(context.Background(), []string{"audA"}), "usertoken1"); !ok || u.User.GetName() != "user1" {
|
||||
t.Errorf("Expected user1")
|
||||
}
|
||||
if u, ok, _ := a.AuthenticateToken(request.WithAudiences(context.Background(), []string{"audB"}), "usertoken1"); !ok || u.User.GetName() != "user1-different" {
|
||||
t.Errorf("Expected user1-different")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
],
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
],
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue