chore: implement Phase 1 and 2 security remediations
Some checks failed
Automated Container Build / build-and-push (push) Has been cancelled
Some checks failed
Automated Container Build / build-and-push (push) Has been cancelled
This commit is contained in:
parent
82731e93b1
commit
701766b611
14 changed files with 213 additions and 55 deletions
|
|
@ -2,10 +2,13 @@ package main
|
|||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.elijahkuntz.com/Elijah/drive/config"
|
||||
|
|
@ -26,12 +29,7 @@ func main() {
|
|||
|
||||
// Auto-generate JWT secret if not set
|
||||
if cfg.JWTSecret == "" {
|
||||
secret, err := generateSecret(32)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to generate JWT secret:", err)
|
||||
}
|
||||
cfg.JWTSecret = secret
|
||||
log.Println("Warning: JWT_SECRET not set, generated a random one. Set JWT_SECRET env var for persistence across restarts.")
|
||||
cfg.JWTSecret = getOrCreateJWTSecret(cfg.DataDir)
|
||||
}
|
||||
|
||||
// Ensure required directories exist
|
||||
|
|
@ -60,12 +58,16 @@ func main() {
|
|||
guard := middleware.NewBruteForceGuard(cfg.MaxLoginAttempts, cfg.LockoutSeconds)
|
||||
|
||||
// Initialize handlers
|
||||
authHandler := &handlers.AuthHandler{DB: db, Config: cfg, Guard: guard}
|
||||
authHandler := handlers.NewAuthHandler(db, cfg, guard)
|
||||
fsHandler := &handlers.FSHandler{DB: db, Config: cfg}
|
||||
healthHandler := &handlers.HealthHandler{DB: db, Config: cfg}
|
||||
settingsHandler := &handlers.SettingsHandler{DB: db}
|
||||
tusHandler := handlers.NewTusHandler(db, cfg)
|
||||
webdavHandler := handlers.NewWebDAVHandler(db, cfg)
|
||||
// WebDAV Handler
|
||||
webdavHandler := handlers.NewWebDAVHandler(db, cfg, guard)
|
||||
|
||||
// Add WebDAV routes
|
||||
app.All("/webdav/*", guard.Check(), webdavHandler.Handle)
|
||||
archiveHandler := &handlers.ArchiveHandler{DB: db, Config: cfg}
|
||||
shareGuard := middleware.NewBruteForceGuard(3, 60)
|
||||
shareHandler := &handlers.ShareHandler{DB: db, Config: cfg, Guard: shareGuard}
|
||||
|
|
@ -250,3 +252,33 @@ func generateSecret(length int) (string, error) {
|
|||
}
|
||||
return hex.EncodeToString(bytes), nil
|
||||
}
|
||||
|
||||
func getOrCreateJWTSecret(dataDir string) string {
|
||||
if secret := os.Getenv("JWT_SECRET"); secret != "" {
|
||||
return secret
|
||||
}
|
||||
|
||||
secretPath := filepath.Join(dataDir, ".jwt_secret")
|
||||
|
||||
if data, err := os.ReadFile(secretPath); err == nil {
|
||||
secret := strings.TrimSpace(string(data))
|
||||
if len(secret) >= 32 {
|
||||
return secret
|
||||
}
|
||||
}
|
||||
|
||||
buf := make([]byte, 32)
|
||||
if _, err := rand.Read(buf); err != nil {
|
||||
log.Fatal("failed to generate JWT secret: ", err)
|
||||
}
|
||||
secret := base64.URLEncoding.EncodeToString(buf)
|
||||
|
||||
if err := os.WriteFile(secretPath, []byte(secret), 0600); err != nil {
|
||||
log.Printf("WARNING: could not persist JWT secret to %s: %v", secretPath, err)
|
||||
log.Printf("Sessions will be invalidated on next restart.")
|
||||
} else {
|
||||
log.Printf("Generated and persisted new JWT secret to %s", secretPath)
|
||||
}
|
||||
|
||||
return secret
|
||||
}
|
||||
|
|
|
|||
Reference in a new issue