Simplify bearer token auth chain, cache successful authentications

This commit is contained in:
Jordan Liggitt 2017-08-07 11:55:35 -04:00
parent 4fd8196cf5
commit 0458fac8c0
No known key found for this signature in database
GPG Key ID: 39928704103C7229
4 changed files with 44 additions and 15 deletions

View File

@ -166,7 +166,9 @@ func TestAddFlagsFlag(t *testing.T) {
ServiceAccounts: &kubeoptions.ServiceAccountAuthenticationOptions{
Lookup: true,
},
TokenFile: &kubeoptions.TokenFileAuthenticationOptions{},
TokenFile: &kubeoptions.TokenFileAuthenticationOptions{},
TokenSuccessCacheTTL: 10 * time.Second,
TokenFailureCacheTTL: 0,
},
Authorization: &kubeoptions.BuiltInAuthorizationOptions{
Mode: "AlwaysDeny",

View File

@ -23,7 +23,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",

View File

@ -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",

View File

@ -41,6 +41,9 @@ type BuiltInAuthenticationOptions struct {
ServiceAccounts *ServiceAccountAuthenticationOptions
TokenFile *TokenFileAuthenticationOptions
WebHook *WebHookAuthenticationOptions
TokenSuccessCacheTTL time.Duration
TokenFailureCacheTTL time.Duration
}
type AnonymousAuthenticationOptions struct {
@ -83,7 +86,10 @@ type WebHookAuthenticationOptions struct {
}
func NewBuiltInAuthenticationOptions() *BuiltInAuthenticationOptions {
return &BuiltInAuthenticationOptions{}
return &BuiltInAuthenticationOptions{
TokenSuccessCacheTTL: 10 * time.Second,
TokenFailureCacheTTL: 0 * time.Second,
}
}
func (s *BuiltInAuthenticationOptions) WithAll() *BuiltInAuthenticationOptions {
@ -250,7 +256,10 @@ func (s *BuiltInAuthenticationOptions) AddFlags(fs *pflag.FlagSet) {
}
func (s *BuiltInAuthenticationOptions) ToAuthenticationConfig() authenticator.AuthenticatorConfig {
ret := authenticator.AuthenticatorConfig{}
ret := authenticator.AuthenticatorConfig{
TokenSuccessCacheTTL: s.TokenSuccessCacheTTL,
TokenFailureCacheTTL: s.TokenFailureCacheTTL,
}
if s.Anonymous != nil {
ret.Anonymous = s.Anonymous.Allow
@ -297,6 +306,15 @@ func (s *BuiltInAuthenticationOptions) ToAuthenticationConfig() authenticator.Au
if s.WebHook != nil {
ret.WebhookTokenAuthnConfigFile = s.WebHook.ConfigFile
ret.WebhookTokenAuthnCacheTTL = s.WebHook.CacheTTL
if len(s.WebHook.ConfigFile) > 0 && s.WebHook.CacheTTL > 0 {
if s.TokenSuccessCacheTTL > 0 && s.WebHook.CacheTTL < s.TokenSuccessCacheTTL {
glog.Warningf("the webhook cache ttl of %s is shorter than the overall cache ttl of %s for successful token authentication attempts.", s.WebHook.CacheTTL, s.TokenSuccessCacheTTL)
}
if s.TokenFailureCacheTTL > 0 && s.WebHook.CacheTTL < s.TokenFailureCacheTTL {
glog.Warningf("the webhook cache ttl of %s is shorter than the overall cache ttl of %s for failed token authentication attempts.", s.WebHook.CacheTTL, s.TokenFailureCacheTTL)
}
}
}
return ret