chore: implement Phase 1 and 2 security remediations
Some checks failed
Automated Container Build / build-and-push (push) Has been cancelled

This commit is contained in:
Elijah 2026-05-26 13:32:09 -07:00
parent 82731e93b1
commit 701766b611
14 changed files with 213 additions and 55 deletions

View file

@ -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
}