mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-16 07:13:53 +00:00
Allow short-circuiting union auth on error
This commit is contained in:
parent
0f3baaad50
commit
174e454874
@ -25,26 +25,40 @@ import (
|
||||
)
|
||||
|
||||
// unionAuthRequestHandler authenticates requests using a chain of authenticator.Requests
|
||||
type unionAuthRequestHandler []authenticator.Request
|
||||
|
||||
// New returns a request authenticator that validates credentials using a chain of authenticator.Request objects
|
||||
func New(authRequestHandlers ...authenticator.Request) authenticator.Request {
|
||||
return unionAuthRequestHandler(authRequestHandlers)
|
||||
type unionAuthRequestHandler struct {
|
||||
// Handlers is a chain of request authenticators to delegate to
|
||||
Handlers []authenticator.Request
|
||||
// FailOnError determines whether an error returns short-circuits the chain
|
||||
FailOnError bool
|
||||
}
|
||||
|
||||
// AuthenticateRequest authenticates the request using a chain of authenticator.Request objects. The first
|
||||
// success returns that identity. Errors are only returned if no matches are found.
|
||||
func (authHandler unionAuthRequestHandler) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
|
||||
// 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 {
|
||||
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 {
|
||||
return &unionAuthRequestHandler{Handlers: authRequestHandlers, FailOnError: true}
|
||||
}
|
||||
|
||||
// AuthenticateRequest authenticates the request using a chain of authenticator.Request objects.
|
||||
func (authHandler *unionAuthRequestHandler) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
|
||||
var errlist []error
|
||||
for _, currAuthRequestHandler := range authHandler {
|
||||
for _, currAuthRequestHandler := range authHandler.Handlers {
|
||||
info, ok, err := currAuthRequestHandler.AuthenticateRequest(req)
|
||||
if err != nil {
|
||||
if authHandler.FailOnError {
|
||||
return info, ok, err
|
||||
}
|
||||
errlist = append(errlist, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if ok {
|
||||
return info, true, nil
|
||||
return info, ok, err
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,3 +143,24 @@ func TestAuthenticateRequestAdditiveErrors(t *testing.T) {
|
||||
t.Errorf("Unexpectedly authenticated: %v", isAuthenticated)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthenticateRequestFailEarly(t *testing.T) {
|
||||
handler1 := &mockAuthRequestHandler{err: errors.New("first")}
|
||||
handler2 := &mockAuthRequestHandler{err: errors.New("second")}
|
||||
authRequestHandler := NewFailOnError(handler1, handler2)
|
||||
req, _ := http.NewRequest("GET", "http://example.org", nil)
|
||||
|
||||
_, isAuthenticated, err := authRequestHandler.AuthenticateRequest(req)
|
||||
if err == nil {
|
||||
t.Errorf("Expected an error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "first") {
|
||||
t.Errorf("Expected error containing %v, got %v", "first", err)
|
||||
}
|
||||
if strings.Contains(err.Error(), "second") {
|
||||
t.Errorf("Did not expect second error, got %v", err)
|
||||
}
|
||||
if isAuthenticated {
|
||||
t.Errorf("Unexpectedly authenticated: %v", isAuthenticated)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user