UpdateDefaultSettings now checks CheckJailLocalIntegrity as first and returns error if not managed by Fail2ban-UI

This commit is contained in:
2026-02-09 22:33:13 +01:00
parent 5dbe12917b
commit 8f9399196e
4 changed files with 77 additions and 7 deletions

View File

@@ -410,6 +410,21 @@ func (ac *AgentConnector) TestLogpathWithResolution(ctx context.Context, logpath
// UpdateDefaultSettings implements Connector.
func (ac *AgentConnector) UpdateDefaultSettings(ctx context.Context, settings config.AppSettings) error {
// Check jail.local integrity first
exists, hasUI, chkErr := ac.CheckJailLocalIntegrity(ctx)
if chkErr != nil {
config.DebugLog("Warning: could not check jail.local integrity on agent %s: %v", ac.server.Name, chkErr)
}
if exists && !hasUI {
return fmt.Errorf("jail.local on agent server %s is not managed by Fail2ban-UI - skipping settings update (please migrate your jail.local manually)", ac.server.Name)
}
if !exists {
config.DebugLog("jail.local does not exist on agent server %s - initializing fresh managed file", ac.server.Name)
if err := ac.EnsureJailLocalStructure(ctx); err != nil {
return fmt.Errorf("failed to initialize jail.local on agent server %s: %w", ac.server.Name, err)
}
}
// Convert IgnoreIPs array to space-separated string
ignoreIPStr := strings.Join(settings.IgnoreIPs, " ")
if ignoreIPStr == "" {

View File

@@ -1555,10 +1555,28 @@ PYEOF
func (sc *SSHConnector) UpdateDefaultSettings(ctx context.Context, settings config.AppSettings) error {
jailLocalPath := "/etc/fail2ban/jail.local"
// Read existing file if it exists
// Check jail.local integrity first
exists, hasUI, chkErr := sc.CheckJailLocalIntegrity(ctx)
if chkErr != nil {
config.DebugLog("Warning: could not check jail.local integrity on %s: %v", sc.server.Name, chkErr)
}
if exists && !hasUI {
// File belongs to the user never overwrite
return fmt.Errorf("jail.local on server %s is not managed by Fail2ban-UI - skipping settings update (please migrate your jail.local manually)", sc.server.Name)
}
if !exists {
// File was deleted (e.g. user finished migration) create a fresh managed file
config.DebugLog("jail.local does not exist on server %s - initializing fresh managed file", sc.server.Name)
if err := sc.EnsureJailLocalStructure(ctx); err != nil {
return fmt.Errorf("failed to initialize jail.local on server %s: %w", sc.server.Name, err)
}
}
// Read existing file
existingContent, err := sc.runRemoteCommand(ctx, []string{"cat", jailLocalPath})
if err != nil {
// File doesn't exist, create new one
existingContent = ""
}

View File

@@ -1071,14 +1071,35 @@ func UpdateDefaultSettingsLocal(settings config.AppSettings) error {
config.DebugLog("UpdateDefaultSettingsLocal called")
localPath := "/etc/fail2ban/jail.local"
// Read existing file if it exists
// Check jail.local integrity first
var existingContent string
fileExists := false
if content, err := os.ReadFile(localPath); err == nil {
existingContent = string(content)
fileExists = len(strings.TrimSpace(existingContent)) > 0
} else if !os.IsNotExist(err) {
return fmt.Errorf("failed to read jail.local: %w", err)
}
hasUIAction := strings.Contains(existingContent, "ui-custom-action")
if fileExists && !hasUIAction {
// File belongs to the user never overwrite
return fmt.Errorf("jail.local is not managed by Fail2ban-UI - skipping settings update (please migrate your jail.local manually)")
}
if !fileExists {
// File was deleted (e.g. user finished migration); create a fresh managed file
config.DebugLog("jail.local does not exist - initializing fresh managed file")
if err := config.EnsureJailLocalStructure(); err != nil {
return fmt.Errorf("failed to initialize jail.local: %w", err)
}
// Re-read the freshly created file
if content, err := os.ReadFile(localPath); err == nil {
existingContent = string(content)
}
}
// Remove commented lines (lines starting with #) but preserve:
// - Banner lines (containing "Fail2Ban-UI" or "fail2ban-ui")
// - action_mwlg and action override lines