Heavy security and file splitting
CI / Go Tests (push) Successful in 15s
CI / Build (push) Successful in 9s
Format / gofmt (push) Successful in 7s
Release Artifacts / Validate release tag (push) Successful in 2s
Release Artifacts / Build and release executables (push) Successful in 15s
Release Artifacts / Build and release Docker image (push) Successful in 28s
CI / Go Tests (push) Successful in 15s
CI / Build (push) Successful in 9s
Format / gofmt (push) Successful in 7s
Release Artifacts / Validate release tag (push) Successful in 2s
Release Artifacts / Build and release executables (push) Successful in 15s
Release Artifacts / Build and release Docker image (push) Successful in 28s
This commit is contained in:
@@ -111,14 +111,18 @@ func (w *rollingFileWriter) rotateLocked() error {
|
||||
}
|
||||
return fmt.Errorf("stat rotated file %s: %w", from, err)
|
||||
}
|
||||
_ = os.Remove(to)
|
||||
if err := os.Remove(to); err != nil && !os.IsNotExist(err) {
|
||||
return fmt.Errorf("remove target backup slot %s: %w", to, err)
|
||||
}
|
||||
if err := os.Rename(from, to); err != nil {
|
||||
return fmt.Errorf("rotate backup %s -> %s: %w", from, to, err)
|
||||
}
|
||||
}
|
||||
|
||||
firstBackup := rotatedLogPath(w.path, 1)
|
||||
_ = os.Remove(firstBackup)
|
||||
if err := os.Remove(firstBackup); err != nil && !os.IsNotExist(err) {
|
||||
return fmt.Errorf("remove first backup %s: %w", firstBackup, err)
|
||||
}
|
||||
if _, err := os.Stat(w.path); err == nil {
|
||||
if err := os.Rename(w.path, firstBackup); err != nil {
|
||||
return fmt.Errorf("rotate current log to %s: %w", firstBackup, err)
|
||||
|
||||
@@ -347,6 +347,16 @@ func TestGenerateConfigCommandWritesDefaultYAML(t *testing.T) {
|
||||
if !cfg.Security.RateLimitAPIWrite.Enabled {
|
||||
t.Fatalf("security.rate_limit_api_write.enabled = %v, want true", cfg.Security.RateLimitAPIWrite.Enabled)
|
||||
}
|
||||
// Additional assertions act as golden checks against generate drift in defaults/comments/struct.
|
||||
if cfg.Storage.CleanupInterval != "1m" {
|
||||
t.Fatalf("storage.cleanup_interval = %q, want %q", cfg.Storage.CleanupInterval, "1m")
|
||||
}
|
||||
if !cfg.Security.HSTSEnabled {
|
||||
t.Fatalf("security.hsts_enabled = %v, want true", cfg.Security.HSTSEnabled)
|
||||
}
|
||||
if cfg.Limits.RawCacheMaxEntries != 32 {
|
||||
t.Fatalf("limits.raw_cache_max_entries = %d, want 32", cfg.Limits.RawCacheMaxEntries)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateConfigCommandRejectsUnexpectedArgs(t *testing.T) {
|
||||
@@ -437,6 +447,9 @@ security:
|
||||
if err != nil {
|
||||
t.Fatalf("config.Load() error = %v", err)
|
||||
}
|
||||
if err := cfg.PrepareDataDir(); err != nil {
|
||||
t.Fatalf("config.PrepareDataDir() error = %v", err)
|
||||
}
|
||||
logger := log.New(io.Discard, "", 0)
|
||||
store, err := storage.NewFilesystemStore(cfg.Storage.DataDir, cfg.Storage.EncryptionKeyBytes)
|
||||
if err != nil {
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@@ -66,6 +65,12 @@ func run(configPath string, useEnv bool) error {
|
||||
return fmt.Errorf("config load failed: %w", err)
|
||||
}
|
||||
|
||||
// Prepare data dir + key (side effects) after pure Validate inside Load*/Default.
|
||||
// This addresses the layering issue where Validate used to mutate FS.
|
||||
if err := cfg.PrepareDataDir(); err != nil {
|
||||
return fmt.Errorf("prepare storage data dir failed: %w", err)
|
||||
}
|
||||
|
||||
logger := log.New(os.Stdout, "[scratchbox] ", log.LstdFlags|log.LUTC)
|
||||
accessWriter, closeAccessWriter, err := newAccessLogWriter(cfg)
|
||||
if err != nil {
|
||||
@@ -114,7 +119,7 @@ func run(configPath string, useEnv bool) error {
|
||||
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), cfg.Server.ShutdownTimeoutDur)
|
||||
defer shutdownCancel()
|
||||
if err := httpServer.Shutdown(shutdownCtx); err != nil {
|
||||
logger.Printf("http shutdown failed: %v", err)
|
||||
@@ -143,7 +148,15 @@ func printEnvStartup() int {
|
||||
return 0
|
||||
}
|
||||
for _, item := range entries {
|
||||
fmt.Fprintf(os.Stdout, "[scratchbox] %s\n", item)
|
||||
printItem := item
|
||||
// Redact values for IP list config (security sensitive for allowlist/rate/proxy spoof surface).
|
||||
// Rates and other are left as-is (numeric, not secret).
|
||||
if strings.Contains(item, "ALLOWED_IPS=") || strings.Contains(item, "TRUSTED_PROXY_IPS=") {
|
||||
if eq := strings.IndexByte(item, '='); eq >= 0 {
|
||||
printItem = item[:eq+1] + "*** (redacted)"
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(os.Stdout, "[scratchbox] %s\n", printItem)
|
||||
}
|
||||
return len(entries)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user