Make /db/info available anonymously from localhost

Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
This commit is contained in:
Brad Davidson 2024-04-22 20:23:34 +00:00 committed by Brad Davidson
parent d3b60543e7
commit 94e29e2ef5
3 changed files with 36 additions and 11 deletions

View File

@ -664,12 +664,18 @@ func (e *ETCD) setName(force bool) error {
// handler wraps the handler with routes for database info
func (e *ETCD) handler(next http.Handler) http.Handler {
mux := mux.NewRouter().SkipClean(true)
mux.Use(auth.Middleware(e.config, version.Program+":server"))
mux.Handle("/db/info", e.infoHandler())
mux.Handle("/db/snapshot", e.snapshotHandler())
mux.NotFoundHandler = next
return mux
r := mux.NewRouter().SkipClean(true)
r.NotFoundHandler = next
ir := r.Path("/db/info").Subrouter()
ir.Use(auth.IsLocalOrHasRole(e.config, version.Program+":server"))
ir.Handle("", e.infoHandler())
sr := r.Path("/db/snapshot").Subrouter()
sr.Use(auth.HasRole(e.config, version.Program+":server"))
sr.Handle("", e.snapshotHandler())
return r
}
// infoHandler returns etcd cluster information. This is used by new members when joining the cluster.

View File

@ -1,6 +1,7 @@
package auth
import (
"net"
"net/http"
"github.com/gorilla/mux"
@ -22,6 +23,7 @@ func hasRole(mustRoles []string, roles []string) bool {
return false
}
// doAuth calls the cluster's authenticator to validate that the client has at least one of the listed roles
func doAuth(roles []string, serverConfig *config.Control, next http.Handler, rw http.ResponseWriter, req *http.Request) {
switch {
case serverConfig == nil:
@ -51,10 +53,27 @@ func doAuth(roles []string, serverConfig *config.Control, next http.Handler, rw
next.ServeHTTP(rw, req)
}
func Middleware(serverConfig *config.Control, roles ...string) mux.MiddlewareFunc {
// HasRole returns a middleware function that validates that the request
// is being made with at least one of the listed roles.
func HasRole(serverConfig *config.Control, roles ...string) mux.MiddlewareFunc {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
doAuth(roles, serverConfig, next, rw, req)
})
}
}
// IsLocalOrHasRole returns a middleware function that validates that the request
// is from a local client or has at least one of the listed roles.
func IsLocalOrHasRole(serverConfig *config.Control, roles ...string) mux.MiddlewareFunc {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
client, _, _ := net.SplitHostPort(req.RemoteAddr)
if client == "127.0.0.1" || client == "::1" {
next.ServeHTTP(rw, req)
} else {
doAuth(roles, serverConfig, next, rw, req)
}
})
}
}

View File

@ -52,7 +52,7 @@ func router(ctx context.Context, config *Config, cfg *cmds.Server) http.Handler
prefix := "/v1-" + version.Program
authed := mux.NewRouter().SkipClean(true)
authed.Use(auth.Middleware(serverConfig, version.Program+":agent", user.NodesGroup, bootstrapapi.BootstrapDefaultGroup))
authed.Use(auth.HasRole(serverConfig, version.Program+":agent", user.NodesGroup, bootstrapapi.BootstrapDefaultGroup))
authed.Path(prefix + "/serving-kubelet.crt").Handler(servingKubeletCert(serverConfig, serverConfig.Runtime.ServingKubeletKey, nodeAuth))
authed.Path(prefix + "/client-kubelet.crt").Handler(clientKubeletCert(serverConfig, serverConfig.Runtime.ClientKubeletKey, nodeAuth))
authed.Path(prefix + "/client-kube-proxy.crt").Handler(fileHandler(serverConfig.Runtime.ClientKubeProxyCert, serverConfig.Runtime.ClientKubeProxyKey))
@ -71,12 +71,12 @@ func router(ctx context.Context, config *Config, cfg *cmds.Server) http.Handler
nodeAuthed := mux.NewRouter().SkipClean(true)
nodeAuthed.NotFoundHandler = authed
nodeAuthed.Use(auth.Middleware(serverConfig, user.NodesGroup))
nodeAuthed.Use(auth.HasRole(serverConfig, user.NodesGroup))
nodeAuthed.Path(prefix + "/connect").Handler(serverConfig.Runtime.Tunnel)
serverAuthed := mux.NewRouter().SkipClean(true)
serverAuthed.NotFoundHandler = nodeAuthed
serverAuthed.Use(auth.Middleware(serverConfig, version.Program+":server"))
serverAuthed.Use(auth.HasRole(serverConfig, version.Program+":server"))
serverAuthed.Path(prefix + "/encrypt/status").Handler(encryptionStatusHandler(serverConfig))
serverAuthed.Path(prefix + "/encrypt/config").Handler(encryptionConfigHandler(ctx, serverConfig))
serverAuthed.Path(prefix + "/cert/cacerts").Handler(caCertReplaceHandler(serverConfig))
@ -86,7 +86,7 @@ func router(ctx context.Context, config *Config, cfg *cmds.Server) http.Handler
systemAuthed := mux.NewRouter().SkipClean(true)
systemAuthed.NotFoundHandler = serverAuthed
systemAuthed.MethodNotAllowedHandler = serverAuthed
systemAuthed.Use(auth.Middleware(serverConfig, user.SystemPrivilegedGroup))
systemAuthed.Use(auth.HasRole(serverConfig, user.SystemPrivilegedGroup))
systemAuthed.Methods(http.MethodConnect).Handler(serverConfig.Runtime.Tunnel)
staticDir := filepath.Join(serverConfig.DataDir, "static")