183 lines
4.7 KiB
Go
183 lines
4.7 KiB
Go
package auth
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"github.com/gorilla/mux"
|
|
"github.com/rancher/norman/store/proxy"
|
|
"github.com/rancher/rancher/pkg/api/norman"
|
|
"github.com/rancher/rancher/pkg/auth/api"
|
|
"github.com/rancher/rancher/pkg/auth/data"
|
|
"github.com/rancher/rancher/pkg/auth/providerrefresh"
|
|
"github.com/rancher/rancher/pkg/auth/providers/common"
|
|
"github.com/rancher/rancher/pkg/auth/providers/publicapi"
|
|
"github.com/rancher/rancher/pkg/auth/providers/saml"
|
|
"github.com/rancher/rancher/pkg/auth/requests"
|
|
"github.com/rancher/rancher/pkg/auth/tokens"
|
|
"github.com/rancher/rancher/pkg/clusterrouter"
|
|
"github.com/rancher/rancher/pkg/features"
|
|
"github.com/rancher/rancher/pkg/types/config"
|
|
steveauth "github.com/rancher/steve/pkg/auth"
|
|
"github.com/sirupsen/logrus"
|
|
"k8s.io/apiserver/pkg/endpoints/request"
|
|
"k8s.io/client-go/rest"
|
|
)
|
|
|
|
type Server struct {
|
|
Authenticator steveauth.Middleware
|
|
Management func(http.Handler) http.Handler
|
|
scaledContext *config.ScaledContext
|
|
}
|
|
|
|
func NewAlwaysAdmin() (*Server, error) {
|
|
return &Server{
|
|
Authenticator: steveauth.ToMiddleware(steveauth.AuthenticatorFunc(steveauth.AlwaysAdmin)),
|
|
Management: func(next http.Handler) http.Handler {
|
|
return next
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func NewHeaderAuth() (*Server, error) {
|
|
return &Server{
|
|
Authenticator: steveauth.ToMiddleware(steveauth.AuthenticatorFunc(steveauth.Impersonation)),
|
|
Management: func(next http.Handler) http.Handler {
|
|
return next
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func NewServer(ctx context.Context, cfg *rest.Config) (*Server, error) {
|
|
sc, err := config.NewScaledContext(*cfg, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
sc.UserManager, err = common.NewUserManagerNoBindings(sc)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
sc.ClientGetter, err = proxy.NewClientGetterFromConfig(*cfg)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
authenticator := requests.NewAuthenticator(ctx, clusterrouter.GetClusterID, sc)
|
|
authManagement, err := newAPIManagement(ctx, sc)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &Server{
|
|
Authenticator: requests.ToAuthMiddleware(authenticator),
|
|
Management: authManagement,
|
|
scaledContext: sc,
|
|
}, nil
|
|
}
|
|
|
|
func newAPIManagement(ctx context.Context, scaledContext *config.ScaledContext) (steveauth.Middleware, error) {
|
|
privateAPI, err := newPrivateAPI(ctx, scaledContext)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
publicAPI, err := publicapi.NewHandler(ctx, scaledContext, norman.ConfigureAPIUI)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
saml := saml.AuthHandler()
|
|
|
|
root := mux.NewRouter()
|
|
root.UseEncodedPath()
|
|
root.PathPrefix("/v3-public").Handler(publicAPI)
|
|
root.PathPrefix("/v1-saml").Handler(saml)
|
|
root.NotFoundHandler = privateAPI
|
|
|
|
return func(next http.Handler) http.Handler {
|
|
privateAPI.NotFoundHandler = next
|
|
return root
|
|
}, nil
|
|
}
|
|
|
|
func newPrivateAPI(ctx context.Context, scaledContext *config.ScaledContext) (*mux.Router, error) {
|
|
tokenAPI, err := tokens.NewAPIHandler(ctx, scaledContext, norman.ConfigureAPIUI)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
otherAPIs, err := api.NewNormanServer(ctx, clusterrouter.GetClusterID, scaledContext)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
root := mux.NewRouter()
|
|
root.UseEncodedPath()
|
|
root.Use(requests.NewAuthenticatedFilter)
|
|
root.PathPrefix("/v3/identit").Handler(tokenAPI)
|
|
root.PathPrefix("/v3/token").Handler(tokenAPI)
|
|
root.PathPrefix("/v3/authConfig").Handler(otherAPIs)
|
|
root.PathPrefix("/v3/principal").Handler(otherAPIs)
|
|
root.PathPrefix("/v3/user").Handler(otherAPIs)
|
|
root.PathPrefix("/v3/schema").Handler(otherAPIs)
|
|
root.PathPrefix("/v3/subscribe").Handler(otherAPIs)
|
|
return root, nil
|
|
}
|
|
|
|
func (s *Server) OnLeader(ctx context.Context) error {
|
|
if s.scaledContext == nil {
|
|
return nil
|
|
}
|
|
|
|
management := &config.ManagementContext{
|
|
Management: s.scaledContext.Management,
|
|
Core: s.scaledContext.Core,
|
|
}
|
|
|
|
if err := data.AuthConfigs(management); err != nil {
|
|
return fmt.Errorf("failed to add authconfig data: %v", err)
|
|
}
|
|
|
|
tokens.StartPurgeDaemon(ctx, management)
|
|
providerrefresh.StartRefreshDaemon(ctx, s.scaledContext, management)
|
|
logrus.Infof("Steve auth startup complete")
|
|
return nil
|
|
}
|
|
|
|
func (s *Server) Start(ctx context.Context, leader bool) error {
|
|
if s.scaledContext == nil {
|
|
return nil
|
|
}
|
|
|
|
if err := s.scaledContext.Start(ctx); err != nil {
|
|
return err
|
|
}
|
|
if leader {
|
|
return s.OnLeader(ctx)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func SetXAPICattleAuthHeader(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
|
if features.Auth.Enabled() {
|
|
user, ok := request.UserFrom(req.Context())
|
|
if ok {
|
|
ok = false
|
|
for _, group := range user.GetGroups() {
|
|
if group == "system:authenticated" {
|
|
ok = true
|
|
}
|
|
}
|
|
}
|
|
rw.Header().Set("X-API-Cattle-Auth", fmt.Sprint(ok))
|
|
} else {
|
|
rw.Header().Set("X-API-Cattle-Auth", "none")
|
|
}
|
|
next.ServeHTTP(rw, req)
|
|
})
|
|
}
|