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{
Anonymous: s.AnonymousAuth,
BasicAuthFile: s.BasicAuthFile,
ClientCAFile: s.ClientCAFile,
TokenAuthFile: s.TokenAuthFile,

View File

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

View File

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

View File

@ -27,6 +27,7 @@ import (
certutil "k8s.io/kubernetes/pkg/util/cert"
"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/request/anonymous"
"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/x509"
@ -36,6 +37,7 @@ import (
)
type AuthenticatorConfig struct {
Anonymous bool
BasicAuthFile string
ClientCAFile string
TokenAuthFile string
@ -57,6 +59,7 @@ type AuthenticatorConfig struct {
func New(config AuthenticatorConfig) (authenticator.Request, error) {
var authenticators []authenticator.Request
// BasicAuth methods, local first, then remote
if len(config.BasicAuthFile) > 0 {
basicAuth, err := newAuthenticatorFromBasicAuthFile(config.BasicAuthFile)
if err != nil {
@ -64,7 +67,15 @@ func New(config AuthenticatorConfig) (authenticator.Request, error) {
}
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 {
certAuth, err := newAuthenticatorFromClientCAFile(config.ClientCAFile)
if err != nil {
@ -73,6 +84,7 @@ func New(config AuthenticatorConfig) (authenticator.Request, error) {
authenticators = append(authenticators, certAuth)
}
// Bearer token methods, local first, then remote
if len(config.TokenAuthFile) > 0 {
tokenAuth, err := newAuthenticatorFromTokenFile(config.TokenAuthFile)
if err != nil {
@ -80,7 +92,6 @@ func New(config AuthenticatorConfig) (authenticator.Request, error) {
}
authenticators = append(authenticators, tokenAuth)
}
if len(config.ServiceAccountKeyFile) > 0 {
serviceAccountAuth, err := newServiceAccountAuthenticator(config.ServiceAccountKeyFile, config.ServiceAccountLookup, config.ServiceAccountTokenGetter)
if err != nil {
@ -88,7 +99,6 @@ func New(config AuthenticatorConfig) (authenticator.Request, error) {
}
authenticators = append(authenticators, serviceAccountAuth)
}
// NOTE(ericchiang): Keep the OpenID Connect after Service Accounts.
//
// 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)
}
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 {
webhookTokenAuth, err := newWebhookTokenAuthenticator(config.WebhookTokenAuthnConfigFile, config.WebhookTokenAuthnCacheTTL)
if err != nil {
@ -119,14 +120,21 @@ func New(config AuthenticatorConfig) (authenticator.Request, error) {
authenticators = append(authenticators, webhookTokenAuth)
}
switch len(authenticators) {
case 0:
if len(authenticators) == 0 {
if config.Anonymous {
return anonymous.NewAuthenticator(), nil
}
return nil, nil
case 1:
return authenticators[0], nil
default:
return union.New(authenticators...), 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

View File

@ -71,6 +71,7 @@ type ServerRunOptions struct {
AuthorizationWebhookCacheUnauthorizedTTL time.Duration
AuthorizationRBACSuperUser string
AnonymousAuth bool
BasicAuthFile string
BindAddress net.IP
CertDirectory string
@ -127,6 +128,7 @@ func NewServerRunOptions() *ServerRunOptions {
APIGroupPrefix: "/apis",
APIPrefix: "/api",
AdmissionControl: "AlwaysAdmit",
AnonymousAuth: true,
AuthorizationMode: "AlwaysAllow",
AuthorizationWebhookCacheAuthorizedTTL: 5 * time.Minute,
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 "+
"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, ""+
"If set, the file that will be used to admit requests to the secure port of the API server "+
"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.
// The entire chain is tried until one succeeds. If all fail, an aggregate error is returned.
func New(authRequestHandlers ...authenticator.Request) authenticator.Request {
if len(authRequestHandlers) == 1 {
return authRequestHandlers[0]
}
return &unionAuthRequestHandler{Handlers: authRequestHandlers, FailOnError: false}
}
// NewFailOnError returns a request authenticator that validates credentials using a chain of authenticator.Request objects.
// The first error short-circuits the chain.
func NewFailOnError(authRequestHandlers ...authenticator.Request) authenticator.Request {
if len(authRequestHandlers) == 1 {
return authRequestHandlers[0]
}
return &unionAuthRequestHandler{Handlers: authRequestHandlers, FailOnError: true}
}