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{ ServiceAccounts: &kubeoptions.ServiceAccountAuthenticationOptions{
Lookup: true, Lookup: true,
}, },
TokenFile: &kubeoptions.TokenFileAuthenticationOptions{}, TokenFile: &kubeoptions.TokenFileAuthenticationOptions{},
TokenSuccessCacheTTL: 10 * time.Second,
TokenFailureCacheTTL: 0,
}, },
Authorization: &kubeoptions.BuiltInAuthorizationOptions{ Authorization: &kubeoptions.BuiltInAuthorizationOptions{
Mode: "AlwaysDeny", 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/union:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authentication/request/websocket: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/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/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/keystone:go_default_library",
"//vendor/k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile: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", "//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/union"
"k8s.io/apiserver/pkg/authentication/request/websocket" "k8s.io/apiserver/pkg/authentication/request/websocket"
"k8s.io/apiserver/pkg/authentication/request/x509" "k8s.io/apiserver/pkg/authentication/request/x509"
tokencache "k8s.io/apiserver/pkg/authentication/token/cache"
"k8s.io/apiserver/pkg/authentication/token/tokenfile" "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/keystone"
"k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile" "k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile"
"k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth" "k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth"
@ -62,6 +64,9 @@ type AuthenticatorConfig struct {
WebhookTokenAuthnConfigFile string WebhookTokenAuthnConfigFile string
WebhookTokenAuthnCacheTTL time.Duration WebhookTokenAuthnCacheTTL time.Duration
TokenSuccessCacheTTL time.Duration
TokenFailureCacheTTL time.Duration
RequestHeaderConfig *authenticatorfactory.RequestHeaderConfig RequestHeaderConfig *authenticatorfactory.RequestHeaderConfig
// TODO, this is the only non-serializable part of the entire config. Factor it out into a clientconfig // 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. // Kubernetes authentication mechanisms.
func (config AuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDefinitions, error) { func (config AuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDefinitions, error) {
var authenticators []authenticator.Request var authenticators []authenticator.Request
var tokenAuthenticators []authenticator.Token
securityDefinitions := spec.SecurityDefinitions{} securityDefinitions := spec.SecurityDefinitions{}
hasBasicAuth := false hasBasicAuth := false
hasTokenAuth := false
// front-proxy, BasicAuth methods, local first, then remote // front-proxy, BasicAuth methods, local first, then remote
// Add the front proxy authenticator if requested // Add the front proxy authenticator if requested
@ -125,22 +130,19 @@ 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, bearertoken.New(tokenAuth), websocket.NewProtocolAuthenticator(tokenAuth)) tokenAuthenticators = append(tokenAuthenticators, tokenAuth)
hasTokenAuth = true
} }
if len(config.ServiceAccountKeyFiles) > 0 { if len(config.ServiceAccountKeyFiles) > 0 {
serviceAccountAuth, err := newServiceAccountAuthenticator(config.ServiceAccountKeyFiles, config.ServiceAccountLookup, config.ServiceAccountTokenGetter) serviceAccountAuth, err := newServiceAccountAuthenticator(config.ServiceAccountKeyFiles, config.ServiceAccountLookup, config.ServiceAccountTokenGetter)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
authenticators = append(authenticators, bearertoken.New(serviceAccountAuth), websocket.NewProtocolAuthenticator(serviceAccountAuth)) tokenAuthenticators = append(tokenAuthenticators, serviceAccountAuth)
hasTokenAuth = true
} }
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
authenticators = append(authenticators, bearertoken.New(config.BootstrapTokenAuthenticator), websocket.NewProtocolAuthenticator(config.BootstrapTokenAuthenticator)) tokenAuthenticators = append(tokenAuthenticators, config.BootstrapTokenAuthenticator)
hasTokenAuth = true
} }
} }
// NOTE(ericchiang): Keep the OpenID Connect after Service Accounts. // NOTE(ericchiang): Keep the OpenID Connect after Service Accounts.
@ -154,16 +156,14 @@ 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, bearertoken.New(oidcAuth), websocket.NewProtocolAuthenticator(oidcAuth)) tokenAuthenticators = append(tokenAuthenticators, oidcAuth)
hasTokenAuth = true
} }
if len(config.WebhookTokenAuthnConfigFile) > 0 { if len(config.WebhookTokenAuthnConfigFile) > 0 {
webhookTokenAuth, err := newWebhookTokenAuthenticator(config.WebhookTokenAuthnConfigFile, config.WebhookTokenAuthnCacheTTL) webhookTokenAuth, err := newWebhookTokenAuthenticator(config.WebhookTokenAuthnConfigFile, config.WebhookTokenAuthnCacheTTL)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
authenticators = append(authenticators, bearertoken.New(webhookTokenAuth), websocket.NewProtocolAuthenticator(webhookTokenAuth)) tokenAuthenticators = append(tokenAuthenticators, webhookTokenAuth)
hasTokenAuth = true
} }
if hasBasicAuth { 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{ securityDefinitions["BearerToken"] = &spec.SecurityScheme{
SecuritySchemeProps: spec.SecuritySchemeProps{ SecuritySchemeProps: spec.SecuritySchemeProps{
Type: "apiKey", Type: "apiKey",

View File

@ -41,6 +41,9 @@ type BuiltInAuthenticationOptions struct {
ServiceAccounts *ServiceAccountAuthenticationOptions ServiceAccounts *ServiceAccountAuthenticationOptions
TokenFile *TokenFileAuthenticationOptions TokenFile *TokenFileAuthenticationOptions
WebHook *WebHookAuthenticationOptions WebHook *WebHookAuthenticationOptions
TokenSuccessCacheTTL time.Duration
TokenFailureCacheTTL time.Duration
} }
type AnonymousAuthenticationOptions struct { type AnonymousAuthenticationOptions struct {
@ -83,7 +86,10 @@ type WebHookAuthenticationOptions struct {
} }
func NewBuiltInAuthenticationOptions() *BuiltInAuthenticationOptions { func NewBuiltInAuthenticationOptions() *BuiltInAuthenticationOptions {
return &BuiltInAuthenticationOptions{} return &BuiltInAuthenticationOptions{
TokenSuccessCacheTTL: 10 * time.Second,
TokenFailureCacheTTL: 0 * time.Second,
}
} }
func (s *BuiltInAuthenticationOptions) WithAll() *BuiltInAuthenticationOptions { func (s *BuiltInAuthenticationOptions) WithAll() *BuiltInAuthenticationOptions {
@ -250,7 +256,10 @@ func (s *BuiltInAuthenticationOptions) AddFlags(fs *pflag.FlagSet) {
} }
func (s *BuiltInAuthenticationOptions) ToAuthenticationConfig() authenticator.AuthenticatorConfig { func (s *BuiltInAuthenticationOptions) ToAuthenticationConfig() authenticator.AuthenticatorConfig {
ret := authenticator.AuthenticatorConfig{} ret := authenticator.AuthenticatorConfig{
TokenSuccessCacheTTL: s.TokenSuccessCacheTTL,
TokenFailureCacheTTL: s.TokenFailureCacheTTL,
}
if s.Anonymous != nil { if s.Anonymous != nil {
ret.Anonymous = s.Anonymous.Allow ret.Anonymous = s.Anonymous.Allow
@ -297,6 +306,15 @@ func (s *BuiltInAuthenticationOptions) ToAuthenticationConfig() authenticator.Au
if s.WebHook != nil { if s.WebHook != nil {
ret.WebhookTokenAuthnConfigFile = s.WebHook.ConfigFile ret.WebhookTokenAuthnConfigFile = s.WebHook.ConfigFile
ret.WebhookTokenAuthnCacheTTL = s.WebHook.CacheTTL 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 return ret