mirror of
https://github.com/yusing/godoxy.git
synced 2025-05-19 20:32:35 +02:00

* implement OIDC middleware * auth code cleanup * allow override allowed_user in middleware, fix typos * fix tests and callbackURL * update next release docs * fix OIDC middleware not working with Authentik * feat: add groups support for OIDC claims (#41) Allow users to specify allowed groups in the env and use it to inspect the claims. This performs a logical AND of users and groups (additive). * merge feat/oidc-middleware (#49) * api: enrich provider statistifcs * fix: docker monitor now uses container status * Feat/auto schemas (#48) * use auto generated schemas * go version bump and dependencies upgrade * clarify some error messages --------- Co-authored-by: yusing <yusing@6uo.me> * cleanup some loadbalancer code * api: cleanup websocket code * api: add /v1/health/ws for health bubbles on dashboard * feat: experimental memory logger and logs api for WebUI --------- Co-authored-by: yusing <yusing@6uo.me> --------- Co-authored-by: yusing <yusing@6uo.me> Co-authored-by: Peter Olds <peter@olds.co>
154 lines
3.5 KiB
Go
Executable file
154 lines
3.5 KiB
Go
Executable file
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/yusing/go-proxy/internal"
|
|
v1 "github.com/yusing/go-proxy/internal/api/v1"
|
|
"github.com/yusing/go-proxy/internal/api/v1/auth"
|
|
"github.com/yusing/go-proxy/internal/api/v1/query"
|
|
"github.com/yusing/go-proxy/internal/common"
|
|
"github.com/yusing/go-proxy/internal/config"
|
|
E "github.com/yusing/go-proxy/internal/error"
|
|
"github.com/yusing/go-proxy/internal/logging"
|
|
"github.com/yusing/go-proxy/internal/net/http/middleware"
|
|
"github.com/yusing/go-proxy/internal/route/routes"
|
|
"github.com/yusing/go-proxy/internal/task"
|
|
"github.com/yusing/go-proxy/pkg"
|
|
)
|
|
|
|
var rawLogger = log.New(os.Stdout, "", 0)
|
|
|
|
func main() {
|
|
var out io.Writer = os.Stdout
|
|
if common.EnableLogStreaming {
|
|
out = io.MultiWriter(out, v1.MemLogger())
|
|
}
|
|
logging.InitLogger(out)
|
|
|
|
args := common.GetArgs()
|
|
|
|
switch args.Command {
|
|
case common.CommandSetup:
|
|
internal.Setup()
|
|
return
|
|
case common.CommandReload:
|
|
if err := query.ReloadServer(); err != nil {
|
|
E.LogFatal("server reload error", err)
|
|
}
|
|
rawLogger.Println("ok")
|
|
return
|
|
case common.CommandListIcons:
|
|
icons, err := internal.ListAvailableIcons()
|
|
if err != nil {
|
|
rawLogger.Fatal(err)
|
|
}
|
|
printJSON(icons)
|
|
return
|
|
case common.CommandListRoutes:
|
|
routes, err := query.ListRoutes()
|
|
if err != nil {
|
|
log.Printf("failed to connect to api server: %s", err)
|
|
log.Printf("falling back to config file")
|
|
} else {
|
|
printJSON(routes)
|
|
return
|
|
}
|
|
case common.CommandDebugListMTrace:
|
|
trace, err := query.ListMiddlewareTraces()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
printJSON(trace)
|
|
return
|
|
}
|
|
|
|
if args.Command == common.CommandStart {
|
|
logging.Info().Msgf("GoDoxy version %s", pkg.GetVersion())
|
|
logging.Trace().Msg("trace enabled")
|
|
// logging.AddHook(notif.GetDispatcher())
|
|
} else {
|
|
logging.DiscardLogger()
|
|
}
|
|
|
|
if args.Command == common.CommandValidate {
|
|
data, err := os.ReadFile(common.ConfigPath)
|
|
if err == nil {
|
|
err = config.Validate(data)
|
|
}
|
|
if err != nil {
|
|
log.Fatal("config error: ", err)
|
|
}
|
|
log.Print("config OK")
|
|
return
|
|
}
|
|
|
|
for _, dir := range common.RequiredDirectories {
|
|
prepareDirectory(dir)
|
|
}
|
|
|
|
middleware.LoadComposeFiles()
|
|
|
|
var cfg *config.Config
|
|
var err E.Error
|
|
if cfg, err = config.Load(); err != nil {
|
|
E.LogWarn("errors in config", err)
|
|
}
|
|
|
|
switch args.Command {
|
|
case common.CommandListRoutes:
|
|
cfg.StartProxyProviders()
|
|
printJSON(routes.RoutesByAlias())
|
|
return
|
|
case common.CommandListConfigs:
|
|
printJSON(cfg.Value())
|
|
return
|
|
case common.CommandDebugListEntries:
|
|
printJSON(cfg.DumpEntries())
|
|
return
|
|
case common.CommandDebugListProviders:
|
|
printJSON(cfg.DumpProviders())
|
|
return
|
|
}
|
|
|
|
if err := auth.Initialize(); err != nil {
|
|
logging.Fatal().Err(err).Msg("failed to initialize authentication")
|
|
}
|
|
|
|
cfg.Start()
|
|
config.WatchChanges()
|
|
|
|
sig := make(chan os.Signal, 1)
|
|
signal.Notify(sig, syscall.SIGINT)
|
|
signal.Notify(sig, syscall.SIGTERM)
|
|
signal.Notify(sig, syscall.SIGHUP)
|
|
|
|
// wait for signal
|
|
<-sig
|
|
|
|
// gracefully shutdown
|
|
logging.Info().Msg("shutting down")
|
|
_ = task.GracefulShutdown(time.Second * time.Duration(cfg.Value().TimeoutShutdown))
|
|
}
|
|
|
|
func prepareDirectory(dir string) {
|
|
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
|
if err = os.MkdirAll(dir, 0o755); err != nil {
|
|
logging.Fatal().Msgf("failed to create directory %s: %v", dir, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func printJSON(obj any) {
|
|
j, err := json.MarshalIndent(obj, "", " ")
|
|
if err != nil {
|
|
logging.Fatal().Err(err).Send()
|
|
}
|
|
rawLogger.Print(string(j)) // raw output for convenience using "jq"
|
|
}
|