feat(server): role based authentication system (#2434)

- Parse toml configuration file, see https://github.com/qdm12/gluetun-wiki/blob/main/setup/advanced/control-server.md#authentication
- Retro-compatible with existing AND documented routes, until after v3.41 release
- Log a warning if an unprotected-by-default route is accessed unprotected
- Authentication methods: none, apikey, basic
- `genkey` command to generate API keys
- move log middleware to internal/server/middlewares/log

Co-authored-by: Joe Jose <45399349+joejose97@users.noreply.github.com>
This commit is contained in:
Quentin McGaw
2024-08-23 13:46:52 +00:00
parent cbfdb25190
commit 67ae5f5065
27 changed files with 943 additions and 24 deletions

View File

@@ -2,13 +2,17 @@ package server
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/server/middlewares/auth"
"github.com/qdm12/gluetun/internal/server/middlewares/log"
)
func newHandler(ctx context.Context, logger infoWarner, logging bool,
func newHandler(ctx context.Context, logger Logger, logging bool,
authSettings auth.Settings,
buildInfo models.BuildInformation,
vpnLooper VPNLooper,
pfGetter PortForwardedGetter,
@@ -17,7 +21,7 @@ func newHandler(ctx context.Context, logger infoWarner, logging bool,
publicIPLooper PublicIPLoop,
storage Storage,
ipv6Supported bool,
) http.Handler {
) (httpHandler http.Handler, err error) {
handler := &handler{}
vpn := newVPNHandler(ctx, vpnLooper, storage, ipv6Supported, logger)
@@ -29,16 +33,25 @@ func newHandler(ctx context.Context, logger infoWarner, logging bool,
handler.v0 = newHandlerV0(ctx, logger, vpnLooper, unboundLooper, updaterLooper)
handler.v1 = newHandlerV1(logger, buildInfo, vpn, openvpn, dns, updater, publicip)
handlerWithLog := withLogMiddleware(handler, logger, logging)
handler.setLogEnabled = handlerWithLog.setEnabled
authMiddleware, err := auth.New(authSettings, logger)
if err != nil {
return nil, fmt.Errorf("creating auth middleware: %w", err)
}
return handlerWithLog
middlewares := []func(http.Handler) http.Handler{
authMiddleware,
log.New(logger, logging),
}
httpHandler = handler
for _, middleware := range middlewares {
httpHandler = middleware(httpHandler)
}
return httpHandler, nil
}
type handler struct {
v0 http.Handler
v1 http.Handler
setLogEnabled func(enabled bool)
v0 http.Handler
v1 http.Handler
}
func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {