Add anonymous auth to the auth chain

This commit is contained in:
Jordan Liggitt 2016-09-09 10:18:08 -04:00
parent 174e454874
commit 0c36c5e556
No known key found for this signature in database
GPG Key ID: 24E7ADF9A3B42012
6 changed files with 41 additions and 17 deletions

View File

@ -201,6 +201,7 @@ func Run(s *options.APIServer) error {
} }
apiAuthenticator, err := authenticator.New(authenticator.AuthenticatorConfig{ apiAuthenticator, err := authenticator.New(authenticator.AuthenticatorConfig{
Anonymous: s.AnonymousAuth,
BasicAuthFile: s.BasicAuthFile, BasicAuthFile: s.BasicAuthFile,
ClientCAFile: s.ClientCAFile, ClientCAFile: s.ClientCAFile,
TokenAuthFile: s.TokenAuthFile, TokenAuthFile: s.TokenAuthFile,

View File

@ -115,6 +115,7 @@ func Run(s *options.ServerRunOptions) error {
} }
apiAuthenticator, err := authenticator.New(authenticator.AuthenticatorConfig{ apiAuthenticator, err := authenticator.New(authenticator.AuthenticatorConfig{
Anonymous: s.AnonymousAuth,
BasicAuthFile: s.BasicAuthFile, BasicAuthFile: s.BasicAuthFile,
ClientCAFile: s.ClientCAFile, ClientCAFile: s.ClientCAFile,
TokenAuthFile: s.TokenAuthFile, TokenAuthFile: s.TokenAuthFile,

View File

@ -9,6 +9,7 @@ all-namespaces
allocate-node-cidrs allocate-node-cidrs
allow-privileged allow-privileged
allowed-not-ready-nodes allowed-not-ready-nodes
anonymous-auth
api-advertise-addresses api-advertise-addresses
api-external-dns-names api-external-dns-names
api-burst api-burst

View File

@ -27,6 +27,7 @@ import (
certutil "k8s.io/kubernetes/pkg/util/cert" certutil "k8s.io/kubernetes/pkg/util/cert"
"k8s.io/kubernetes/plugin/pkg/auth/authenticator/password/keystone" "k8s.io/kubernetes/plugin/pkg/auth/authenticator/password/keystone"
"k8s.io/kubernetes/plugin/pkg/auth/authenticator/password/passwordfile" "k8s.io/kubernetes/plugin/pkg/auth/authenticator/password/passwordfile"
"k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/anonymous"
"k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/basicauth" "k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/basicauth"
"k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/union" "k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/union"
"k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/x509" "k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/x509"
@ -36,6 +37,7 @@ import (
) )
type AuthenticatorConfig struct { type AuthenticatorConfig struct {
Anonymous bool
BasicAuthFile string BasicAuthFile string
ClientCAFile string ClientCAFile string
TokenAuthFile string TokenAuthFile string
@ -57,6 +59,7 @@ type AuthenticatorConfig struct {
func New(config AuthenticatorConfig) (authenticator.Request, error) { func New(config AuthenticatorConfig) (authenticator.Request, error) {
var authenticators []authenticator.Request var authenticators []authenticator.Request
// BasicAuth methods, local first, then remote
if len(config.BasicAuthFile) > 0 { if len(config.BasicAuthFile) > 0 {
basicAuth, err := newAuthenticatorFromBasicAuthFile(config.BasicAuthFile) basicAuth, err := newAuthenticatorFromBasicAuthFile(config.BasicAuthFile)
if err != nil { if err != nil {
@ -64,7 +67,15 @@ func New(config AuthenticatorConfig) (authenticator.Request, error) {
} }
authenticators = append(authenticators, basicAuth) authenticators = append(authenticators, basicAuth)
} }
if len(config.KeystoneURL) > 0 {
keystoneAuth, err := newAuthenticatorFromKeystoneURL(config.KeystoneURL)
if err != nil {
return nil, err
}
authenticators = append(authenticators, keystoneAuth)
}
// X509 methods
if len(config.ClientCAFile) > 0 { if len(config.ClientCAFile) > 0 {
certAuth, err := newAuthenticatorFromClientCAFile(config.ClientCAFile) certAuth, err := newAuthenticatorFromClientCAFile(config.ClientCAFile)
if err != nil { if err != nil {
@ -73,6 +84,7 @@ func New(config AuthenticatorConfig) (authenticator.Request, error) {
authenticators = append(authenticators, certAuth) authenticators = append(authenticators, certAuth)
} }
// Bearer token methods, local first, then remote
if len(config.TokenAuthFile) > 0 { if len(config.TokenAuthFile) > 0 {
tokenAuth, err := newAuthenticatorFromTokenFile(config.TokenAuthFile) tokenAuth, err := newAuthenticatorFromTokenFile(config.TokenAuthFile)
if err != nil { if err != nil {
@ -80,7 +92,6 @@ func New(config AuthenticatorConfig) (authenticator.Request, error) {
} }
authenticators = append(authenticators, tokenAuth) authenticators = append(authenticators, tokenAuth)
} }
if len(config.ServiceAccountKeyFile) > 0 { if len(config.ServiceAccountKeyFile) > 0 {
serviceAccountAuth, err := newServiceAccountAuthenticator(config.ServiceAccountKeyFile, config.ServiceAccountLookup, config.ServiceAccountTokenGetter) serviceAccountAuth, err := newServiceAccountAuthenticator(config.ServiceAccountKeyFile, config.ServiceAccountLookup, config.ServiceAccountTokenGetter)
if err != nil { if err != nil {
@ -88,7 +99,6 @@ func New(config AuthenticatorConfig) (authenticator.Request, error) {
} }
authenticators = append(authenticators, serviceAccountAuth) authenticators = append(authenticators, serviceAccountAuth)
} }
// NOTE(ericchiang): Keep the OpenID Connect after Service Accounts. // NOTE(ericchiang): Keep the OpenID Connect after Service Accounts.
// //
// Because both plugins verify JWTs whichever comes first in the union experiences // Because both plugins verify JWTs whichever comes first in the union experiences
@ -102,15 +112,6 @@ func New(config AuthenticatorConfig) (authenticator.Request, error) {
} }
authenticators = append(authenticators, oidcAuth) authenticators = append(authenticators, oidcAuth)
} }
if len(config.KeystoneURL) > 0 {
keystoneAuth, err := newAuthenticatorFromKeystoneURL(config.KeystoneURL)
if err != nil {
return nil, err
}
authenticators = append(authenticators, keystoneAuth)
}
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 {
@ -119,14 +120,21 @@ func New(config AuthenticatorConfig) (authenticator.Request, error) {
authenticators = append(authenticators, webhookTokenAuth) authenticators = append(authenticators, webhookTokenAuth)
} }
switch len(authenticators) { if len(authenticators) == 0 {
case 0: if config.Anonymous {
return nil, nil return anonymous.NewAuthenticator(), nil
case 1:
return authenticators[0], nil
default:
return union.New(authenticators...), nil
} }
return nil, nil
}
authenticator := union.New(authenticators...)
if config.Anonymous {
// If the authenticator chain returns an error, return an error (don't consider a bad bearer token anonymous).
authenticator = union.NewFailOnError(authenticator, anonymous.NewAuthenticator())
}
return authenticator, nil
} }
// IsValidServiceAccountKeyFile returns true if a valid public RSA key can be read from the given file // IsValidServiceAccountKeyFile returns true if a valid public RSA key can be read from the given file

View File

@ -71,6 +71,7 @@ type ServerRunOptions struct {
AuthorizationWebhookCacheUnauthorizedTTL time.Duration AuthorizationWebhookCacheUnauthorizedTTL time.Duration
AuthorizationRBACSuperUser string AuthorizationRBACSuperUser string
AnonymousAuth bool
BasicAuthFile string BasicAuthFile string
BindAddress net.IP BindAddress net.IP
CertDirectory string CertDirectory string
@ -127,6 +128,7 @@ func NewServerRunOptions() *ServerRunOptions {
APIGroupPrefix: "/apis", APIGroupPrefix: "/apis",
APIPrefix: "/api", APIPrefix: "/api",
AdmissionControl: "AlwaysAdmit", AdmissionControl: "AlwaysAdmit",
AnonymousAuth: true,
AuthorizationMode: "AlwaysAllow", AuthorizationMode: "AlwaysAllow",
AuthorizationWebhookCacheAuthorizedTTL: 5 * time.Minute, AuthorizationWebhookCacheAuthorizedTTL: 5 * time.Minute,
AuthorizationWebhookCacheUnauthorizedTTL: 30 * time.Second, AuthorizationWebhookCacheUnauthorizedTTL: 30 * time.Second,
@ -269,6 +271,11 @@ func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
"If specified, a username which avoids RBAC authorization checks and role binding "+ "If specified, a username which avoids RBAC authorization checks and role binding "+
"privilege escalation checks, to be used with --authorization-mode=RBAC.") "privilege escalation checks, to be used with --authorization-mode=RBAC.")
fs.BoolVar(&s.AnonymousAuth, "anonymous-auth", s.AnonymousAuth, ""+
"Enables anonymous requests to the secure port of the API server. "+
"Requests that are not rejected by another authentication method are treated as anonymous requests. "+
"Anonymous requests have a username of system:anonymous, and a group name of system:unauthenticated.")
fs.StringVar(&s.BasicAuthFile, "basic-auth-file", s.BasicAuthFile, ""+ fs.StringVar(&s.BasicAuthFile, "basic-auth-file", s.BasicAuthFile, ""+
"If set, the file that will be used to admit requests to the secure port of the API server "+ "If set, the file that will be used to admit requests to the secure port of the API server "+
"via http basic authentication.") "via http basic authentication.")

View File

@ -35,12 +35,18 @@ type unionAuthRequestHandler struct {
// New returns a request authenticator that validates credentials using a chain of authenticator.Request objects. // New returns a request authenticator that validates credentials using a chain of authenticator.Request objects.
// The entire chain is tried until one succeeds. If all fail, an aggregate error is returned. // The entire chain is tried until one succeeds. If all fail, an aggregate error is returned.
func New(authRequestHandlers ...authenticator.Request) authenticator.Request { func New(authRequestHandlers ...authenticator.Request) authenticator.Request {
if len(authRequestHandlers) == 1 {
return authRequestHandlers[0]
}
return &unionAuthRequestHandler{Handlers: authRequestHandlers, FailOnError: false} return &unionAuthRequestHandler{Handlers: authRequestHandlers, FailOnError: false}
} }
// NewFailOnError returns a request authenticator that validates credentials using a chain of authenticator.Request objects. // NewFailOnError returns a request authenticator that validates credentials using a chain of authenticator.Request objects.
// The first error short-circuits the chain. // The first error short-circuits the chain.
func NewFailOnError(authRequestHandlers ...authenticator.Request) authenticator.Request { func NewFailOnError(authRequestHandlers ...authenticator.Request) authenticator.Request {
if len(authRequestHandlers) == 1 {
return authRequestHandlers[0]
}
return &unionAuthRequestHandler{Handlers: authRequestHandlers, FailOnError: true} return &unionAuthRequestHandler{Handlers: authRequestHandlers, FailOnError: true}
} }