diff --git a/pkg/master/master.go b/pkg/master/master.go index 7dbc0b378d6..b2d25a12f70 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -335,7 +335,7 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) // handlers that we have. restStorageProviders := []RESTStorageProvider{ auditregistrationrest.RESTStorageProvider{}, - authenticationrest.RESTStorageProvider{Authenticator: c.GenericConfig.Authentication.Authenticator}, + authenticationrest.RESTStorageProvider{Authenticator: c.GenericConfig.Authentication.Authenticator, APIAudiences: c.GenericConfig.Authentication.APIAudiences}, authorizationrest.RESTStorageProvider{Authorizer: c.GenericConfig.Authorization.Authorizer, RuleResolver: c.GenericConfig.RuleResolver}, autoscalingrest.RESTStorageProvider{}, batchrest.RESTStorageProvider{}, diff --git a/pkg/registry/authentication/rest/storage_authentication.go b/pkg/registry/authentication/rest/storage_authentication.go index 5dec4aeb077..9dc3cf1a8e4 100644 --- a/pkg/registry/authentication/rest/storage_authentication.go +++ b/pkg/registry/authentication/rest/storage_authentication.go @@ -31,6 +31,7 @@ import ( type RESTStorageProvider struct { Authenticator authenticator.Request + APIAudiences authenticator.Audiences } func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { @@ -56,7 +57,7 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorag func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { storage := map[string]rest.Storage{} // tokenreviews - tokenReviewStorage := tokenreview.NewREST(p.Authenticator) + tokenReviewStorage := tokenreview.NewREST(p.Authenticator, p.APIAudiences) storage["tokenreviews"] = tokenReviewStorage return storage @@ -65,7 +66,7 @@ func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorag func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { storage := map[string]rest.Storage{} // tokenreviews - tokenReviewStorage := tokenreview.NewREST(p.Authenticator) + tokenReviewStorage := tokenreview.NewREST(p.Authenticator, p.APIAudiences) storage["tokenreviews"] = tokenReviewStorage return storage diff --git a/pkg/registry/authentication/tokenreview/BUILD b/pkg/registry/authentication/tokenreview/BUILD index 7ef5901f8f3..4533e49e8b7 100644 --- a/pkg/registry/authentication/tokenreview/BUILD +++ b/pkg/registry/authentication/tokenreview/BUILD @@ -17,6 +17,7 @@ go_library( "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", "//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library", + "//vendor/k8s.io/klog:go_default_library", ], ) diff --git a/pkg/registry/authentication/tokenreview/storage.go b/pkg/registry/authentication/tokenreview/storage.go index 3150b2afd1b..d14ee1a90f7 100644 --- a/pkg/registry/authentication/tokenreview/storage.go +++ b/pkg/registry/authentication/tokenreview/storage.go @@ -18,6 +18,7 @@ package tokenreview import ( "context" + "errors" "fmt" "net/http" @@ -27,15 +28,22 @@ import ( "k8s.io/apiserver/pkg/authentication/authenticator" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" + "k8s.io/klog" "k8s.io/kubernetes/pkg/apis/authentication" ) +var badAuthenticatorAuds = apierrors.NewInternalError(errors.New("error validating audiences")) + type REST struct { tokenAuthenticator authenticator.Request + apiAudiences []string } -func NewREST(tokenAuthenticator authenticator.Request) *REST { - return &REST{tokenAuthenticator: tokenAuthenticator} +func NewREST(tokenAuthenticator authenticator.Request, apiAudiences []string) *REST { + return &REST{ + tokenAuthenticator: tokenAuthenticator, + apiAudiences: apiAudiences, + } } func (r *REST) NamespaceScoped() bool { @@ -68,14 +76,24 @@ 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) + auds := tokenReview.Spec.Audiences + if len(auds) == 0 { + auds = r.apiAudiences + } + if len(auds) > 0 { + fakeReq = fakeReq.WithContext(authenticator.WithAudiences(fakeReq.Context(), auds)) + } + resp, ok, err := r.tokenAuthenticator.AuthenticateRequest(fakeReq) tokenReview.Status.Authenticated = ok if err != nil { tokenReview.Status.Error = err.Error() } - // TODO(mikedanese): verify the response audience matches one of apiAuds if - // non-empty + if len(auds) > 0 && resp != nil && len(authenticator.Audiences(auds).Intersect(resp.Audiences)) == 0 { + klog.Errorf("error validating audience. want=%q got=%q", auds, resp.Audiences) + return nil, badAuthenticatorAuds + } if resp != nil && resp.User != nil { tokenReview.Status.User = authentication.UserInfo{ @@ -87,6 +105,7 @@ func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation for k, v := range resp.User.GetExtra() { tokenReview.Status.User.Extra[k] = authentication.ExtraValue(v) } + tokenReview.Status.Audiences = resp.Audiences } return tokenReview, nil