mirror of https://github.com/k3s-io/k3s
patch webhook authenticator to support token review with arbitrary audiences
parent
ed17876e52
commit
effad15ecc
|
@ -179,7 +179,7 @@ func (config Config) New() (authenticator.Request, *spec.SecurityDefinitions, er
|
||||||
tokenAuthenticators = append(tokenAuthenticators, oidcAuth)
|
tokenAuthenticators = append(tokenAuthenticators, oidcAuth)
|
||||||
}
|
}
|
||||||
if len(config.WebhookTokenAuthnConfigFile) > 0 {
|
if len(config.WebhookTokenAuthnConfigFile) > 0 {
|
||||||
webhookTokenAuth, err := newWebhookTokenAuthenticator(config.WebhookTokenAuthnConfigFile, config.WebhookTokenAuthnCacheTTL)
|
webhookTokenAuth, err := newWebhookTokenAuthenticator(config.WebhookTokenAuthnConfigFile, config.WebhookTokenAuthnCacheTTL, config.APIAudiences)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -318,8 +318,8 @@ func newAuthenticatorFromClientCAFile(clientCAFile string) (authenticator.Reques
|
||||||
return x509.New(opts, x509.CommonNameUserConversion), nil
|
return x509.New(opts, x509.CommonNameUserConversion), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newWebhookTokenAuthenticator(webhookConfigFile string, ttl time.Duration) (authenticator.Token, error) {
|
func newWebhookTokenAuthenticator(webhookConfigFile string, ttl time.Duration, implicitAuds authenticator.Audiences) (authenticator.Token, error) {
|
||||||
webhookTokenAuthenticator, err := webhook.New(webhookConfigFile)
|
webhookTokenAuthenticator, err := webhook.New(webhookConfigFile, implicitAuds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,8 @@ type DelegatingAuthenticatorConfig struct {
|
||||||
// ClientCAFile is the CA bundle file used to authenticate client certificates
|
// ClientCAFile is the CA bundle file used to authenticate client certificates
|
||||||
ClientCAFile string
|
ClientCAFile string
|
||||||
|
|
||||||
|
APIAudiences authenticator.Audiences
|
||||||
|
|
||||||
RequestHeaderConfig *RequestHeaderConfig
|
RequestHeaderConfig *RequestHeaderConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +88,7 @@ func (c DelegatingAuthenticatorConfig) New() (authenticator.Request, *spec.Secur
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.TokenAccessReviewClient != nil {
|
if c.TokenAccessReviewClient != nil {
|
||||||
tokenAuth, err := webhooktoken.NewFromInterface(c.TokenAccessReviewClient)
|
tokenAuth, err := webhooktoken.NewFromInterface(c.TokenAccessReviewClient, c.APIAudiences)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/klog"
|
|
||||||
|
|
||||||
authentication "k8s.io/api/authentication/v1beta1"
|
authentication "k8s.io/api/authentication/v1beta1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
@ -31,6 +29,7 @@ import (
|
||||||
"k8s.io/apiserver/pkg/util/webhook"
|
"k8s.io/apiserver/pkg/util/webhook"
|
||||||
"k8s.io/client-go/kubernetes/scheme"
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
authenticationclient "k8s.io/client-go/kubernetes/typed/authentication/v1beta1"
|
authenticationclient "k8s.io/client-go/kubernetes/typed/authentication/v1beta1"
|
||||||
|
"k8s.io/klog"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -45,38 +44,58 @@ var _ authenticator.Token = (*WebhookTokenAuthenticator)(nil)
|
||||||
type WebhookTokenAuthenticator struct {
|
type WebhookTokenAuthenticator struct {
|
||||||
tokenReview authenticationclient.TokenReviewInterface
|
tokenReview authenticationclient.TokenReviewInterface
|
||||||
initialBackoff time.Duration
|
initialBackoff time.Duration
|
||||||
|
implicitAuds authenticator.Audiences
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFromInterface creates a webhook authenticator using the given tokenReview
|
// NewFromInterface creates a webhook authenticator using the given tokenReview
|
||||||
// client. It is recommend to wrap this authenticator with the token cache
|
// client. It is recommend to wrap this authenticator with the token cache
|
||||||
// authenticator implemented in
|
// authenticator implemented in
|
||||||
// k8s.io/apiserver/pkg/authentication/token/cache.
|
// k8s.io/apiserver/pkg/authentication/token/cache.
|
||||||
func NewFromInterface(tokenReview authenticationclient.TokenReviewInterface) (*WebhookTokenAuthenticator, error) {
|
func NewFromInterface(tokenReview authenticationclient.TokenReviewInterface, implicitAuds authenticator.Audiences) (*WebhookTokenAuthenticator, error) {
|
||||||
return newWithBackoff(tokenReview, retryBackoff)
|
return newWithBackoff(tokenReview, retryBackoff, implicitAuds)
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new WebhookTokenAuthenticator from the provided kubeconfig file.
|
// New creates a new WebhookTokenAuthenticator from the provided kubeconfig
|
||||||
func New(kubeConfigFile string) (*WebhookTokenAuthenticator, error) {
|
// file. It is recommend to wrap this authenticator with the token cache
|
||||||
|
// authenticator implemented in
|
||||||
|
// k8s.io/apiserver/pkg/authentication/token/cache.
|
||||||
|
func New(kubeConfigFile string, implicitAuds authenticator.Audiences) (*WebhookTokenAuthenticator, error) {
|
||||||
tokenReview, err := tokenReviewInterfaceFromKubeconfig(kubeConfigFile)
|
tokenReview, err := tokenReviewInterfaceFromKubeconfig(kubeConfigFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return newWithBackoff(tokenReview, retryBackoff)
|
return newWithBackoff(tokenReview, retryBackoff, implicitAuds)
|
||||||
}
|
}
|
||||||
|
|
||||||
// newWithBackoff allows tests to skip the sleep.
|
// newWithBackoff allows tests to skip the sleep.
|
||||||
func newWithBackoff(tokenReview authenticationclient.TokenReviewInterface, initialBackoff time.Duration) (*WebhookTokenAuthenticator, error) {
|
func newWithBackoff(tokenReview authenticationclient.TokenReviewInterface, initialBackoff time.Duration, implicitAuds authenticator.Audiences) (*WebhookTokenAuthenticator, error) {
|
||||||
return &WebhookTokenAuthenticator{tokenReview, initialBackoff}, nil
|
return &WebhookTokenAuthenticator{tokenReview, initialBackoff, implicitAuds}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AuthenticateToken implements the authenticator.Token interface.
|
// AuthenticateToken implements the authenticator.Token interface.
|
||||||
func (w *WebhookTokenAuthenticator) AuthenticateToken(ctx context.Context, token string) (*authenticator.Response, bool, error) {
|
func (w *WebhookTokenAuthenticator) AuthenticateToken(ctx context.Context, token string) (*authenticator.Response, bool, error) {
|
||||||
|
// We take implicit audiences of the API server at WebhookTokenAuthenticator
|
||||||
|
// construction time. The outline of how we validate audience here is:
|
||||||
|
//
|
||||||
|
// * if the ctx is not audience limited, don't do any audience validation.
|
||||||
|
// * if ctx is audience-limited, add the audiences to the tokenreview spec
|
||||||
|
// * if the tokenreview returns with audiences in the status that intersect
|
||||||
|
// with the audiences in the ctx, copy into the response and return success
|
||||||
|
// * if the tokenreview returns without an audience in the status, ensure
|
||||||
|
// the ctx audiences intersect with the implicit audiences, and set the
|
||||||
|
// intersection in the response.
|
||||||
|
// * otherwise return unauthenticated.
|
||||||
|
wantAuds, checkAuds := authenticator.AudiencesFrom(ctx)
|
||||||
r := &authentication.TokenReview{
|
r := &authentication.TokenReview{
|
||||||
Spec: authentication.TokenReviewSpec{Token: token},
|
Spec: authentication.TokenReviewSpec{
|
||||||
|
Token: token,
|
||||||
|
Audiences: wantAuds,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
result *authentication.TokenReview
|
result *authentication.TokenReview
|
||||||
err error
|
err error
|
||||||
|
auds authenticator.Audiences
|
||||||
)
|
)
|
||||||
webhook.WithExponentialBackoff(w.initialBackoff, func() error {
|
webhook.WithExponentialBackoff(w.initialBackoff, func() error {
|
||||||
result, err = w.tokenReview.Create(r)
|
result, err = w.tokenReview.Create(r)
|
||||||
|
@ -87,6 +106,18 @@ func (w *WebhookTokenAuthenticator) AuthenticateToken(ctx context.Context, token
|
||||||
klog.Errorf("Failed to make webhook authenticator request: %v", err)
|
klog.Errorf("Failed to make webhook authenticator request: %v", err)
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if checkAuds {
|
||||||
|
gotAuds := w.implicitAuds
|
||||||
|
if len(result.Status.Audiences) > 0 {
|
||||||
|
gotAuds = result.Status.Audiences
|
||||||
|
}
|
||||||
|
auds = wantAuds.Intersect(gotAuds)
|
||||||
|
if len(auds) == 0 {
|
||||||
|
return nil, false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
r.Status = result.Status
|
r.Status = result.Status
|
||||||
if !r.Status.Authenticated {
|
if !r.Status.Authenticated {
|
||||||
return nil, false, nil
|
return nil, false, nil
|
||||||
|
@ -107,6 +138,7 @@ func (w *WebhookTokenAuthenticator) AuthenticateToken(ctx context.Context, token
|
||||||
Groups: r.Status.User.Groups,
|
Groups: r.Status.User.Groups,
|
||||||
Extra: extra,
|
Extra: extra,
|
||||||
},
|
},
|
||||||
|
Audiences: auds,
|
||||||
}, true, nil
|
}, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,8 @@ import (
|
||||||
"k8s.io/client-go/tools/clientcmd/api/v1"
|
"k8s.io/client-go/tools/clientcmd/api/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var apiAuds = authenticator.Audiences{"api"}
|
||||||
|
|
||||||
// Service mocks a remote authentication service.
|
// Service mocks a remote authentication service.
|
||||||
type Service interface {
|
type Service interface {
|
||||||
// Review looks at the TokenReviewSpec and provides an authentication
|
// Review looks at the TokenReviewSpec and provides an authentication
|
||||||
|
@ -105,6 +107,7 @@ func NewTestServer(s Service, cert, key, caCert []byte) (*httptest.Server, error
|
||||||
type status struct {
|
type status struct {
|
||||||
Authenticated bool `json:"authenticated"`
|
Authenticated bool `json:"authenticated"`
|
||||||
User userInfo `json:"user"`
|
User userInfo `json:"user"`
|
||||||
|
Audiences []string `json:"audiences"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var extra map[string][]string
|
var extra map[string][]string
|
||||||
|
@ -130,6 +133,7 @@ func NewTestServer(s Service, cert, key, caCert []byte) (*httptest.Server, error
|
||||||
Groups: review.Status.User.Groups,
|
Groups: review.Status.User.Groups,
|
||||||
Extra: extra,
|
Extra: extra,
|
||||||
},
|
},
|
||||||
|
review.Status.Audiences,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
@ -168,7 +172,7 @@ func (m *mockService) HTTPStatusCode() int { return m.statusCode }
|
||||||
|
|
||||||
// newTokenAuthenticator creates a temporary kubeconfig file from the provided
|
// newTokenAuthenticator creates a temporary kubeconfig file from the provided
|
||||||
// arguments and attempts to load a new WebhookTokenAuthenticator from it.
|
// arguments and attempts to load a new WebhookTokenAuthenticator from it.
|
||||||
func newTokenAuthenticator(serverURL string, clientCert, clientKey, ca []byte, cacheTime time.Duration) (authenticator.Token, error) {
|
func newTokenAuthenticator(serverURL string, clientCert, clientKey, ca []byte, cacheTime time.Duration, implicitAuds authenticator.Audiences) (authenticator.Token, error) {
|
||||||
tempfile, err := ioutil.TempFile("", "")
|
tempfile, err := ioutil.TempFile("", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -196,7 +200,7 @@ func newTokenAuthenticator(serverURL string, clientCert, clientKey, ca []byte, c
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
authn, err := newWithBackoff(c, 0)
|
authn, err := newWithBackoff(c, 0, implicitAuds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -257,7 +261,7 @@ func TestTLSConfig(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
wh, err := newTokenAuthenticator(server.URL, tt.clientCert, tt.clientKey, tt.clientCA, 0)
|
wh, err := newTokenAuthenticator(server.URL, tt.clientCert, tt.clientKey, tt.clientCA, 0, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s: failed to create client: %v", tt.test, err)
|
t.Errorf("%s: failed to create client: %v", tt.test, err)
|
||||||
return
|
return
|
||||||
|
@ -312,23 +316,21 @@ func TestWebhookTokenAuthenticator(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
|
||||||
wh, err := newTokenAuthenticator(s.URL, clientCert, clientKey, caCert, 0)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
expTypeMeta := metav1.TypeMeta{
|
expTypeMeta := metav1.TypeMeta{
|
||||||
APIVersion: "authentication.k8s.io/v1beta1",
|
APIVersion: "authentication.k8s.io/v1beta1",
|
||||||
Kind: "TokenReview",
|
Kind: "TokenReview",
|
||||||
}
|
}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
description string
|
||||||
|
implicitAuds, reqAuds authenticator.Audiences
|
||||||
serverResponse v1beta1.TokenReviewStatus
|
serverResponse v1beta1.TokenReviewStatus
|
||||||
expectedAuthenticated bool
|
expectedAuthenticated bool
|
||||||
expectedUser *user.DefaultInfo
|
expectedUser *user.DefaultInfo
|
||||||
|
expectedAuds authenticator.Audiences
|
||||||
}{
|
}{
|
||||||
// Successful response should pass through all user info.
|
|
||||||
{
|
{
|
||||||
|
description: "successful response should pass through all user info.",
|
||||||
serverResponse: v1beta1.TokenReviewStatus{
|
serverResponse: v1beta1.TokenReviewStatus{
|
||||||
Authenticated: true,
|
Authenticated: true,
|
||||||
User: v1beta1.UserInfo{
|
User: v1beta1.UserInfo{
|
||||||
|
@ -341,6 +343,7 @@ func TestWebhookTokenAuthenticator(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
description: "successful response should pass through all user info.",
|
||||||
serverResponse: v1beta1.TokenReviewStatus{
|
serverResponse: v1beta1.TokenReviewStatus{
|
||||||
Authenticated: true,
|
Authenticated: true,
|
||||||
User: v1beta1.UserInfo{
|
User: v1beta1.UserInfo{
|
||||||
|
@ -358,8 +361,8 @@ func TestWebhookTokenAuthenticator(t *testing.T) {
|
||||||
Extra: map[string][]string{"foo": {"bar", "baz"}},
|
Extra: map[string][]string{"foo": {"bar", "baz"}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// Unauthenticated shouldn't even include extra provided info.
|
|
||||||
{
|
{
|
||||||
|
description: "unauthenticated shouldn't even include extra provided info.",
|
||||||
serverResponse: v1beta1.TokenReviewStatus{
|
serverResponse: v1beta1.TokenReviewStatus{
|
||||||
Authenticated: false,
|
Authenticated: false,
|
||||||
User: v1beta1.UserInfo{
|
User: v1beta1.UserInfo{
|
||||||
|
@ -372,37 +375,151 @@ func TestWebhookTokenAuthenticator(t *testing.T) {
|
||||||
expectedUser: nil,
|
expectedUser: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
description: "unauthenticated shouldn't even include extra provided info.",
|
||||||
serverResponse: v1beta1.TokenReviewStatus{
|
serverResponse: v1beta1.TokenReviewStatus{
|
||||||
Authenticated: false,
|
Authenticated: false,
|
||||||
},
|
},
|
||||||
expectedAuthenticated: false,
|
expectedAuthenticated: false,
|
||||||
expectedUser: nil,
|
expectedUser: nil,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
description: "good audience",
|
||||||
|
implicitAuds: apiAuds,
|
||||||
|
reqAuds: apiAuds,
|
||||||
|
serverResponse: v1beta1.TokenReviewStatus{
|
||||||
|
Authenticated: true,
|
||||||
|
User: v1beta1.UserInfo{
|
||||||
|
Username: "somebody",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedAuthenticated: true,
|
||||||
|
expectedUser: &user.DefaultInfo{
|
||||||
|
Name: "somebody",
|
||||||
|
},
|
||||||
|
expectedAuds: apiAuds,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "good audience",
|
||||||
|
implicitAuds: append(apiAuds, "other"),
|
||||||
|
reqAuds: apiAuds,
|
||||||
|
serverResponse: v1beta1.TokenReviewStatus{
|
||||||
|
Authenticated: true,
|
||||||
|
User: v1beta1.UserInfo{
|
||||||
|
Username: "somebody",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedAuthenticated: true,
|
||||||
|
expectedUser: &user.DefaultInfo{
|
||||||
|
Name: "somebody",
|
||||||
|
},
|
||||||
|
expectedAuds: apiAuds,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "bad audiences",
|
||||||
|
implicitAuds: apiAuds,
|
||||||
|
reqAuds: authenticator.Audiences{"other"},
|
||||||
|
serverResponse: v1beta1.TokenReviewStatus{
|
||||||
|
Authenticated: false,
|
||||||
|
},
|
||||||
|
expectedAuthenticated: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "bad audiences",
|
||||||
|
implicitAuds: apiAuds,
|
||||||
|
reqAuds: authenticator.Audiences{"other"},
|
||||||
|
// webhook authenticator hasn't been upgraded to support audience.
|
||||||
|
serverResponse: v1beta1.TokenReviewStatus{
|
||||||
|
Authenticated: true,
|
||||||
|
User: v1beta1.UserInfo{
|
||||||
|
Username: "somebody",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedAuthenticated: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "audience aware backend",
|
||||||
|
implicitAuds: apiAuds,
|
||||||
|
reqAuds: apiAuds,
|
||||||
|
serverResponse: v1beta1.TokenReviewStatus{
|
||||||
|
Authenticated: true,
|
||||||
|
User: v1beta1.UserInfo{
|
||||||
|
Username: "somebody",
|
||||||
|
},
|
||||||
|
Audiences: []string(apiAuds),
|
||||||
|
},
|
||||||
|
expectedAuthenticated: true,
|
||||||
|
expectedUser: &user.DefaultInfo{
|
||||||
|
Name: "somebody",
|
||||||
|
},
|
||||||
|
expectedAuds: apiAuds,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "audience aware backend",
|
||||||
|
serverResponse: v1beta1.TokenReviewStatus{
|
||||||
|
Authenticated: true,
|
||||||
|
User: v1beta1.UserInfo{
|
||||||
|
Username: "somebody",
|
||||||
|
},
|
||||||
|
Audiences: []string(apiAuds),
|
||||||
|
},
|
||||||
|
expectedAuthenticated: true,
|
||||||
|
expectedUser: &user.DefaultInfo{
|
||||||
|
Name: "somebody",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "audience aware backend",
|
||||||
|
implicitAuds: apiAuds,
|
||||||
|
reqAuds: apiAuds,
|
||||||
|
serverResponse: v1beta1.TokenReviewStatus{
|
||||||
|
Authenticated: true,
|
||||||
|
User: v1beta1.UserInfo{
|
||||||
|
Username: "somebody",
|
||||||
|
},
|
||||||
|
Audiences: []string{"other"},
|
||||||
|
},
|
||||||
|
expectedAuthenticated: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
token := "my-s3cr3t-t0ken"
|
token := "my-s3cr3t-t0ken"
|
||||||
for i, tt := range tests {
|
for _, tt := range tests {
|
||||||
serv.response = tt.serverResponse
|
t.Run(tt.description, func(t *testing.T) {
|
||||||
resp, authenticated, err := wh.AuthenticateToken(context.Background(), token)
|
wh, err := newTokenAuthenticator(s.URL, clientCert, clientKey, caCert, 0, tt.implicitAuds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("case %d: authentication failed: %v", i, err)
|
t.Fatal(err)
|
||||||
continue
|
}
|
||||||
}
|
|
||||||
if serv.lastRequest.Spec.Token != token {
|
ctx := context.Background()
|
||||||
t.Errorf("case %d: Server did not see correct token. Got %q, expected %q.",
|
if tt.reqAuds != nil {
|
||||||
i, serv.lastRequest.Spec.Token, token)
|
ctx = authenticator.WithAudiences(ctx, tt.reqAuds)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(serv.lastRequest.TypeMeta, expTypeMeta) {
|
|
||||||
t.Errorf("case %d: Server did not see correct TypeMeta. Got %v, expected %v",
|
serv.response = tt.serverResponse
|
||||||
i, serv.lastRequest.TypeMeta, expTypeMeta)
|
resp, authenticated, err := wh.AuthenticateToken(ctx, token)
|
||||||
}
|
if err != nil {
|
||||||
if authenticated != tt.expectedAuthenticated {
|
t.Fatalf("authentication failed: %v", err)
|
||||||
t.Errorf("case %d: Plugin returned incorrect authentication response. Got %t, expected %t.",
|
}
|
||||||
i, authenticated, tt.expectedAuthenticated)
|
if serv.lastRequest.Spec.Token != token {
|
||||||
}
|
t.Errorf("Server did not see correct token. Got %q, expected %q.",
|
||||||
if resp != nil && tt.expectedUser != nil && !reflect.DeepEqual(resp.User, tt.expectedUser) {
|
serv.lastRequest.Spec.Token, token)
|
||||||
t.Errorf("case %d: Plugin returned incorrect user. Got %#v, expected %#v",
|
}
|
||||||
i, resp.User, tt.expectedUser)
|
if !reflect.DeepEqual(serv.lastRequest.TypeMeta, expTypeMeta) {
|
||||||
}
|
t.Errorf("Server did not see correct TypeMeta. Got %v, expected %v",
|
||||||
|
serv.lastRequest.TypeMeta, expTypeMeta)
|
||||||
|
}
|
||||||
|
if authenticated != tt.expectedAuthenticated {
|
||||||
|
t.Errorf("Plugin returned incorrect authentication response. Got %t, expected %t.",
|
||||||
|
authenticated, tt.expectedAuthenticated)
|
||||||
|
}
|
||||||
|
if resp != nil && tt.expectedUser != nil && !reflect.DeepEqual(resp.User, tt.expectedUser) {
|
||||||
|
t.Errorf("Plugin returned incorrect user. Got %#v, expected %#v",
|
||||||
|
resp.User, tt.expectedUser)
|
||||||
|
}
|
||||||
|
if resp != nil && tt.expectedAuds != nil && !reflect.DeepEqual(resp.Audiences, tt.expectedAuds) {
|
||||||
|
t.Errorf("Plugin returned incorrect audiences. Got %#v, expected %#v",
|
||||||
|
resp.Audiences, tt.expectedAuds)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,7 +557,7 @@ func TestWebhookCacheAndRetry(t *testing.T) {
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
|
||||||
// Create an authenticator that caches successful responses "forever" (100 days).
|
// Create an authenticator that caches successful responses "forever" (100 days).
|
||||||
wh, err := newTokenAuthenticator(s.URL, clientCert, clientKey, caCert, 2400*time.Hour)
|
wh, err := newTokenAuthenticator(s.URL, clientCert, clientKey, caCert, 2400*time.Hour, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ func getTestWebhookTokenAuth(serverURL string) (authenticator.Request, error) {
|
||||||
if err := json.NewEncoder(kubecfgFile).Encode(config); err != nil {
|
if err := json.NewEncoder(kubecfgFile).Encode(config); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
webhookTokenAuth, err := webhook.New(kubecfgFile.Name())
|
webhookTokenAuth, err := webhook.New(kubecfgFile.Name(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue