diff --git a/containers_part1.go b/containers_part1.go index 9cc151b..75b7887 100644 --- a/containers_part1.go +++ b/containers_part1.go @@ -69,7 +69,7 @@ func setupContainers(config Config, clientTitle string, clientInfo *ClientInfo, ptafConfig = clientInfo.PTAFConfig.String } - changed, err := generateNginxConf(nginxConfPath, config, ptafConfig, existingPodIP) + changed, err := generateNginxConf(nginxConfPath, config, ptafConfig, existingPodIP, clientInfo.Debug) if err != nil { return fmt.Errorf("ошибка генерации nginx.conf: %w", err) } diff --git a/containers_part2.go b/containers_part2.go index 775e985..0afdf9b 100644 --- a/containers_part2.go +++ b/containers_part2.go @@ -311,7 +311,7 @@ func reloadAngie() { } // generateNginxConf генерирует основной nginx.conf для PTAF -func generateNginxConf(filePath string, config Config, ptafConfig string, existingPodIP string) (bool, error) { +func generateNginxConf(filePath string, config Config, ptafConfig string, existingPodIP string, debug bool) (bool, error) { var randomIP string if existingPodIP != "" { randomIP = existingPodIP @@ -339,6 +339,16 @@ func generateNginxConf(filePath string, config Config, ptafConfig string, existi hostname := fmt.Sprintf("ptaf-%s-agent%s", clientTitle, containerNum) log.Printf(" → clientTitle=%s, containerNum=%s, hostname=%s", clientTitle, containerNum, hostname) + // Настройки логирования зависят от режима debug + ptafLogLevel := "INFO" + debugEnv := "false" + errorLogLevel := "notice" + if debug { + ptafLogLevel = "DEBUG" + debugEnv = "true" + errorLogLevel = "debug" + } + content := fmt.Sprintf(`#user ptaf; master_process on; worker_processes %d; @@ -346,10 +356,10 @@ worker_rlimit_nofile 1048576; daemon off; load_module /opt/ptaf/lib/ngx_wrapper.so; env POD_IP=%s; -env PTAF_LOG_LEVEL=INFO; -env DEBUG=false; +env PTAF_LOG_LEVEL=%s; +env DEBUG=%s; env HOSTNAME=%s; -error_log stderr notice; +error_log stderr %s; pid /opt/ptaf/logs/nginx.pid; events { @@ -438,7 +448,7 @@ http { include /opt/ptaf/conf/conf.d/*.conf; } -`, config.WorkerProcesses, randomIP, hostname, config.WorkerConnections, clientTitle, ptafConfig) +`, config.WorkerProcesses, randomIP, ptafLogLevel, debugEnv, hostname, errorLogLevel, config.WorkerConnections, clientTitle, ptafConfig) return writeFileIfChanged(filePath, content) } @@ -556,6 +566,7 @@ func generateDockerCompose(filePath string, config Config, clientTitle string, c FluentBitEnabled bool FluentBitPort int HasMTLS bool + Debug bool SortedHTTPPorts []SortedPortMapping SortedHTTPSPorts []SortedPortMapping } @@ -612,6 +623,7 @@ func generateDockerCompose(filePath string, config Config, clientTitle string, c WorkerConnections: config.WorkerConnections, FluentBitEnabled: false, HasMTLS: hasMTLS, + Debug: clientInfo.Debug, SortedHTTPPorts: allHTTPPorts, SortedHTTPSPorts: allHTTPSPorts, } @@ -643,6 +655,10 @@ func generateDockerCompose(filePath string, config Config, clientTitle string, c - EVENT_SENDER_PORT={{.FluentBitPort}} - EVENT_SENDER_TIMEOUT=3 - EVENT_WEB_UI_URL=https://af.ptcloud.ru/events/attacks/%s/general/ +{{- end}} +{{- if .Debug}} + - PTAF_DEBUG=True + - ERROR_LOG_LEVEL=debug {{- end}} sysctls: kernel.sem: "32000 1024000000 500 32000" diff --git a/db.go b/db.go index ccc2474..d0c3b1e 100644 --- a/db.go +++ b/db.go @@ -98,7 +98,7 @@ func checkHostBelongsToInstance(db *sql.DB, hostname, instance string) (bool, er func getClientInfoByInstance(db *sql.DB, instance string) ([]ClientInfo, error) { query := ` SELECT containers_count, ptaf_config, client_title, fluent_bit_port, waf_instance, - docker_image, docker_image_download + docker_image, docker_image_download, debug FROM client_info WHERE waf_instance = $1 ` @@ -124,6 +124,7 @@ func getClientInfoByInstance(db *sql.DB, instance string) ([]ClientInfo, error) &wafInstance, &ci.DockerImage, &ci.DockerImageDownload, + &ci.Debug, ) if err != nil { return nil, fmt.Errorf("ошибка сканирования строки: %w", err) @@ -207,7 +208,7 @@ func getAppsSettingsByClientTitle(db *sql.DB, clientTitle string) ([]AppsSetting func getClientInfoByClientTitle(db *sql.DB, clientTitle string) (*ClientInfo, error) { query := ` SELECT containers_count, ptaf_config, client_title, fluent_bit_port, waf_instance, - docker_image, docker_image_download + docker_image, docker_image_download, debug FROM client_info WHERE client_title = $1 ` @@ -222,6 +223,7 @@ func getClientInfoByClientTitle(db *sql.DB, clientTitle string) (*ClientInfo, er &wafInstance, &clientInfo.DockerImage, &clientInfo.DockerImageDownload, + &clientInfo.Debug, ) if err != nil { if strings.Contains(err.Error(), "does not exist") { diff --git a/nginx.go b/nginx.go index 534959e..5f41461 100644 --- a/nginx.go +++ b/nginx.go @@ -10,7 +10,7 @@ import ( ) // generateAngieConfigsWithoutReload генерирует конфиги Angie БЕЗ автоматического reload -func generateAngieConfigsWithoutReload(config Config, clientTitle string, resources []ResourceData, resourcePortMap map[int][]PortMapping) (bool, error) { +func generateAngieConfigsWithoutReload(config Config, clientTitle string, resources []ResourceData, resourcePortMap map[int][]PortMapping, debug bool) (bool, error) { log.Printf("Генерация конфигов Angie для %s", clientTitle) configDir := "/etc/angie/http.d" @@ -47,7 +47,7 @@ func generateAngieConfigsWithoutReload(config Config, clientTitle string, resour return false, fmt.Errorf("не найдены порты для l7ResourceID %d", res.L7ResourceID) } - err := writeAngieResourceConfig(f, config, res, containerPorts) + err := writeAngieResourceConfig(f, config, res, containerPorts, debug) if err != nil { os.Remove(tmpFile) return false, fmt.Errorf("ошибка генерации конфига для l7ResourceID %d: %w", res.L7ResourceID, err) @@ -93,8 +93,8 @@ func generateAngieConfigsWithoutReload(config Config, clientTitle string, resour } // generateAngieConfigs генерирует конфигурационные файлы Angie с автоматическим reload -func generateAngieConfigs(config Config, clientTitle string, resources []ResourceData, resourcePortMap map[int][]PortMapping) error { - changed, err := generateAngieConfigsWithoutReload(config, clientTitle, resources, resourcePortMap) +func generateAngieConfigs(config Config, clientTitle string, resources []ResourceData, resourcePortMap map[int][]PortMapping, debug bool) error { + changed, err := generateAngieConfigsWithoutReload(config, clientTitle, resources, resourcePortMap, debug) if err != nil { return err } @@ -107,7 +107,7 @@ func generateAngieConfigs(config Config, clientTitle string, resources []Resourc } // writeAngieResourceConfig записывает конфигурацию для одного ресурса в Angie -func writeAngieResourceConfig(f *os.File, config Config, res ResourceData, containerPorts []PortMapping) error { +func writeAngieResourceConfig(f *os.File, config Config, res ResourceData, containerPorts []PortMapping, debug bool) error { allDomains := []string{res.ServerName} allDomains = append(allDomains, res.Aliases...) processedDomains := processDomainsWithWWW(allDomains) @@ -272,7 +272,7 @@ func writeAngieResourceConfig(f *os.File, config Config, res ResourceData, conta f.WriteString(fmt.Sprintf(" error_log /var/log/angie/%d_%s_error.log error;\n\n", res.L7ResourceID, res.ServerName)) writeNetworkSettings(f, config) - writeStandardServerSettings(f, getCustomServerDirectives(res.AppsSettings.ServerDirectivesAngieCustom)) + writeStandardServerSettings(f, getCustomServerDirectives(res.AppsSettings.ServerDirectivesAngieCustom), debug) if hasCustomLocation { log.Printf(" └─ Добавление location_angie_custom (отдельный блок) для l7ResourceID %d (HTTP, порт %d)", res.L7ResourceID, httpPort) @@ -325,7 +325,7 @@ func writeAngieResourceConfig(f *os.File, config Config, res ResourceData, conta } writeNetworkSettings(f, config) - writeStandardServerSettings(f, getCustomServerDirectives(res.AppsSettings.ServerDirectivesAngieCustom)) + writeStandardServerSettings(f, getCustomServerDirectives(res.AppsSettings.ServerDirectivesAngieCustom), debug) if hasCustomLocation { log.Printf(" └─ Добавление location_angie_custom (отдельный блок) для l7ResourceID %d (HTTPS, порт %d)", res.L7ResourceID, httpsPort) @@ -357,7 +357,7 @@ func writeAngieResourceConfig(f *os.File, config Config, res ResourceData, conta } log.Printf(" └─ Angie Server блок: порт %d, server_name %s%s", block.Port, block.ServerName, aliasInfo) - generateAngieCustomServerBlock(f, config, res, block, containerPorts, customLocationStr) + generateAngieCustomServerBlock(f, config, res, block, containerPorts, customLocationStr, debug) } } @@ -399,7 +399,7 @@ func writeAngieSSLSettings(f *os.File, customSSL sql.NullString) { } // writeStandardServerSettings записывает стандартные настройки сервера (Angie) -func writeStandardServerSettings(f *os.File, customDirectives string) { +func writeStandardServerSettings(f *os.File, customDirectives string, debug bool) { settings := ` server_tokens off; sendfile on; gzip on; @@ -419,6 +419,9 @@ func writeStandardServerSettings(f *os.File, customDirectives string) { proxy_pass_header Server; ` f.WriteString(settings) + if debug { + f.WriteString(" client_body_buffer_size 1m;\n") + } writeCustomOrDefaultDirectives(f, customDirectives) } @@ -472,7 +475,7 @@ func writeCustomOrDefaultDirectives(f *os.File, customDirectives string) { } // generateAngieCustomServerBlock генерирует кастомный server блок для Angie -func generateAngieCustomServerBlock(f *os.File, config Config, res ResourceData, block CustomServerBlock, containerPorts []PortMapping, customLocationStr string) { +func generateAngieCustomServerBlock(f *os.File, config Config, res ResourceData, block CustomServerBlock, containerPorts []PortMapping, customLocationStr string, debug bool) { var upstreamName string if block.IsHTTPS { upstreamName = fmt.Sprintf("secure%d_%d_%s", res.L7ResourceID, block.Port, res.ServerName) @@ -511,7 +514,7 @@ func generateAngieCustomServerBlock(f *os.File, config Config, res ResourceData, res.L7ResourceID, sanitizeServerName(block.ServerName), block.Port)) writeNetworkSettings(f, config) - writeStandardServerSettings(f, getCustomServerDirectives(res.AppsSettings.ServerDirectivesAngieCustom)) + writeStandardServerSettings(f, getCustomServerDirectives(res.AppsSettings.ServerDirectivesAngieCustom), debug) // Кастомные location блоки из location_angie_custom (перед location /) if customLocationStr != "" { diff --git a/ptaf_processor.go b/ptaf_processor.go index 2ec30cb..e287729 100644 --- a/ptaf_processor.go +++ b/ptaf_processor.go @@ -95,7 +95,7 @@ func processPTAFClient( // ════════════════════════════════════════════════════════════ // 1. Генерация конфигурации Angie БЕЗ автоматического reload - angieChanged, err := generateAngieConfigsWithoutReload(config, clientInfo.ClientTitle, resourcesData, resourcePortMap) + angieChanged, err := generateAngieConfigsWithoutReload(config, clientInfo.ClientTitle, resourcesData, resourcePortMap, clientInfo.Debug) if err != nil { log.Printf("Ошибка генерации конфигов Angie для %s: %v", clientInfo.ClientTitle, err) return false diff --git a/types.go b/types.go index d0a882a..f4fbadc 100644 --- a/types.go +++ b/types.go @@ -49,6 +49,7 @@ type ClientInfo struct { WAFInstance string // Instance для связи с apps_settings DockerImage sql.NullString // Образ Docker для контейнеров клиента DockerImageDownload sql.NullString // URL для скачивания образа + Debug bool // Режим отладки (влияет на лог-уровень и переменные окружения) } // Структуры для API ответов