ContainerImage.Pinniped/internal/oidc/provider/manager/manager.go
Andrew Keesler 05141592f8 Refactor provider.Manager
- And also handle when an issuer's path is a subpath of another issuer

Signed-off-by: Ryan Richard <richardry@vmware.com>
2020-10-08 14:40:56 -07:00

78 lines
2.6 KiB
Go

// Copyright 2020 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package manager
import (
"net/http"
"sync"
"k8s.io/klog/v2"
"go.pinniped.dev/internal/oidc"
"go.pinniped.dev/internal/oidc/discovery"
"go.pinniped.dev/internal/oidc/provider"
)
// Manager can manage multiple active OIDC providers. It acts as a request router for them.
//
// It is thread-safe.
type Manager struct {
mu sync.RWMutex
providers []*provider.OIDCProvider
providerHandlers map[string]http.Handler // map of all routes for all providers
nextHandler http.Handler // the next handler in a chain, called when this manager didn't know how to handle a request
}
// NewManager returns an empty Manager.
// nextHandler will be invoked for any requests that could not be handled by this manager's providers.
func NewManager(nextHandler http.Handler) *Manager {
return &Manager{providerHandlers: make(map[string]http.Handler), nextHandler: nextHandler}
}
// SetProviders adds or updates all the given providerHandlers using each provider's issuer string
// as the name of the provider to decide if it is an add or update operation.
//
// It also removes any providerHandlers that were previously added but were not passed in to
// the current invocation.
//
// This method assumes that all of the OIDCProvider arguments have already been validated
// by someone else before they are passed to this method.
func (m *Manager) SetProviders(oidcProviders ...*provider.OIDCProvider) {
m.mu.Lock()
defer m.mu.Unlock()
m.providers = oidcProviders
m.providerHandlers = make(map[string]http.Handler)
for _, incomingProvider := range oidcProviders {
m.providerHandlers[incomingProvider.IssuerHost()+"/"+incomingProvider.IssuerPath()+oidc.WellKnownEndpointPath] = discovery.New(incomingProvider.Issuer())
klog.InfoS("oidc provider manager added or updated issuer", "issuer", incomingProvider.Issuer())
}
}
// ServeHTTP implements the http.Handler interface.
func (m *Manager) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
requestHandler := m.findHandler(req)
klog.InfoS(
"oidc provider manager examining request",
"method", req.Method,
"host", req.Host,
"path", req.URL.Path,
"foundMatchingIssuer", requestHandler != nil,
)
if requestHandler == nil {
requestHandler = m.nextHandler // couldn't find an issuer to handle the request
}
requestHandler.ServeHTTP(resp, req)
}
func (m *Manager) findHandler(req *http.Request) http.Handler {
m.mu.RLock()
defer m.mu.RUnlock()
return m.providerHandlers[req.Host+"/"+req.URL.Path]
}