fetch_ml/internal/api/server_config.go
Jeremie Fraeys cd5640ebd2 Slim and secure: move scripts, clean configs, remove secrets
- Move ci-test.sh and setup.sh to scripts/
- Trim docs/src/zig-cli.md to current structure
- Replace hardcoded secrets with placeholders in configs
- Update .gitignore to block .env*, secrets/, keys, build artifacts
- Slim README.md to reflect current CLI/TUI split
- Add cleanup trap to ci-test.sh
- Ensure no secrets are committed
2025-12-07 13:57:51 -05:00

149 lines
3.8 KiB
Go

package api
import (
"log"
"os"
"path/filepath"
"github.com/jfraeys/fetch_ml/internal/auth"
"github.com/jfraeys/fetch_ml/internal/config"
"github.com/jfraeys/fetch_ml/internal/logging"
"gopkg.in/yaml.v3"
)
// ServerConfig holds all server configuration
type ServerConfig struct {
BasePath string `yaml:"base_path"`
Auth auth.Config `yaml:"auth"`
Server ServerSection `yaml:"server"`
Security SecurityConfig `yaml:"security"`
Redis RedisConfig `yaml:"redis"`
Database DatabaseConfig `yaml:"database"`
Logging logging.Config `yaml:"logging"`
Resources config.ResourceConfig `yaml:"resources"`
}
// ServerSection holds server-specific configuration
type ServerSection struct {
Address string `yaml:"address"`
TLS TLSConfig `yaml:"tls"`
}
// TLSConfig holds TLS configuration
type TLSConfig struct {
Enabled bool `yaml:"enabled"`
CertFile string `yaml:"cert_file"`
KeyFile string `yaml:"key_file"`
}
// SecurityConfig holds security-related configuration
type SecurityConfig struct {
RateLimit RateLimitConfig `yaml:"rate_limit"`
IPWhitelist []string `yaml:"ip_whitelist"`
FailedLockout LockoutConfig `yaml:"failed_login_lockout"`
}
// RateLimitConfig holds rate limiting configuration
type RateLimitConfig struct {
Enabled bool `yaml:"enabled"`
RequestsPerMinute int `yaml:"requests_per_minute"`
BurstSize int `yaml:"burst_size"`
}
// LockoutConfig holds failed login lockout configuration
type LockoutConfig struct {
Enabled bool `yaml:"enabled"`
MaxAttempts int `yaml:"max_attempts"`
LockoutDuration string `yaml:"lockout_duration"`
}
// RedisConfig holds Redis connection configuration
type RedisConfig struct {
Addr string `yaml:"addr"`
Password string `yaml:"password"`
DB int `yaml:"db"`
URL string `yaml:"url"`
}
// DatabaseConfig holds database connection configuration
type DatabaseConfig struct {
Type string `yaml:"type"`
Connection string `yaml:"connection"`
Host string `yaml:"host"`
Port int `yaml:"port"`
Username string `yaml:"username"`
Password string `yaml:"password"`
Database string `yaml:"database"`
}
// LoadServerConfig loads and validates server configuration
func LoadServerConfig(path string) (*ServerConfig, error) {
resolvedConfig, err := config.ResolveConfigPath(path)
if err != nil {
return nil, err
}
cfg, err := loadConfigFromFile(resolvedConfig)
if err != nil {
return nil, err
}
cfg.Resources.ApplyDefaults()
return cfg, nil
}
// loadConfigFromFile loads configuration from a YAML file
func loadConfigFromFile(path string) (*ServerConfig, error) {
data, err := secureFileRead(path)
if err != nil {
return nil, err
}
var cfg ServerConfig
if err := yaml.Unmarshal(data, &cfg); err != nil {
return nil, err
}
return &cfg, nil
}
// secureFileRead safely reads a file
func secureFileRead(path string) ([]byte, error) {
// This would use the fileutil.SecureFileRead function
// For now, implement basic file reading
return os.ReadFile(path)
}
// EnsureLogDirectory creates the log directory if needed
func (c *ServerConfig) EnsureLogDirectory() error {
if c.Logging.File == "" {
return nil
}
logDir := filepath.Dir(c.Logging.File)
log.Printf("Creating log directory: %s", logDir)
return os.MkdirAll(logDir, 0750)
}
// BuildAuthConfig creates the auth configuration
func (c *ServerConfig) BuildAuthConfig() *auth.Config {
if !c.Auth.Enabled {
return nil
}
log.Printf("Authentication enabled with %d API keys", len(c.Auth.APIKeys))
return &c.Auth
}
// Validate performs basic configuration validation
func (c *ServerConfig) Validate() error {
// Add validation logic here
if c.Server.Address == "" {
c.Server.Address = ":8080"
}
if c.BasePath == "" {
c.BasePath = "/tmp/ml-experiments"
}
return nil
}