From 817cf70191b73d1ee9f4e7af83089e5854e5131d Mon Sep 17 00:00:00 2001 From: Mike Danese Date: Wed, 31 Oct 2018 14:50:11 -0700 Subject: [PATCH 1/3] move audience context functions to authenticator package --- .../pkg/authentication/authenticator/BUILD | 4 ++-- .../{helpers.go => audiences.go} | 21 +++++++++++++++++++ .../{helpers_test.go => audiences_test.go} | 0 .../authentication/request/anonymous/BUILD | 1 - .../request/anonymous/anonymous.go | 3 +-- .../pkg/authentication/token/cache/BUILD | 2 -- .../token/cache/cached_token_authenticator.go | 3 +-- .../cache/cached_token_authenticator_test.go | 7 +++---- .../pkg/endpoints/filters/authentication.go | 2 +- .../apiserver/pkg/endpoints/request/BUILD | 1 - .../pkg/endpoints/request/context.go | 12 ----------- .../pkg/server/deprecated_insecure_serving.go | 3 +-- 12 files changed, 30 insertions(+), 29 deletions(-) rename staging/src/k8s.io/apiserver/pkg/authentication/authenticator/{helpers.go => audiences.go} (65%) rename staging/src/k8s.io/apiserver/pkg/authentication/authenticator/{helpers_test.go => audiences_test.go} (100%) diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/authenticator/BUILD b/staging/src/k8s.io/apiserver/pkg/authentication/authenticator/BUILD index 1d25f33a21..22ffab2cda 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/authenticator/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/authentication/authenticator/BUILD @@ -5,7 +5,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ - "helpers.go", + "audiences.go", "interfaces.go", ], importmap = "k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/authentication/authenticator", @@ -28,6 +28,6 @@ filegroup( go_test( name = "go_default_test", - srcs = ["helpers_test.go"], + srcs = ["audiences_test.go"], embed = [":go_default_library"], ) diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/authenticator/helpers.go b/staging/src/k8s.io/apiserver/pkg/authentication/authenticator/audiences.go similarity index 65% rename from staging/src/k8s.io/apiserver/pkg/authentication/authenticator/helpers.go rename to staging/src/k8s.io/apiserver/pkg/authentication/authenticator/audiences.go index f2aa9b0d7e..2a3a918896 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/authenticator/helpers.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/authenticator/audiences.go @@ -16,9 +16,30 @@ limitations under the License. package authenticator +import "context" + // Audiences is a container for the Audiences of a token. type Audiences []string +// The key type is unexported to prevent collisions +type key int + +const ( + // audiencesKey is the context key for request audiences. + audiencesKey key = iota +) + +// WithAudiences returns a context that stores a request's expected audiences. +func WithAudiences(ctx context.Context, auds Audiences) context.Context { + return context.WithValue(ctx, audiencesKey, auds) +} + +// AudiencesFrom returns a request's expected audiences stored in the request context. +func AudiencesFrom(ctx context.Context) (Audiences, bool) { + auds, ok := ctx.Value(audiencesKey).(Audiences) + return auds, ok +} + // Has checks if Audiences contains a specific audiences. func (a Audiences) Has(taud string) bool { for _, aud := range a { diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/authenticator/helpers_test.go b/staging/src/k8s.io/apiserver/pkg/authentication/authenticator/audiences_test.go similarity index 100% rename from staging/src/k8s.io/apiserver/pkg/authentication/authenticator/helpers_test.go rename to staging/src/k8s.io/apiserver/pkg/authentication/authenticator/audiences_test.go diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/request/anonymous/BUILD b/staging/src/k8s.io/apiserver/pkg/authentication/request/anonymous/BUILD index b78435554c..329b92ecc5 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/request/anonymous/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/authentication/request/anonymous/BUILD @@ -25,7 +25,6 @@ go_library( 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/endpoints/request:go_default_library", ], ) diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/request/anonymous/anonymous.go b/staging/src/k8s.io/apiserver/pkg/authentication/request/anonymous/anonymous.go index 76ff130227..f9177d1513 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/request/anonymous/anonymous.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/request/anonymous/anonymous.go @@ -21,7 +21,6 @@ import ( "k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authentication/user" - "k8s.io/apiserver/pkg/endpoints/request" ) const ( @@ -32,7 +31,7 @@ const ( func NewAuthenticator() authenticator.Request { return authenticator.RequestFunc(func(req *http.Request) (*authenticator.Response, bool, error) { - auds, _ := request.AudiencesFrom(req.Context()) + auds, _ := authenticator.AudiencesFrom(req.Context()) return &authenticator.Response{ User: &user.DefaultInfo{ Name: anonymousUser, diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/BUILD b/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/BUILD index 3c8ca28129..66c09d4484 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/BUILD @@ -17,7 +17,6 @@ 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", ], ) @@ -35,7 +34,6 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/util/cache:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library", "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library", ], ) diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/cached_token_authenticator.go b/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/cached_token_authenticator.go index ec5af39d8b..457770aa73 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/cached_token_authenticator.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/cached_token_authenticator.go @@ -23,7 +23,6 @@ import ( utilclock "k8s.io/apimachinery/pkg/util/clock" "k8s.io/apiserver/pkg/authentication/authenticator" - "k8s.io/apiserver/pkg/endpoints/request" ) // cacheRecord holds the three return values of the authenticator.Token AuthenticateToken method @@ -67,7 +66,7 @@ func newWithClock(authenticator authenticator.Token, successTTL, failureTTL time // AuthenticateToken implements authenticator.Token func (a *cachedTokenAuthenticator) AuthenticateToken(ctx context.Context, token string) (*authenticator.Response, bool, error) { - auds, _ := request.AudiencesFrom(ctx) + auds, _ := authenticator.AudiencesFrom(ctx) key := keyFunc(auds, token) if record, ok := a.cache.get(key); ok { diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/cached_token_authenticator_test.go b/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/cached_token_authenticator_test.go index e92e957a4d..9215fefc07 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/cached_token_authenticator_test.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/token/cache/cached_token_authenticator_test.go @@ -25,7 +25,6 @@ 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) { @@ -109,7 +108,7 @@ func TestCachedTokenAuthenticator(t *testing.T) { 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) + auds, _ := authenticator.AudiencesFrom(ctx) return &authenticator.Response{User: resultUsers[auds[0]+token]}, true, nil }) fakeClock := utilclock.NewFakeClock(time.Now()) @@ -119,10 +118,10 @@ func TestCachedTokenAuthenticatorWithAudiences(t *testing.T) { 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" { + if u, ok, _ := a.AuthenticateToken(authenticator.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" { + if u, ok, _ := a.AuthenticateToken(authenticator.WithAudiences(context.Background(), []string{"audB"}), "usertoken1"); !ok || u.User.GetName() != "user1-different" { t.Errorf("Expected user1-different") } } diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication.go b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication.go index b9c6f6e51a..70c14e088a 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication.go @@ -57,7 +57,7 @@ func WithAuthentication(handler http.Handler, auth authenticator.Request, failed } return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { if len(apiAuds) > 0 { - req = req.WithContext(genericapirequest.WithAudiences(req.Context(), apiAuds)) + req = req.WithContext(authenticator.WithAudiences(req.Context(), apiAuds)) } resp, ok, err := auth.AuthenticateRequest(req) if err != nil || !ok { diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/request/BUILD b/staging/src/k8s.io/apiserver/pkg/endpoints/request/BUILD index e56dc33f8b..5e84006a1c 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/request/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/request/BUILD @@ -35,7 +35,6 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apiserver/pkg/apis/audit: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", "//vendor/github.com/golang/glog:go_default_library", ], diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/request/context.go b/staging/src/k8s.io/apiserver/pkg/endpoints/request/context.go index eb1e854609..fe3ae38edc 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/request/context.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/request/context.go @@ -21,7 +21,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apiserver/pkg/apis/audit" - "k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authentication/user" ) @@ -95,14 +94,3 @@ func AuditEventFrom(ctx context.Context) *audit.Event { ev, _ := ctx.Value(auditKey).(*audit.Event) return ev } - -// WithAudiences returns a context that stores a request's expected audiences. -func WithAudiences(ctx context.Context, auds authenticator.Audiences) context.Context { - return context.WithValue(ctx, audiencesKey, auds) -} - -// AudiencesFrom returns a request's expected audiences stored in the request context. -func AudiencesFrom(ctx context.Context) (authenticator.Audiences, bool) { - auds, ok := ctx.Value(audiencesKey).(authenticator.Audiences) - return auds, ok -} diff --git a/staging/src/k8s.io/apiserver/pkg/server/deprecated_insecure_serving.go b/staging/src/k8s.io/apiserver/pkg/server/deprecated_insecure_serving.go index cf84988a7e..6cf6c1a64f 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/deprecated_insecure_serving.go +++ b/staging/src/k8s.io/apiserver/pkg/server/deprecated_insecure_serving.go @@ -25,7 +25,6 @@ import ( "k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authentication/user" - "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/client-go/rest" ) @@ -80,7 +79,7 @@ func (s *DeprecatedInsecureServingInfo) NewLoopbackClientConfig() (*rest.Config, type InsecureSuperuser struct{} func (InsecureSuperuser) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) { - auds, _ := request.AudiencesFrom(req.Context()) + auds, _ := authenticator.AudiencesFrom(req.Context()) return &authenticator.Response{ User: &user.DefaultInfo{ Name: "system:unsecured", From c704d70d49bb9799674d84aecb2a49afb6512e11 Mon Sep 17 00:00:00 2001 From: Mike Danese Date: Tue, 16 Oct 2018 20:57:37 -0700 Subject: [PATCH 2/3] create audience unaware authenticator wrappers --- .../pkg/authentication/authenticator/BUILD | 10 +- .../authenticator/audagnostic.go | 90 +++++++ .../authenticator/audagnostic_test.go | 229 ++++++++++++++++++ 3 files changed, 328 insertions(+), 1 deletion(-) create mode 100644 staging/src/k8s.io/apiserver/pkg/authentication/authenticator/audagnostic.go create mode 100644 staging/src/k8s.io/apiserver/pkg/authentication/authenticator/audagnostic_test.go diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/authenticator/BUILD b/staging/src/k8s.io/apiserver/pkg/authentication/authenticator/BUILD index 22ffab2cda..a8a5395dc9 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/authenticator/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/authentication/authenticator/BUILD @@ -5,6 +5,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ + "audagnostic.go", "audiences.go", "interfaces.go", ], @@ -28,6 +29,13 @@ filegroup( go_test( name = "go_default_test", - srcs = ["audiences_test.go"], + srcs = [ + "audagnostic_test.go", + "audiences_test.go", + ], embed = [":go_default_library"], + deps = [ + "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library", + ], ) diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/authenticator/audagnostic.go b/staging/src/k8s.io/apiserver/pkg/authentication/authenticator/audagnostic.go new file mode 100644 index 0000000000..bcf7eb4bc9 --- /dev/null +++ b/staging/src/k8s.io/apiserver/pkg/authentication/authenticator/audagnostic.go @@ -0,0 +1,90 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package authenticator + +import ( + "context" + "fmt" + "net/http" +) + +func authenticate(ctx context.Context, implicitAuds Audiences, authenticate func() (*Response, bool, error)) (*Response, bool, error) { + targetAuds, ok := AudiencesFrom(ctx) + // We can remove this once api audiences is never empty. That will probably + // be N releases after TokenRequest is GA. + if !ok { + return authenticate() + } + auds := implicitAuds.Intersect(targetAuds) + if len(auds) == 0 { + return nil, false, nil + } + resp, ok, err := authenticate() + if err != nil || !ok { + return nil, false, err + } + if len(resp.Audiences) > 0 { + // maybe the authenticator was audience aware after all. + return nil, false, fmt.Errorf("audience agnostic authenticator wrapped an authenticator that returned audiences: %q", resp.Audiences) + } + resp.Audiences = auds + return resp, true, nil +} + +type audAgnosticRequestAuthenticator struct { + implicit Audiences + delegate Request +} + +var _ = Request(&audAgnosticRequestAuthenticator{}) + +func (a *audAgnosticRequestAuthenticator) AuthenticateRequest(req *http.Request) (*Response, bool, error) { + return authenticate(req.Context(), a.implicit, func() (*Response, bool, error) { + return a.delegate.AuthenticateRequest(req) + }) +} + +// WrapAudienceAgnosticRequest wraps an audience agnostic request authenticator +// to restrict its accepted audiences to a set of implicit audiences. +func WrapAudienceAgnosticRequest(implicit Audiences, delegate Request) Request { + return &audAgnosticRequestAuthenticator{ + implicit: implicit, + delegate: delegate, + } +} + +type audAgnosticTokenAuthenticator struct { + implicit Audiences + delegate Token +} + +var _ = Token(&audAgnosticTokenAuthenticator{}) + +func (a *audAgnosticTokenAuthenticator) AuthenticateToken(ctx context.Context, tok string) (*Response, bool, error) { + return authenticate(ctx, a.implicit, func() (*Response, bool, error) { + return a.delegate.AuthenticateToken(ctx, tok) + }) +} + +// WrapAudienceAgnosticToken wraps an audience agnostic token authenticator to +// restrict its accepted audiences to a set of implicit audiences. +func WrapAudienceAgnosticToken(implicit Audiences, delegate Token) Token { + return &audAgnosticTokenAuthenticator{ + implicit: implicit, + delegate: delegate, + } +} diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/authenticator/audagnostic_test.go b/staging/src/k8s.io/apiserver/pkg/authentication/authenticator/audagnostic_test.go new file mode 100644 index 0000000000..0152b9a6e3 --- /dev/null +++ b/staging/src/k8s.io/apiserver/pkg/authentication/authenticator/audagnostic_test.go @@ -0,0 +1,229 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package authenticator + +import ( + "context" + "errors" + "fmt" + "reflect" + "testing" + + "k8s.io/apimachinery/pkg/util/diff" + "k8s.io/apiserver/pkg/authentication/user" +) + +func TestAuthenticate(t *testing.T) { + type treq struct { + resp *Response + authenticated bool + err error + + wantResp *Response + wantAuthenticated bool + wantErr bool + } + type taudcfg struct { + auds Audiences + implicitAuds Audiences + } + cs := []struct { + name string + + taudcfgs []taudcfg + treqs []treq + }{ + { + name: "good audience", + + taudcfgs: []taudcfg{ + { + implicitAuds: Audiences{"api"}, + auds: Audiences{"api"}, + }, + { + implicitAuds: Audiences{"api", "other"}, + auds: Audiences{"api"}, + }, + { + implicitAuds: Audiences{"api"}, + auds: Audiences{"api", "other"}, + }, + { + implicitAuds: Audiences{"api", "other"}, + auds: Audiences{"api", "other_other"}, + }, + }, + + treqs: []treq{ + { + resp: &Response{ + User: &user.DefaultInfo{ + Name: "test_user", + }, + }, + authenticated: true, + + wantResp: &Response{ + User: &user.DefaultInfo{ + Name: "test_user", + }, + Audiences: Audiences{"api"}, + }, + wantAuthenticated: true, + }, + { + err: errors.New("uhoh"), + wantErr: true, + }, + { + authenticated: false, + wantAuthenticated: false, + }, + }, + }, + { + name: "multiple good audiences", + + taudcfgs: []taudcfg{ + { + implicitAuds: Audiences{"api", "other_api"}, + auds: Audiences{"api", "other_api"}, + }, + { + implicitAuds: Audiences{"api", "other_api", "other"}, + auds: Audiences{"api", "other_api"}, + }, + { + implicitAuds: Audiences{"api", "other_api"}, + auds: Audiences{"api", "other_api", "other"}, + }, + { + implicitAuds: Audiences{"api", "other_api", "other"}, + auds: Audiences{"api", "other_api", "other_other"}, + }, + }, + + treqs: []treq{ + { + resp: &Response{ + User: &user.DefaultInfo{ + Name: "test_user", + }, + }, + authenticated: true, + + wantResp: &Response{ + User: &user.DefaultInfo{ + Name: "test_user", + }, + Audiences: Audiences{"api", "other_api"}, + }, + wantAuthenticated: true, + }, + { + err: errors.New("uhoh"), + + wantErr: true, + }, + { + authenticated: false, + + wantAuthenticated: false, + }, + }, + }, + { + name: "bad audience(s)", + + taudcfgs: []taudcfg{ + { + implicitAuds: Audiences{"api"}, + auds: Audiences{"other_api"}, + }, + { + implicitAuds: Audiences{}, + auds: Audiences{"other_api"}, + }, + { + implicitAuds: Audiences{"api"}, + auds: Audiences{}, + }, + { + implicitAuds: Audiences{"api", "other"}, + auds: Audiences{}, + }, + { + implicitAuds: Audiences{}, + auds: Audiences{"api", "other"}, + }, + }, + + treqs: []treq{ + { + resp: &Response{ + User: &user.DefaultInfo{ + Name: "test_user", + }, + }, + authenticated: true, + + wantAuthenticated: false, + }, + { + err: errors.New("uhoh"), + + wantAuthenticated: false, + }, + { + authenticated: false, + + wantAuthenticated: false, + }, + }, + }, + } + + for _, c := range cs { + t.Run(c.name, func(t *testing.T) { + for _, taudcfg := range c.taudcfgs { + for _, treq := range c.treqs { + t.Run(fmt.Sprintf("auds=%q,implicit=%q", taudcfg.auds, taudcfg.implicitAuds), func(t *testing.T) { + ctx := context.Background() + ctx = WithAudiences(ctx, taudcfg.auds) + resp, ok, err := authenticate(ctx, taudcfg.implicitAuds, func() (*Response, bool, error) { + if treq.resp != nil { + resp := *treq.resp + return &resp, treq.authenticated, treq.err + } + return nil, treq.authenticated, treq.err + }) + if got, want := (err != nil), treq.wantErr; got != want { + t.Errorf("Unexpected error. got=%v, want=%v, err=%v", got, want, err) + } + if got, want := ok, treq.wantAuthenticated; got != want { + t.Errorf("Unexpected authentication. got=%v, want=%v", got, want) + } + if got, want := resp, treq.wantResp; !reflect.DeepEqual(got, want) { + t.Errorf("Unexpected response. diff:\n%v", diff.ObjectGoPrintDiff(got, want)) + } + }) + } + } + }) + } +} From 34cc8eeac7eddfff9ff489e1a5299d841861f5a2 Mon Sep 17 00:00:00 2001 From: Mike Danese Date: Mon, 22 Oct 2018 18:49:04 -0700 Subject: [PATCH 3/3] wrap all audience unaware authenticators in kube-apiserver --- pkg/kubeapiserver/authenticator/config.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/pkg/kubeapiserver/authenticator/config.go b/pkg/kubeapiserver/authenticator/config.go index a91136599c..976666f5e6 100644 --- a/pkg/kubeapiserver/authenticator/config.go +++ b/pkg/kubeapiserver/authenticator/config.go @@ -38,11 +38,10 @@ import ( "k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth" "k8s.io/apiserver/plugin/pkg/authenticator/token/oidc" "k8s.io/apiserver/plugin/pkg/authenticator/token/webhook" + _ "k8s.io/client-go/plugin/pkg/client/auth" certutil "k8s.io/client-go/util/cert" "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/serviceaccount" - - _ "k8s.io/client-go/plugin/pkg/client/auth" ) type AuthenticatorConfig struct { @@ -97,7 +96,7 @@ func (config AuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDe if err != nil { return nil, nil, err } - authenticators = append(authenticators, requestHeaderAuthenticator) + authenticators = append(authenticators, authenticator.WrapAudienceAgnosticRequest(config.APIAudiences, requestHeaderAuthenticator)) } // basic auth @@ -106,7 +105,7 @@ func (config AuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDe if err != nil { return nil, nil, err } - authenticators = append(authenticators, basicAuth) + authenticators = append(authenticators, authenticator.WrapAudienceAgnosticRequest(config.APIAudiences, basicAuth)) securityDefinitions["HTTPBasic"] = &spec.SecurityScheme{ SecuritySchemeProps: spec.SecuritySchemeProps{ @@ -131,14 +130,14 @@ func (config AuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDe if err != nil { return nil, nil, err } - tokenAuthenticators = append(tokenAuthenticators, tokenAuth) + tokenAuthenticators = append(tokenAuthenticators, authenticator.WrapAudienceAgnosticToken(config.APIAudiences, tokenAuth)) } if len(config.ServiceAccountKeyFiles) > 0 { serviceAccountAuth, err := newLegacyServiceAccountAuthenticator(config.ServiceAccountKeyFiles, config.ServiceAccountLookup, config.ServiceAccountTokenGetter) if err != nil { return nil, nil, err } - tokenAuthenticators = append(tokenAuthenticators, serviceAccountAuth) + tokenAuthenticators = append(tokenAuthenticators, authenticator.WrapAudienceAgnosticToken(config.APIAudiences, serviceAccountAuth)) } if utilfeature.DefaultFeatureGate.Enabled(features.TokenRequest) && config.ServiceAccountIssuer != "" { serviceAccountAuth, err := newServiceAccountAuthenticator(config.ServiceAccountIssuer, config.APIAudiences, config.ServiceAccountKeyFiles, config.ServiceAccountTokenGetter) @@ -150,7 +149,7 @@ func (config AuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDe if config.BootstrapToken { if config.BootstrapTokenAuthenticator != nil { // TODO: This can sometimes be nil because of - tokenAuthenticators = append(tokenAuthenticators, config.BootstrapTokenAuthenticator) + tokenAuthenticators = append(tokenAuthenticators, authenticator.WrapAudienceAgnosticToken(config.APIAudiences, config.BootstrapTokenAuthenticator)) } } // NOTE(ericchiang): Keep the OpenID Connect after Service Accounts.