Dedublicate banner stuff and add missing init-vars for banactions

This commit is contained in:
2025-12-04 20:36:23 +01:00
parent 0f2a3a1e32
commit def440611a
3 changed files with 75 additions and 35 deletions

View File

@@ -132,6 +132,24 @@ const (
actionServerIDPlaceholder = "__SERVER_ID__" actionServerIDPlaceholder = "__SERVER_ID__"
) )
// jailLocalBanner is the standard banner for jail.local files
const jailLocalBanner = `################################################################################
# Fail2Ban-UI Managed Configuration
#
# WARNING: This file is automatically managed by Fail2Ban-UI.
# DO NOT EDIT THIS FILE MANUALLY - your changes will be overwritten.
#
# This file overrides settings from /etc/fail2ban/jail.conf
# Custom jail configurations should be placed in /etc/fail2ban/jail.d/
################################################################################
`
// JailLocalBanner returns the standard banner for jail.local files
func JailLocalBanner() string {
return jailLocalBanner
}
const fail2banActionTemplate = `[INCLUDES] const fail2banActionTemplate = `[INCLUDES]
before = sendmail-common.conf before = sendmail-common.conf
@@ -771,18 +789,8 @@ func ensureJailLocalStructure() error {
return updateJailLocalDefaultSection(settings) return updateJailLocalDefaultSection(settings)
} }
// Build the banner // Use the standard banner
banner := `################################################################################ banner := jailLocalBanner
# Fail2Ban-UI Managed Configuration
#
# WARNING: This file is automatically managed by Fail2Ban-UI.
# DO NOT EDIT THIS FILE MANUALLY - your changes will be overwritten.
#
# This file overrides settings from /etc/fail2ban/jail.conf
# Custom jail configurations should be placed in /etc/fail2ban/jail.d/
################################################################################
`
// Build [DEFAULT] section // Build [DEFAULT] section
// Convert IgnoreIPs array to space-separated string // Convert IgnoreIPs array to space-separated string
@@ -846,7 +854,8 @@ func updateJailLocalDefaultSection(settings AppSettings) error {
return fmt.Errorf("failed to read jail.local: %w", err) return fmt.Errorf("failed to read jail.local: %w", err)
} }
lines := strings.Split(string(content), "\n") contentStr := string(content)
lines := strings.Split(contentStr, "\n")
var outputLines []string var outputLines []string
inDefault := false inDefault := false
defaultUpdated := false defaultUpdated := false
@@ -878,9 +887,23 @@ func updateJailLocalDefaultSection(settings AppSettings) error {
} }
keysUpdated := make(map[string]bool) keysUpdated := make(map[string]bool)
// Always add the full banner at the start
outputLines = append(outputLines, strings.Split(strings.TrimRight(jailLocalBanner, "\n"), "\n")...)
// Skip everything before [DEFAULT] section (old banner, comments, empty lines)
foundSection := false
for _, line := range lines { for _, line := range lines {
trimmed := strings.TrimSpace(line) trimmed := strings.TrimSpace(line)
if strings.HasPrefix(trimmed, "[") && strings.HasSuffix(trimmed, "]") {
// Found a section - stop skipping and process this line
foundSection = true
}
if !foundSection {
// Skip lines before any section (old banner, comments, empty lines)
continue
}
// Process lines after we found a section
if strings.HasPrefix(trimmed, "[") && strings.HasSuffix(trimmed, "]") { if strings.HasPrefix(trimmed, "[") && strings.HasSuffix(trimmed, "]") {
sectionName := strings.Trim(trimmed, "[]") sectionName := strings.Trim(trimmed, "[]")
if sectionName == "DEFAULT" { if sectionName == "DEFAULT" {

View File

@@ -782,6 +782,7 @@ jail_file = '%s'
ignore_ip_str = '%s' ignore_ip_str = '%s'
banaction_val = '%s' banaction_val = '%s'
banaction_allports_val = '%s' banaction_allports_val = '%s'
banner_content = """%s"""
settings = { settings = {
'bantime_increment': %t, 'bantime_increment': %t,
'ignoreip': ignore_ip_str, 'ignoreip': ignore_ip_str,
@@ -816,13 +817,23 @@ if has_full_banner and has_action_mwlg and has_action_override:
except FileNotFoundError: except FileNotFoundError:
lines = [] lines = []
# Always add the full banner at the start
output_lines = [] output_lines = []
in_default = False output_lines.extend(banner_content.splitlines())
keys_updated = set() output_lines.append('')
# Skip everything before [DEFAULT] section (old banner, comments, empty lines)
found_section = False
for line in lines: for line in lines:
stripped = line.strip() stripped = line.strip()
if stripped.startswith('[') and stripped.endswith(']'):
# Found a section - stop skipping and process this line
found_section = True
if not found_section:
# Skip lines before any section (old banner, comments, empty lines)
continue
# Process lines after we found a section
if stripped.startswith('[') and stripped.endswith(']'): if stripped.startswith('[') and stripped.endswith(']'):
section_name = stripped.strip('[]') section_name = stripped.strip('[]')
if section_name == "DEFAULT": if section_name == "DEFAULT":
@@ -876,17 +887,7 @@ if has_full_banner and has_action_mwlg and has_action_override:
f.writelines(output_lines) f.writelines(output_lines)
else: else:
# Create new structure # Create new structure
banner = """################################################################################ banner = banner_content
# Fail2Ban-UI Managed Configuration
#
# WARNING: This file is automatically managed by Fail2Ban-UI.
# DO NOT EDIT THIS FILE MANUALLY - your changes will be overwritten.
#
# This file overrides settings from /etc/fail2ban/jail.conf
# Custom jail configurations should be placed in /etc/fail2ban/jail.d/
################################################################################
"""
default_section = """[DEFAULT] default_section = """[DEFAULT]
bantime.increment = """ + str(settings['bantime_increment']) + """ bantime.increment = """ + str(settings['bantime_increment']) + """
@@ -914,7 +915,7 @@ action = %%(action_mwlg)s
with open(jail_file, 'w') as f: with open(jail_file, 'w') as f:
f.write(new_content) f.write(new_content)
PY`, escapeForShell(jailLocalPath), escapeForShell(ignoreIPStr), escapeForShell(banactionVal), escapeForShell(banactionAllportsVal), settings.BantimeIncrement, PY`, escapeForShell(jailLocalPath), escapeForShell(ignoreIPStr), escapeForShell(banactionVal), escapeForShell(banactionAllportsVal), escapeForShell(config.JailLocalBanner()), settings.BantimeIncrement,
escapeForShell(settings.Bantime), escapeForShell(settings.Findtime), settings.Maxretry, escapeForShell(settings.Destemail)) escapeForShell(settings.Bantime), escapeForShell(settings.Findtime), settings.Maxretry, escapeForShell(settings.Destemail))
_, err := sc.runRemoteCommand(ctx, []string{"bash", "-lc", ensureScript}) _, err := sc.runRemoteCommand(ctx, []string{"bash", "-lc", ensureScript})

View File

@@ -627,17 +627,19 @@ func UpdateDefaultSettingsLocal(settings config.AppSettings) error {
// Parse existing content and update only specific keys in DEFAULT section // Parse existing content and update only specific keys in DEFAULT section
if existingContent == "" { if existingContent == "" {
// File doesn't exist, create new one with DEFAULT section // File doesn't exist, create new one with banner and DEFAULT section
defaultLines := []string{"[DEFAULT]"} var newLines []string
for _, key := range []string{"bantime.increment", "ignoreip", "bantime", "findtime", "maxretry", "destemail"} { newLines = append(newLines, strings.Split(strings.TrimRight(config.JailLocalBanner(), "\n"), "\n")...)
defaultLines = append(defaultLines, keysToUpdate[key]) newLines = append(newLines, "[DEFAULT]")
for _, key := range []string{"bantime.increment", "ignoreip", "bantime", "findtime", "maxretry", "destemail", "banaction", "banaction_allports"} {
newLines = append(newLines, keysToUpdate[key])
} }
defaultLines = append(defaultLines, "") newLines = append(newLines, "")
newContent := strings.Join(defaultLines, "\n") newContent := strings.Join(newLines, "\n")
if err := os.WriteFile(localPath, []byte(newContent), 0644); err != nil { if err := os.WriteFile(localPath, []byte(newContent), 0644); err != nil {
return fmt.Errorf("failed to write jail.local: %w", err) return fmt.Errorf("failed to write jail.local: %w", err)
} }
config.DebugLog("Created new jail.local with DEFAULT section") config.DebugLog("Created new jail.local with banner and DEFAULT section")
return nil return nil
} }
@@ -647,9 +649,23 @@ func UpdateDefaultSettingsLocal(settings config.AppSettings) error {
inDefault := false inDefault := false
defaultSectionFound := false defaultSectionFound := false
// Always add the full banner at the start
outputLines = append(outputLines, strings.Split(strings.TrimRight(config.JailLocalBanner(), "\n"), "\n")...)
// Skip everything before [DEFAULT] section (old banner, comments, empty lines)
foundSection := false
for _, line := range lines { for _, line := range lines {
trimmed := strings.TrimSpace(line) trimmed := strings.TrimSpace(line)
if strings.HasPrefix(trimmed, "[") && strings.HasSuffix(trimmed, "]") {
// Found a section - stop skipping and process this line
foundSection = true
}
if !foundSection {
// Skip lines before any section (old banner, comments, empty lines)
continue
}
// Process lines after we found a section
if strings.HasPrefix(trimmed, "[") && strings.HasSuffix(trimmed, "]") { if strings.HasPrefix(trimmed, "[") && strings.HasSuffix(trimmed, "]") {
sectionName := strings.Trim(trimmed, "[]") sectionName := strings.Trim(trimmed, "[]")
if sectionName == "DEFAULT" { if sectionName == "DEFAULT" {
@@ -695,7 +711,7 @@ func UpdateDefaultSettingsLocal(settings config.AppSettings) error {
outputLines = append(defaultLines, outputLines...) outputLines = append(defaultLines, outputLines...)
} else { } else {
// Add any missing keys to the DEFAULT section // Add any missing keys to the DEFAULT section
for _, key := range []string{"bantime.increment", "ignoreip", "bantime", "findtime", "maxretry", "destemail"} { for _, key := range []string{"bantime.increment", "ignoreip", "bantime", "findtime", "maxretry", "destemail", "banaction", "banaction_allports"} {
if !keysUpdated[key] { if !keysUpdated[key] {
// Find the DEFAULT section and insert after it // Find the DEFAULT section and insert after it
for i, line := range outputLines { for i, line := range outputLines {