mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2026-06-19 09:47:29 +02:00
Merge branch 'main' into feature/526-average-resample
This commit is contained in:
@@ -17,7 +17,7 @@ var (
|
||||
)
|
||||
|
||||
func cliInit() {
|
||||
flag.BoolVar(&flagInit, "init", false, "Setup var directory, initialize sqlite database file, config.json and .env")
|
||||
flag.BoolVar(&flagInit, "init", false, "Setup var directory, initialize sqlite database file and config.json")
|
||||
flag.BoolVar(&flagReinitDB, "init-db", false, "Go through job-archive and re-initialize the 'job', 'tag', and 'jobtag' tables (all running jobs will be lost!)")
|
||||
flag.BoolVar(&flagSyncLDAP, "sync-ldap", false, "Sync the 'hpc_user' table with ldap")
|
||||
flag.BoolVar(&flagServer, "server", false, "Start a server, continues listening on port after initialization and argument handling")
|
||||
|
||||
@@ -18,16 +18,6 @@ import (
|
||||
"github.com/ClusterCockpit/cc-lib/v2/util"
|
||||
)
|
||||
|
||||
const envString = `
|
||||
# Base64 encoded Ed25519 keys (DO NOT USE THESE TWO IN PRODUCTION!)
|
||||
# You can generate your own keypair using the gen-keypair tool
|
||||
JWT_PUBLIC_KEY="kzfYrYy+TzpanWZHJ5qSdMj5uKUWgq74BWhQG6copP0="
|
||||
JWT_PRIVATE_KEY="dtPC/6dWJFKZK7KZ78CvWuynylOmjBFyMsUWArwmodOTN9itjL5POlqdZkcnmpJ0yPm4pRaCrvgFaFAbpyik/Q=="
|
||||
|
||||
# Some random bytes used as secret for cookie-based sessions (DO NOT USE THIS ONE IN PRODUCTION)
|
||||
SESSION_KEY="67d829bf61dc5f87a73fd814e2c9f629"
|
||||
`
|
||||
|
||||
const configString = `
|
||||
{
|
||||
"main": {
|
||||
@@ -53,7 +43,9 @@ const configString = `
|
||||
},
|
||||
"auth": {
|
||||
"jwts": {
|
||||
"max-age": "2000h"
|
||||
"max-age": "2000h",
|
||||
"public-key": "kzfYrYy+TzpanWZHJ5qSdMj5uKUWgq74BWhQG6copP0=",
|
||||
"private-key": "dtPC/6dWJFKZK7KZ78CvWuynylOmjBFyMsUWArwmodOTN9itjL5POlqdZkcnmpJ0yPm4pRaCrvgFaFAbpyik/Q=="
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,10 +60,6 @@ func initEnv() {
|
||||
cclog.Abortf("Could not write default ./config.json with permissions '0o666'. Application initialization failed, exited.\nError: %s\n", err.Error())
|
||||
}
|
||||
|
||||
if err := os.WriteFile(".env", []byte(envString), 0o666); err != nil {
|
||||
cclog.Abortf("Could not write default ./.env file with permissions '0o666'. Application initialization failed, exited.\nError: %s\n", err.Error())
|
||||
}
|
||||
|
||||
if err := os.Mkdir("var", 0o777); err != nil {
|
||||
cclog.Abortf("Could not create default ./var folder with permissions '0o777'. Application initialization failed, exited.\nError: %s\n", err.Error())
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ import (
|
||||
"github.com/ClusterCockpit/cc-lib/v2/schema"
|
||||
"github.com/ClusterCockpit/cc-lib/v2/util"
|
||||
"github.com/google/gops/agent"
|
||||
"github.com/joho/godotenv"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
@@ -89,13 +88,6 @@ func initGops() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadEnvironment() error {
|
||||
if err := godotenv.Load(); err != nil {
|
||||
return fmt.Errorf("loading .env file: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func initConfiguration() error {
|
||||
ccconf.Init(flagConfigFile)
|
||||
|
||||
@@ -224,7 +216,14 @@ func checkDefaultSecurityKeys() {
|
||||
// Default JWT public key from init.go
|
||||
defaultJWTPublic := "kzfYrYy+TzpanWZHJ5qSdMj5uKUWgq74BWhQG6copP0="
|
||||
|
||||
if os.Getenv("JWT_PUBLIC_KEY") == defaultJWTPublic {
|
||||
// Resolve the public key the same way the authenticators do: environment
|
||||
// variable takes precedence over the value configured in config.json.
|
||||
pubKey := os.Getenv("JWT_PUBLIC_KEY")
|
||||
if pubKey == "" && auth.Keys.JwtConfig != nil {
|
||||
pubKey = auth.Keys.JwtConfig.PublicKey
|
||||
}
|
||||
|
||||
if pubKey == defaultJWTPublic {
|
||||
cclog.Warn("Using default JWT keys - not recommended for production environments")
|
||||
}
|
||||
}
|
||||
@@ -495,7 +494,7 @@ func run() error {
|
||||
if flagInit {
|
||||
initEnv()
|
||||
cclog.Exit("Successfully setup environment!\n" +
|
||||
"Please review config.json and .env and adjust it to your needs.\n" +
|
||||
"Please review config.json and adjust it to your needs.\n" +
|
||||
"Add your job-archive at ./var/job-archive.")
|
||||
}
|
||||
|
||||
@@ -505,17 +504,12 @@ func run() error {
|
||||
}
|
||||
|
||||
// Initialize subsystems in dependency order:
|
||||
// 1. Load environment variables from .env file (contains sensitive configuration)
|
||||
// 2. Load configuration from config.json (may reference environment variables)
|
||||
// 3. Handle database migration commands if requested
|
||||
// 4. Initialize database connection (requires config for connection string)
|
||||
// 5. Handle user commands if requested (requires database and authentication config)
|
||||
// 6. Initialize subsystems like archive and metrics (require config and database)
|
||||
|
||||
// Load environment and configuration
|
||||
if err := loadEnvironment(); err != nil {
|
||||
return err
|
||||
}
|
||||
// 1. Load configuration from config.json (secrets live in config; individual
|
||||
// secrets may be overridden via environment variables)
|
||||
// 2. Handle database migration commands if requested
|
||||
// 3. Initialize database connection (requires config for connection string)
|
||||
// 4. Handle user commands if requested (requires database and authentication config)
|
||||
// 5. Initialize subsystems like archive and metrics (require config and database)
|
||||
|
||||
if err := initConfiguration(); err != nil {
|
||||
return err
|
||||
|
||||
@@ -121,6 +121,7 @@ func (s *Server) init() error {
|
||||
}
|
||||
|
||||
authHandle := auth.GetAuthInstance()
|
||||
sessionManager := authHandle.SessionManager()
|
||||
|
||||
// Middleware must be defined before routes in chi
|
||||
s.router.Use(func(next http.Handler) http.Handler {
|
||||
@@ -220,10 +221,12 @@ func (s *Server) init() error {
|
||||
})
|
||||
}
|
||||
|
||||
s.router.Post("/login", authHandle.Login(loginFailureHandler).ServeHTTP)
|
||||
s.router.HandleFunc("/jwt-login", authHandle.Login(loginFailureHandler).ServeHTTP)
|
||||
// Login/logout mutate the session, so they are wrapped with
|
||||
// scs.LoadAndSave, which commits the session and writes the cookie.
|
||||
s.router.Post("/login", sessionManager.LoadAndSave(authHandle.Login(loginFailureHandler)).ServeHTTP)
|
||||
s.router.Handle("/jwt-login", sessionManager.LoadAndSave(authHandle.Login(loginFailureHandler)))
|
||||
|
||||
s.router.Post("/logout", authHandle.Logout(
|
||||
s.router.Post("/logout", sessionManager.LoadAndSave(authHandle.Logout(
|
||||
http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.Header().Add("Content-Type", "text/html; charset=utf-8")
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
@@ -234,7 +237,7 @@ func (s *Server) init() error {
|
||||
Build: buildInfo,
|
||||
Infos: info,
|
||||
})
|
||||
})).ServeHTTP)
|
||||
}))).ServeHTTP)
|
||||
}
|
||||
|
||||
if flagDev {
|
||||
@@ -246,6 +249,10 @@ func (s *Server) init() error {
|
||||
// Secured routes (require authentication)
|
||||
s.router.Group(func(secured chi.Router) {
|
||||
if !config.Keys.DisableAuthentication {
|
||||
// Non-buffering session load: makes the session available to
|
||||
// AuthViaSession without wrapping/buffering the (potentially large,
|
||||
// e.g. GraphQL /query) response.
|
||||
secured.Use(authHandle.LoadSession)
|
||||
secured.Use(func(next http.Handler) http.Handler {
|
||||
return authHandle.Auth(
|
||||
next,
|
||||
@@ -309,6 +316,7 @@ func (s *Server) init() error {
|
||||
// the /config page route that is registered in the secured group)
|
||||
s.router.Group(func(configapi chi.Router) {
|
||||
if !config.Keys.DisableAuthentication {
|
||||
configapi.Use(authHandle.LoadSession)
|
||||
configapi.Use(func(next http.Handler) http.Handler {
|
||||
return authHandle.AuthConfigAPI(next, onFailureResponse)
|
||||
})
|
||||
@@ -319,6 +327,7 @@ func (s *Server) init() error {
|
||||
// Frontend API routes
|
||||
s.router.Route("/frontend", func(frontendapi chi.Router) {
|
||||
if !config.Keys.DisableAuthentication {
|
||||
frontendapi.Use(authHandle.LoadSession)
|
||||
frontendapi.Use(func(next http.Handler) http.Handler {
|
||||
return authHandle.AuthFrontendAPI(next, onFailureResponse)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user