Merge pull request #50258 from liggitt/token-cache
Automatic merge from submit-queue (batch tested with PRs 49488, 50407, 46105, 50456, 50258) Enable caching successful token authentication Resolves #50472 To support revocation of service account tokens, an etcd lookup of the token and service account is done by the token authenticator. Controllers that make dozens or hundreds of API calls per second (like the endpoints controller) cause this lookup to be done very frequently on the same objects. This PR: * Implements a cached token authenticator that conforms to the authenticator.Token interface * Implements a union token authenticator (same approach as the union request authenticator, conforming to the authenticator.Token interface) * Cleans up the auth chain construction to group all token authenticators (means we only do bearer and websocket header parsing once) * Adds a 10-second TTL cache to successful token authentication ```release-note API server authentication now caches successful bearer token authentication results for a few seconds. ```
This commit is contained in:
@@ -20,7 +20,9 @@ go_library(
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/request/union:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/request/websocket:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/request/x509:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/token/cache:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/token/tokenfile:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/token/union:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/plugin/pkg/authenticator/password/keystone:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth:go_default_library",
|
||||
|
@@ -30,7 +30,9 @@ import (
|
||||
"k8s.io/apiserver/pkg/authentication/request/union"
|
||||
"k8s.io/apiserver/pkg/authentication/request/websocket"
|
||||
"k8s.io/apiserver/pkg/authentication/request/x509"
|
||||
tokencache "k8s.io/apiserver/pkg/authentication/token/cache"
|
||||
"k8s.io/apiserver/pkg/authentication/token/tokenfile"
|
||||
tokenunion "k8s.io/apiserver/pkg/authentication/token/union"
|
||||
"k8s.io/apiserver/plugin/pkg/authenticator/password/keystone"
|
||||
"k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile"
|
||||
"k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth"
|
||||
@@ -62,6 +64,9 @@ type AuthenticatorConfig struct {
|
||||
WebhookTokenAuthnConfigFile string
|
||||
WebhookTokenAuthnCacheTTL time.Duration
|
||||
|
||||
TokenSuccessCacheTTL time.Duration
|
||||
TokenFailureCacheTTL time.Duration
|
||||
|
||||
RequestHeaderConfig *authenticatorfactory.RequestHeaderConfig
|
||||
|
||||
// TODO, this is the only non-serializable part of the entire config. Factor it out into a clientconfig
|
||||
@@ -73,9 +78,9 @@ type AuthenticatorConfig struct {
|
||||
// Kubernetes authentication mechanisms.
|
||||
func (config AuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDefinitions, error) {
|
||||
var authenticators []authenticator.Request
|
||||
var tokenAuthenticators []authenticator.Token
|
||||
securityDefinitions := spec.SecurityDefinitions{}
|
||||
hasBasicAuth := false
|
||||
hasTokenAuth := false
|
||||
|
||||
// front-proxy, BasicAuth methods, local first, then remote
|
||||
// Add the front proxy authenticator if requested
|
||||
@@ -125,22 +130,19 @@ func (config AuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDe
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
authenticators = append(authenticators, bearertoken.New(tokenAuth), websocket.NewProtocolAuthenticator(tokenAuth))
|
||||
hasTokenAuth = true
|
||||
tokenAuthenticators = append(tokenAuthenticators, tokenAuth)
|
||||
}
|
||||
if len(config.ServiceAccountKeyFiles) > 0 {
|
||||
serviceAccountAuth, err := newServiceAccountAuthenticator(config.ServiceAccountKeyFiles, config.ServiceAccountLookup, config.ServiceAccountTokenGetter)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
authenticators = append(authenticators, bearertoken.New(serviceAccountAuth), websocket.NewProtocolAuthenticator(serviceAccountAuth))
|
||||
hasTokenAuth = true
|
||||
tokenAuthenticators = append(tokenAuthenticators, serviceAccountAuth)
|
||||
}
|
||||
if config.BootstrapToken {
|
||||
if config.BootstrapTokenAuthenticator != nil {
|
||||
// TODO: This can sometimes be nil because of
|
||||
authenticators = append(authenticators, bearertoken.New(config.BootstrapTokenAuthenticator), websocket.NewProtocolAuthenticator(config.BootstrapTokenAuthenticator))
|
||||
hasTokenAuth = true
|
||||
tokenAuthenticators = append(tokenAuthenticators, config.BootstrapTokenAuthenticator)
|
||||
}
|
||||
}
|
||||
// NOTE(ericchiang): Keep the OpenID Connect after Service Accounts.
|
||||
@@ -154,16 +156,14 @@ func (config AuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDe
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
authenticators = append(authenticators, bearertoken.New(oidcAuth), websocket.NewProtocolAuthenticator(oidcAuth))
|
||||
hasTokenAuth = true
|
||||
tokenAuthenticators = append(tokenAuthenticators, oidcAuth)
|
||||
}
|
||||
if len(config.WebhookTokenAuthnConfigFile) > 0 {
|
||||
webhookTokenAuth, err := newWebhookTokenAuthenticator(config.WebhookTokenAuthnConfigFile, config.WebhookTokenAuthnCacheTTL)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
authenticators = append(authenticators, bearertoken.New(webhookTokenAuth), websocket.NewProtocolAuthenticator(webhookTokenAuth))
|
||||
hasTokenAuth = true
|
||||
tokenAuthenticators = append(tokenAuthenticators, webhookTokenAuth)
|
||||
}
|
||||
|
||||
if hasBasicAuth {
|
||||
@@ -175,7 +175,14 @@ func (config AuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDe
|
||||
}
|
||||
}
|
||||
|
||||
if hasTokenAuth {
|
||||
if len(tokenAuthenticators) > 0 {
|
||||
// Union the token authenticators
|
||||
tokenAuth := tokenunion.New(tokenAuthenticators...)
|
||||
// Optionally cache authentication results
|
||||
if config.TokenSuccessCacheTTL > 0 || config.TokenFailureCacheTTL > 0 {
|
||||
tokenAuth = tokencache.New(tokenAuth, config.TokenSuccessCacheTTL, config.TokenFailureCacheTTL)
|
||||
}
|
||||
authenticators = append(authenticators, bearertoken.New(tokenAuth), websocket.NewProtocolAuthenticator(tokenAuth))
|
||||
securityDefinitions["BearerToken"] = &spec.SecurityScheme{
|
||||
SecuritySchemeProps: spec.SecuritySchemeProps{
|
||||
Type: "apiKey",
|
||||
|
Reference in New Issue
Block a user