auspex/config.go
2026-06-09 17:12:18 +03:00

401 lines
11 KiB
Go
Executable file

package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
// =============================================================================
// Глобальная конфигурация Auspex
// =============================================================================
//
// Конфигурация загружается из /etc/auspex/auspex.env
// Fallback значения используются если env файл не найден
// =============================================================================
const (
// Путь к файлу конфигурации
envFilePath = "/etc/auspex/auspex.env"
)
// --- Telegram ---
var (
cfgTelegramBotToken = ""
cfgTelegramChatID = ""
cfgTelegramSocks5Proxy = "" // Опционально: host:port
cfgTelegramSocks5User = "" // Логин прокси (опционально)
cfgTelegramSocks5Password = "" // Пароль прокси (опционально)
cfgTelegramHTTPProxy = "" // Опционально: http://user:pass@host:port
)
// --- Mattermost ---
var (
cfgMattermostURL = "" // https://mattermost.example.com
cfgMattermostBotToken = "" // Токен бота
cfgMattermostChannelID = "" // ID канала для отправки
)
// --- Email / SMTP ---
var (
cfgEmailSMTPHost = ""
cfgEmailSMTPPort = 587
cfgEmailSMTPUser = ""
cfgEmailSMTPPassword = ""
cfgEmailFrom = ""
cfgEmailTo = []string{}
)
// --- PostgreSQL Database ---
var (
cfgDBUser = ""
cfgDBPassword = ""
cfgDBName = "waf_info" // Значение по умолчанию
cfgDBPort = 5432 // Значение по умолчанию
)
// --- Пути к хостам БД ---
var (
cfgPrimaryDBHost = "10.100.10.8"
cfgSecondaryDBHost = "10.100.13.5"
)
// --- Пороги сертификатов (дни) ---
var (
cfgCertCriticalDays = 3
cfgCertWarningDays = 15
cfgCertInfoDays = 30
)
// --- Пути ---
var (
cfgPTAFBaseDir = "/home/install/ptaf"
cfgAngieConfDir = "/etc/angie/http.d"
cfgSSLDir = "/etc/ssl"
cfgNginxConfigGlob = "/home/install/conf/ptaf-nginx/*/*/*/*.conf"
cfgStateFilePath = "/tmp/port_checker_state.json"
cfgServiceStateFilePath = "/tmp/auspex_service_state.json"
cfgDockerStateFilePath = "/tmp/auspex_docker_state.json"
)
// --- Параметры проверки портов ---
var (
cfgCheckTimeoutSec = 10
cfgMaxRetries = 3
cfgRetryDelaySec = 2
)
// cfgMaxWorkers — количество горутин для параллельной обработки
var cfgMaxWorkers = 10
// --- Log Check ---
var (
cfgLogDir = "/var/log/ptaf_nginx"
cfgLogStaleMinutes = 61 // Порог в минутах для определения устаревшего лога
)
// --- Service Check ---
// Список служб systemd для проверки на текущем хосте.
// Задаётся через SERVICES_TO_CHECK в auspex.env в виде списка через запятую.
// Пример: SERVICES_TO_CHECK=angie,docker
var cfgServicesToCheck = []string{}
// =============================================================================
// Загрузка конфигурации из файла
// =============================================================================
// loadConfig загружает конфигурацию из /etc/auspex/auspex.env
func loadConfig() error {
file, err := os.Open(envFilePath)
if err != nil {
// Файл не найден - используем значения по умолчанию
return fmt.Errorf("файл конфигурации не найден: %s", envFilePath)
}
defer file.Close()
envVars := make(map[string]string)
scanner := bufio.NewScanner(file)
lineNum := 0
for scanner.Scan() {
lineNum++
line := strings.TrimSpace(scanner.Text())
// Пропускаем пустые строки и комментарии
if line == "" || strings.HasPrefix(line, "#") {
continue
}
// Парсим KEY=VALUE
parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
fmt.Printf("⚠️ Некорректная строка %d в %s: %s\n", lineNum, envFilePath, line)
continue
}
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
// Убираем кавычки если есть
value = strings.Trim(value, `"'`)
envVars[key] = value
}
if err := scanner.Err(); err != nil {
return fmt.Errorf("ошибка чтения файла: %v", err)
}
// Применяем значения
applyConfig(envVars)
return nil
}
// applyConfig применяет загруженные значения к переменным конфигурации
func applyConfig(env map[string]string) {
// Telegram
if v, ok := env["TELEGRAM_BOT_TOKEN"]; ok && v != "" {
cfgTelegramBotToken = v
}
if v, ok := env["TELEGRAM_CHAT_ID"]; ok && v != "" {
cfgTelegramChatID = v
}
if v, ok := env["TELEGRAM_SOCKS5_PROXY"]; ok && v != "" {
cfgTelegramSocks5Proxy = v
}
if v, ok := env["TELEGRAM_SOCKS5_USER"]; ok && v != "" {
cfgTelegramSocks5User = v
}
if v, ok := env["TELEGRAM_SOCKS5_PASSWORD"]; ok && v != "" {
cfgTelegramSocks5Password = v
}
if v, ok := env["TELEGRAM_HTTP_PROXY"]; ok && v != "" {
cfgTelegramHTTPProxy = v
}
// Database
if v, ok := env["DB_USER"]; ok && v != "" {
cfgDBUser = v
}
if v, ok := env["DB_PASSWORD"]; ok && v != "" {
cfgDBPassword = v
}
if v, ok := env["DB_NAME"]; ok && v != "" {
cfgDBName = v
}
if v, ok := env["DB_PORT"]; ok && v != "" {
if port, err := strconv.Atoi(v); err == nil {
cfgDBPort = port
}
}
if v, ok := env["PRIMARY_DB_HOST"]; ok && v != "" {
cfgPrimaryDBHost = v
}
if v, ok := env["SECONDARY_DB_HOST"]; ok && v != "" {
cfgSecondaryDBHost = v
}
// Paths
if v, ok := env["PTAF_BASE_DIR"]; ok && v != "" {
cfgPTAFBaseDir = v
}
if v, ok := env["ANGIE_CONF_DIR"]; ok && v != "" {
cfgAngieConfDir = v
}
if v, ok := env["SSL_DIR"]; ok && v != "" {
cfgSSLDir = v
}
if v, ok := env["NGINX_CONFIG_GLOB"]; ok && v != "" {
cfgNginxConfigGlob = v
}
if v, ok := env["STATE_FILE_PATH"]; ok && v != "" {
cfgStateFilePath = v
}
if v, ok := env["SERVICE_STATE_FILE_PATH"]; ok && v != "" {
cfgServiceStateFilePath = v
}
if v, ok := env["DOCKER_STATE_FILE_PATH"]; ok && v != "" {
cfgDockerStateFilePath = v
}
if v, ok := env["LOG_DIR"]; ok && v != "" {
cfgLogDir = v
}
// Thresholds
if v, ok := env["CERT_CRITICAL_DAYS"]; ok && v != "" {
if days, err := strconv.Atoi(v); err == nil {
cfgCertCriticalDays = days
}
}
if v, ok := env["CERT_WARNING_DAYS"]; ok && v != "" {
if days, err := strconv.Atoi(v); err == nil {
cfgCertWarningDays = days
}
}
if v, ok := env["CERT_INFO_DAYS"]; ok && v != "" {
if days, err := strconv.Atoi(v); err == nil {
cfgCertInfoDays = days
}
}
if v, ok := env["LOG_STALE_MINUTES"]; ok && v != "" {
if mins, err := strconv.Atoi(v); err == nil {
cfgLogStaleMinutes = mins
}
}
// Timeouts and retries
if v, ok := env["CHECK_TIMEOUT_SEC"]; ok && v != "" {
if sec, err := strconv.Atoi(v); err == nil {
cfgCheckTimeoutSec = sec
}
}
if v, ok := env["MAX_RETRIES"]; ok && v != "" {
if retries, err := strconv.Atoi(v); err == nil {
cfgMaxRetries = retries
}
}
if v, ok := env["RETRY_DELAY_SEC"]; ok && v != "" {
if sec, err := strconv.Atoi(v); err == nil {
cfgRetryDelaySec = sec
}
}
if v, ok := env["MAX_WORKERS"]; ok && v != "" {
if workers, err := strconv.Atoi(v); err == nil {
cfgMaxWorkers = workers
}
}
// Services to check
if v, ok := env["SERVICES_TO_CHECK"]; ok && v != "" {
parts := strings.Split(v, ",")
services := make([]string, 0, len(parts))
for _, s := range parts {
s = strings.TrimSpace(s)
if s != "" {
services = append(services, s)
}
}
cfgServicesToCheck = services
}
// Email / SMTP
if v, ok := env["EMAIL_SMTP_HOST"]; ok && v != "" {
cfgEmailSMTPHost = v
}
if v, ok := env["EMAIL_SMTP_PORT"]; ok && v != "" {
if port, err := strconv.Atoi(v); err == nil {
cfgEmailSMTPPort = port
}
}
if v, ok := env["EMAIL_SMTP_USER"]; ok && v != "" {
cfgEmailSMTPUser = v
}
if v, ok := env["EMAIL_SMTP_PASSWORD"]; ok && v != "" {
cfgEmailSMTPPassword = v
}
if v, ok := env["EMAIL_FROM"]; ok && v != "" {
cfgEmailFrom = v
}
// Mattermost
if v, ok := env["MATTERMOST_URL"]; ok && v != "" {
cfgMattermostURL = v
}
if v, ok := env["MATTERMOST_BOT_TOKEN"]; ok && v != "" {
cfgMattermostBotToken = v
}
if v, ok := env["MATTERMOST_CHANNEL_ID"]; ok && v != "" {
cfgMattermostChannelID = v
}
// Email / SMTP
if v, ok := env["EMAIL_TO"]; ok && v != "" {
parts := strings.Split(v, ",")
recipients := make([]string, 0, len(parts))
for _, s := range parts {
s = strings.TrimSpace(s)
if s != "" {
recipients = append(recipients, s)
}
}
cfgEmailTo = recipients
}
}
// =============================================================================
// Вспомогательные функции
// =============================================================================
func isTelegramConfigured() bool {
return cfgTelegramBotToken != "" &&
cfgTelegramBotToken != "YOUR_BOT_TOKEN" &&
cfgTelegramChatID != "" &&
cfgTelegramChatID != "YOUR_CHAT_ID"
}
func isMattermostConfigured() bool {
return cfgMattermostURL != "" &&
cfgMattermostBotToken != "" &&
cfgMattermostChannelID != ""
}
func isEmailConfigured() bool {
return cfgEmailSMTPHost != "" &&
cfgEmailFrom != "" &&
len(cfgEmailTo) > 0
}
// printConfigStatus выводит статус загруженной конфигурации
func printConfigStatus() {
fmt.Println("📋 Статус конфигурации:")
// Telegram
if isTelegramConfigured() {
switch {
case cfgTelegramSocks5Proxy != "":
if cfgTelegramSocks5User != "" {
fmt.Printf(" ✅ Telegram: настроен (SOCKS5: %s, пользователь: %s)\n", cfgTelegramSocks5Proxy, cfgTelegramSocks5User)
} else {
fmt.Printf(" ✅ Telegram: настроен (SOCKS5: %s, без авторизации)\n", cfgTelegramSocks5Proxy)
}
case cfgTelegramHTTPProxy != "":
fmt.Printf(" ✅ Telegram: настроен (HTTP прокси: %s)\n", cfgTelegramHTTPProxy)
default:
fmt.Println(" ✅ Telegram: настроен (прямое соединение)")
}
} else {
fmt.Println(" ⚠️ Telegram: не настроен")
}
// Database
if cfgDBUser != "" && cfgDBPassword != "" {
fmt.Printf(" ✅ База данных: %s@%s:%d/%s\n", cfgDBUser, cfgPrimaryDBHost, cfgDBPort, cfgDBName)
} else {
fmt.Println(" ⚠️ База данных: не настроена")
}
// Mattermost
if isMattermostConfigured() {
fmt.Printf(" ✅ Mattermost: настроен (%s, channel: %s)\n", cfgMattermostURL, cfgMattermostChannelID)
} else {
fmt.Println(" ⚠️ Mattermost: не настроен (MATTERMOST_URL, MATTERMOST_BOT_TOKEN, MATTERMOST_CHANNEL_ID)")
}
// Email
if isEmailConfigured() {
fmt.Printf(" ✅ Email: %s → %s (smtp: %s:%d)\n", cfgEmailFrom, strings.Join(cfgEmailTo, ", "), cfgEmailSMTPHost, cfgEmailSMTPPort)
} else {
fmt.Println(" ⚠️ Email: не настроен (EMAIL_SMTP_HOST, EMAIL_FROM, EMAIL_TO)")
}
// Services
if len(cfgServicesToCheck) > 0 {
fmt.Printf(" ✅ Службы для проверки: %s\n", strings.Join(cfgServicesToCheck, ", "))
} else {
fmt.Println(" ⚠️ Службы для проверки: не заданы (SERVICES_TO_CHECK)")
}
fmt.Println()
}