package auth import ( "fmt" "log" "os" "strings" ) // ValidateAuthConfig enforces authentication requirements func (c *Config) ValidateAuthConfig() error { // Check if we're in production environment isProduction := os.Getenv("FETCH_ML_ENV") == "prod" if isProduction { if !c.Enabled { return fmt.Errorf("authentication must be enabled in production environment") } if len(c.APIKeys) == 0 { return fmt.Errorf("at least one API key must be configured in production") } // Ensure at least one admin user exists hasAdmin := false for _, entry := range c.APIKeys { if entry.Admin { hasAdmin = true break } } if !hasAdmin { return fmt.Errorf("at least one admin user must be configured in production") } // Check for insecure development override if os.Getenv("FETCH_ML_ALLOW_INSECURE_AUTH") == "1" { log.Printf("WARNING: FETCH_ML_ALLOW_INSECURE_AUTH is enabled in production - this is insecure") } } // Validate API key format for username, entry := range c.APIKeys { if string(username) == "" { return fmt.Errorf("empty username not allowed") } if entry.Hash == "" { return fmt.Errorf("user %s has empty API key hash", username) } // Validate hash format (should be 64 hex chars for SHA256) if len(entry.Hash) != 64 { return fmt.Errorf("user %s has invalid API key hash format", username) } // Check hash contains only hex characters for _, char := range entry.Hash { if char < '0' || (char > '9' && char < 'a') || (char > 'f' && char < 'A') || char > 'F' { return fmt.Errorf("user %s has invalid API key hash characters", username) } } } return nil } // CheckConfigFilePermissions ensures config files have secure permissions func CheckConfigFilePermissions(configPath string) error { info, err := os.Stat(configPath) if err != nil { return fmt.Errorf("cannot stat config file: %w", err) } // Check file permissions (should be 600) perm := info.Mode().Perm() if perm&0077 != 0 { return fmt.Errorf("config file %s has insecure permissions: %o (should be 600)", configPath, perm) } return nil } // SanitizeConfig removes sensitive information for logging func (c *Config) SanitizeConfig() map[string]interface{} { sanitized := map[string]interface{}{ "enabled": c.Enabled, "users": make(map[string]interface{}), } for username := range c.APIKeys { sanitized["users"].(map[string]interface{})[string(username)] = map[string]interface{}{ "admin": c.APIKeys[username].Admin, "hash": strings.Repeat("*", 8) + "...", // Show only prefix } } return sanitized }