mirror of https://github.com/k3s-io/k3s
Merge pull request #69916 from mikedanese/trev9
create audience unaware authenticator wrapperspull/58/head
commit
1165d661f0
|
@ -38,11 +38,10 @@ import (
|
||||||
"k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth"
|
"k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth"
|
||||||
"k8s.io/apiserver/plugin/pkg/authenticator/token/oidc"
|
"k8s.io/apiserver/plugin/pkg/authenticator/token/oidc"
|
||||||
"k8s.io/apiserver/plugin/pkg/authenticator/token/webhook"
|
"k8s.io/apiserver/plugin/pkg/authenticator/token/webhook"
|
||||||
|
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||||
certutil "k8s.io/client-go/util/cert"
|
certutil "k8s.io/client-go/util/cert"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
"k8s.io/kubernetes/pkg/serviceaccount"
|
"k8s.io/kubernetes/pkg/serviceaccount"
|
||||||
|
|
||||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type AuthenticatorConfig struct {
|
type AuthenticatorConfig struct {
|
||||||
|
@ -97,7 +96,7 @@ func (config AuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDe
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
authenticators = append(authenticators, requestHeaderAuthenticator)
|
authenticators = append(authenticators, authenticator.WrapAudienceAgnosticRequest(config.APIAudiences, requestHeaderAuthenticator))
|
||||||
}
|
}
|
||||||
|
|
||||||
// basic auth
|
// basic auth
|
||||||
|
@ -106,7 +105,7 @@ func (config AuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDe
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
authenticators = append(authenticators, basicAuth)
|
authenticators = append(authenticators, authenticator.WrapAudienceAgnosticRequest(config.APIAudiences, basicAuth))
|
||||||
|
|
||||||
securityDefinitions["HTTPBasic"] = &spec.SecurityScheme{
|
securityDefinitions["HTTPBasic"] = &spec.SecurityScheme{
|
||||||
SecuritySchemeProps: spec.SecuritySchemeProps{
|
SecuritySchemeProps: spec.SecuritySchemeProps{
|
||||||
|
@ -131,14 +130,14 @@ func (config AuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDe
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
tokenAuthenticators = append(tokenAuthenticators, tokenAuth)
|
tokenAuthenticators = append(tokenAuthenticators, authenticator.WrapAudienceAgnosticToken(config.APIAudiences, tokenAuth))
|
||||||
}
|
}
|
||||||
if len(config.ServiceAccountKeyFiles) > 0 {
|
if len(config.ServiceAccountKeyFiles) > 0 {
|
||||||
serviceAccountAuth, err := newLegacyServiceAccountAuthenticator(config.ServiceAccountKeyFiles, config.ServiceAccountLookup, config.ServiceAccountTokenGetter)
|
serviceAccountAuth, err := newLegacyServiceAccountAuthenticator(config.ServiceAccountKeyFiles, config.ServiceAccountLookup, config.ServiceAccountTokenGetter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
tokenAuthenticators = append(tokenAuthenticators, serviceAccountAuth)
|
tokenAuthenticators = append(tokenAuthenticators, authenticator.WrapAudienceAgnosticToken(config.APIAudiences, serviceAccountAuth))
|
||||||
}
|
}
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.TokenRequest) && config.ServiceAccountIssuer != "" {
|
if utilfeature.DefaultFeatureGate.Enabled(features.TokenRequest) && config.ServiceAccountIssuer != "" {
|
||||||
serviceAccountAuth, err := newServiceAccountAuthenticator(config.ServiceAccountIssuer, config.APIAudiences, config.ServiceAccountKeyFiles, config.ServiceAccountTokenGetter)
|
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.BootstrapToken {
|
||||||
if config.BootstrapTokenAuthenticator != nil {
|
if config.BootstrapTokenAuthenticator != nil {
|
||||||
// TODO: This can sometimes be nil because of
|
// 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.
|
// NOTE(ericchiang): Keep the OpenID Connect after Service Accounts.
|
||||||
|
|
|
@ -5,7 +5,8 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||||
go_library(
|
go_library(
|
||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = [
|
srcs = [
|
||||||
"helpers.go",
|
"audagnostic.go",
|
||||||
|
"audiences.go",
|
||||||
"interfaces.go",
|
"interfaces.go",
|
||||||
],
|
],
|
||||||
importmap = "k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/authentication/authenticator",
|
importmap = "k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/authentication/authenticator",
|
||||||
|
@ -28,6 +29,13 @@ filegroup(
|
||||||
|
|
||||||
go_test(
|
go_test(
|
||||||
name = "go_default_test",
|
name = "go_default_test",
|
||||||
srcs = ["helpers_test.go"],
|
srcs = [
|
||||||
|
"audagnostic_test.go",
|
||||||
|
"audiences_test.go",
|
||||||
|
],
|
||||||
embed = [":go_default_library"],
|
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",
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -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,
|
||||||
|
}
|
||||||
|
}
|
|
@ -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))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,9 +16,30 @@ limitations under the License.
|
||||||
|
|
||||||
package authenticator
|
package authenticator
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
// Audiences is a container for the Audiences of a token.
|
// Audiences is a container for the Audiences of a token.
|
||||||
type Audiences []string
|
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.
|
// Has checks if Audiences contains a specific audiences.
|
||||||
func (a Audiences) Has(taud string) bool {
|
func (a Audiences) Has(taud string) bool {
|
||||||
for _, aud := range a {
|
for _, aud := range a {
|
|
@ -25,7 +25,6 @@ go_library(
|
||||||
deps = [
|
deps = [
|
||||||
"//staging/src/k8s.io/apiserver/pkg/authentication/authenticator: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/authentication/user:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ import (
|
||||||
|
|
||||||
"k8s.io/apiserver/pkg/authentication/authenticator"
|
"k8s.io/apiserver/pkg/authentication/authenticator"
|
||||||
"k8s.io/apiserver/pkg/authentication/user"
|
"k8s.io/apiserver/pkg/authentication/user"
|
||||||
"k8s.io/apiserver/pkg/endpoints/request"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -32,7 +31,7 @@ const (
|
||||||
|
|
||||||
func NewAuthenticator() authenticator.Request {
|
func NewAuthenticator() authenticator.Request {
|
||||||
return authenticator.RequestFunc(func(req *http.Request) (*authenticator.Response, bool, error) {
|
return authenticator.RequestFunc(func(req *http.Request) (*authenticator.Response, bool, error) {
|
||||||
auds, _ := request.AudiencesFrom(req.Context())
|
auds, _ := authenticator.AudiencesFrom(req.Context())
|
||||||
return &authenticator.Response{
|
return &authenticator.Response{
|
||||||
User: &user.DefaultInfo{
|
User: &user.DefaultInfo{
|
||||||
Name: anonymousUser,
|
Name: anonymousUser,
|
||||||
|
|
|
@ -17,7 +17,6 @@ go_test(
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/clock: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/authenticator:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/authentication/user: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",
|
"//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/cache:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/clock: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/authenticator:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ import (
|
||||||
|
|
||||||
utilclock "k8s.io/apimachinery/pkg/util/clock"
|
utilclock "k8s.io/apimachinery/pkg/util/clock"
|
||||||
"k8s.io/apiserver/pkg/authentication/authenticator"
|
"k8s.io/apiserver/pkg/authentication/authenticator"
|
||||||
"k8s.io/apiserver/pkg/endpoints/request"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// cacheRecord holds the three return values of the authenticator.Token AuthenticateToken method
|
// 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
|
// AuthenticateToken implements authenticator.Token
|
||||||
func (a *cachedTokenAuthenticator) AuthenticateToken(ctx context.Context, token string) (*authenticator.Response, bool, error) {
|
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)
|
key := keyFunc(auds, token)
|
||||||
if record, ok := a.cache.get(key); ok {
|
if record, ok := a.cache.get(key); ok {
|
||||||
|
|
|
@ -25,7 +25,6 @@ import (
|
||||||
utilclock "k8s.io/apimachinery/pkg/util/clock"
|
utilclock "k8s.io/apimachinery/pkg/util/clock"
|
||||||
"k8s.io/apiserver/pkg/authentication/authenticator"
|
"k8s.io/apiserver/pkg/authentication/authenticator"
|
||||||
"k8s.io/apiserver/pkg/authentication/user"
|
"k8s.io/apiserver/pkg/authentication/user"
|
||||||
"k8s.io/apiserver/pkg/endpoints/request"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCachedTokenAuthenticator(t *testing.T) {
|
func TestCachedTokenAuthenticator(t *testing.T) {
|
||||||
|
@ -109,7 +108,7 @@ func TestCachedTokenAuthenticator(t *testing.T) {
|
||||||
func TestCachedTokenAuthenticatorWithAudiences(t *testing.T) {
|
func TestCachedTokenAuthenticatorWithAudiences(t *testing.T) {
|
||||||
resultUsers := make(map[string]user.Info)
|
resultUsers := make(map[string]user.Info)
|
||||||
fakeAuth := authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) {
|
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
|
return &authenticator.Response{User: resultUsers[auds[0]+token]}, true, nil
|
||||||
})
|
})
|
||||||
fakeClock := utilclock.NewFakeClock(time.Now())
|
fakeClock := utilclock.NewFakeClock(time.Now())
|
||||||
|
@ -119,10 +118,10 @@ func TestCachedTokenAuthenticatorWithAudiences(t *testing.T) {
|
||||||
resultUsers["audAusertoken1"] = &user.DefaultInfo{Name: "user1"}
|
resultUsers["audAusertoken1"] = &user.DefaultInfo{Name: "user1"}
|
||||||
resultUsers["audBusertoken1"] = &user.DefaultInfo{Name: "user1-different"}
|
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")
|
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")
|
t.Errorf("Expected user1-different")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ func WithAuthentication(handler http.Handler, auth authenticator.Request, failed
|
||||||
}
|
}
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
if len(apiAuds) > 0 {
|
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)
|
resp, ok, err := auth.AuthenticateRequest(req)
|
||||||
if err != nil || !ok {
|
if err != nil || !ok {
|
||||||
|
|
|
@ -35,7 +35,6 @@ go_library(
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_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/apimachinery/pkg/util/sets:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/apis/audit: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",
|
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||||
"//vendor/github.com/golang/glog:go_default_library",
|
"//vendor/github.com/golang/glog:go_default_library",
|
||||||
],
|
],
|
||||||
|
|
|
@ -21,7 +21,6 @@ import (
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apiserver/pkg/apis/audit"
|
"k8s.io/apiserver/pkg/apis/audit"
|
||||||
"k8s.io/apiserver/pkg/authentication/authenticator"
|
|
||||||
"k8s.io/apiserver/pkg/authentication/user"
|
"k8s.io/apiserver/pkg/authentication/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -95,14 +94,3 @@ func AuditEventFrom(ctx context.Context) *audit.Event {
|
||||||
ev, _ := ctx.Value(auditKey).(*audit.Event)
|
ev, _ := ctx.Value(auditKey).(*audit.Event)
|
||||||
return ev
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ import (
|
||||||
|
|
||||||
"k8s.io/apiserver/pkg/authentication/authenticator"
|
"k8s.io/apiserver/pkg/authentication/authenticator"
|
||||||
"k8s.io/apiserver/pkg/authentication/user"
|
"k8s.io/apiserver/pkg/authentication/user"
|
||||||
"k8s.io/apiserver/pkg/endpoints/request"
|
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -80,7 +79,7 @@ func (s *DeprecatedInsecureServingInfo) NewLoopbackClientConfig() (*rest.Config,
|
||||||
type InsecureSuperuser struct{}
|
type InsecureSuperuser struct{}
|
||||||
|
|
||||||
func (InsecureSuperuser) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) {
|
func (InsecureSuperuser) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) {
|
||||||
auds, _ := request.AudiencesFrom(req.Context())
|
auds, _ := authenticator.AudiencesFrom(req.Context())
|
||||||
return &authenticator.Response{
|
return &authenticator.Response{
|
||||||
User: &user.DefaultInfo{
|
User: &user.DefaultInfo{
|
||||||
Name: "system:unsecured",
|
Name: "system:unsecured",
|
||||||
|
|
Loading…
Reference in New Issue