// config.go — environment-driven configuration // // We read everything from environment variables so the container image stays // generic. No config files to mount — just env vars and a single whitelist // file (see --permanet-whitelist-file below). // // Why env vars instead of a config file? // // - Containers are meant to be configuration via env vars (12-factor). // - It avoids an extra volume mount for a JSON/TOML config file. // - The permanent whitelist file IS mounted as a volume, but that's // intentional: it's data, not configuration. // // Defaults are sensible so the service can start even if the operator // forgets to set some values. package main import ( "os" "time" ) // Config holds the runtime configuration for the auth-gate service. type Config struct { // Port is the HTTP listen address (no host — we rely on Docker port mapping). Port string // APIToken is the bearer token that authorises the /api/* endpoints. // This is NOT the auth credential for clients — it's the admin token // for the API. Keep it secret. APIToken string // BasicAuthUser and BasicAuthPass are the credentials for the // /auth endpoint's HTTP Basic Auth challenge. // // Why Basic Auth instead of JWT/OAuth? // // - Simplicity: no library dependencies, no token signing. // - Browsers natively support it (pop-up dialog). // - curl, git, and most HTTP clients support it out of the box. BasicAuthUser string BasicAuthPass string // PermanentWhitelistFile is the path to a text file containing // permanently whitelisted IPs/CIDRs (one per line). // // The file is loaded at startup and reloaded by the watcher every // cfg.WatchInterval seconds. PermanentWhitelistFile string PermanentWhitelist *PermanentWhitelist TemporaryWhitelist *tempWhitelist // DataDir is the directory where the service stores the temporary // whitelist in JSON format. // // Why store temp whitelists on disk? // // - We chose an in-memory approach (see tempWhitelist in auth.go) // for simplicity. If you need persistence across restarts, // add a disk-backed store later. // - For now, this field is unused but kept for future extensibility. DataDir string // CleanupInterval is how often the cleanup goroutine runs to expire // temporary whitelisted IPs. CleanupInterval time.Duration // WatchInterval is how often the permanent-whitelist file watcher // polls the file for changes. WatchInterval time.Duration } // loadConfig reads configuration from environment variables with sensible defaults. func loadConfig() Config { cfg := Config{ Port: getEnv("AUTH_GATE_PORT", "8080"), APIToken: getEnv("AUTH_GATE_API_TOKEN", ""), BasicAuthUser: getEnv("AUTH_GATE_BASIC_USER", "admin"), BasicAuthPass: getEnv("AUTH_GATE_BASIC_PASSWORD", "changeme"), PermanentWhitelistFile: getEnv("PERMANENT_WHITELIST_FILE", "./config/permanent_whitelist.txt"), DataDir: getEnv("DATA_DIR", "/data"), CleanupInterval: parseDuration("CLEANUP_INTERVAL", 60*time.Second), WatchInterval: parseDuration("WATCH_INTERVAL", 30*time.Second), } return cfg } // getEnv returns os.Getenv(key) or defaultValue if key is unset or empty. func getEnv(key, defaultValue string) string { if v := os.Getenv(key); v != "" { return v } return defaultValue } // parseDuration reads a duration from the environment, falling back to // the provided default. func parseDuration(key string, defaultVal time.Duration) time.Duration { if v := os.Getenv(key); v != "" { d, err := time.ParseDuration(v) if err == nil { return d } } return defaultVal }