Merge pull request #7 from swissmakers/main

sync dev
This commit is contained in:
Swissmakers GmbH
2025-02-19 15:04:29 +01:00
committed by GitHub
3 changed files with 53 additions and 15 deletions

View File

@@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"log" "log"
"os" "os"
"strconv"
"time" "time"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@@ -24,6 +25,7 @@ func main() {
// Create a new Gin router. // Create a new Gin router.
router := gin.Default() router := gin.Default()
serverPort := strconv.Itoa(int(settings.Port))
// Load HTML templates depending on whether the application is running inside a container. // Load HTML templates depending on whether the application is running inside a container.
_, container := os.LookupEnv("CONTAINER") _, container := os.LookupEnv("CONTAINER")
@@ -38,18 +40,18 @@ func main() {
// Register all application routes, including the static file serving route for locales. // Register all application routes, including the static file serving route for locales.
web.RegisterRoutes(router) web.RegisterRoutes(router)
printWelcomeBanner() printWelcomeBanner(serverPort)
log.Println("--- Fail2Ban-UI started in", gin.Mode(), "mode ---") log.Println("--- Fail2Ban-UI started in", gin.Mode(), "mode ---")
log.Println("Server listening on port :8080.") log.Println("Server listening on port", serverPort, ".")
// Start the server on port 8080. // Start the server on port 8080.
if err := router.Run(":8080"); err != nil { if err := router.Run(":" + serverPort); err != nil {
log.Fatalf("Server crashed: %v", err) log.Fatalf("Could not start server: %v\n", err)
} }
} }
// printWelcomeBanner prints a cool Tux banner with startup info. // printWelcomeBanner prints a cool Tux banner with startup info.
func printWelcomeBanner() { func printWelcomeBanner(appPort string) {
greeting := getGreeting() greeting := getGreeting()
const tuxBanner = ` const tuxBanner = `
.--. .--.
@@ -64,11 +66,11 @@ Fail2Ban UI - A Swissmade Management Interface
---------------------------------------------- ----------------------------------------------
Developers: https://swissmakers.ch Developers: https://swissmakers.ch
Mode: %s Mode: %s
Listening on: http://0.0.0.0:8080 Listening on: http://0.0.0.0:%s
---------------------------------------------- ----------------------------------------------
` `
fmt.Printf(tuxBanner, greeting, gin.Mode()) fmt.Printf(tuxBanner, greeting, gin.Mode(), appPort)
} }
// getGreeting returns a friendly greeting based on the time of day. // getGreeting returns a friendly greeting based on the time of day.

View File

@@ -20,6 +20,7 @@ import (
"bufio" "bufio"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"os" "os"
"regexp" "regexp"
"strconv" "strconv"
@@ -40,6 +41,7 @@ type SMTPSettings struct {
// AppSettings holds the main UI settings and Fail2ban configuration // AppSettings holds the main UI settings and Fail2ban configuration
type AppSettings struct { type AppSettings struct {
Language string `json:"language"` Language string `json:"language"`
Port int `json:"port"`
Debug bool `json:"debug"` Debug bool `json:"debug"`
ReloadNeeded bool `json:"reloadNeeded"` ReloadNeeded bool `json:"reloadNeeded"`
AlertCountries []string `json:"alertCountries"` AlertCountries []string `json:"alertCountries"`
@@ -57,7 +59,8 @@ type AppSettings struct {
// init paths to key-files // init paths to key-files
const ( const (
settingsFile = "fail2ban-ui-settings.json" // this is relative to where the app was started settingsFile = "fail2ban-ui-settings.json" // this file is created, relatively to where the app was started
defaultJailFile = "/etc/fail2ban/jail.conf"
jailFile = "/etc/fail2ban/jail.local" // Path to jail.local (to override conf-values from jail.conf) jailFile = "/etc/fail2ban/jail.local" // Path to jail.local (to override conf-values from jail.conf)
jailDFile = "/etc/fail2ban/jail.d/ui-custom-action.conf" jailDFile = "/etc/fail2ban/jail.d/ui-custom-action.conf"
actionFile = "/etc/fail2ban/action.d/ui-custom-action.conf" actionFile = "/etc/fail2ban/action.d/ui-custom-action.conf"
@@ -97,6 +100,9 @@ func setDefaults() {
if currentSettings.Language == "" { if currentSettings.Language == "" {
currentSettings.Language = "en" currentSettings.Language = "en"
} }
if currentSettings.Port == 0 {
currentSettings.Port = 8080
}
if currentSettings.AlertCountries == nil { if currentSettings.AlertCountries == nil {
currentSettings.AlertCountries = []string{"ALL"} currentSettings.AlertCountries = []string{"ALL"}
} }
@@ -201,7 +207,19 @@ func initializeFail2banAction() error {
func setupGeoCustomAction() error { func setupGeoCustomAction() error {
file, err := os.Open(jailFile) file, err := os.Open(jailFile)
if err != nil { if err != nil {
return err // File not found or inaccessible // Fallback: Copy default file if jail.local is not found
if os.IsNotExist(err) {
if err := copyFile(defaultJailFile, jailFile); err != nil {
return fmt.Errorf("failed to copy default jail.conf to jail.local: %w", err)
}
fmt.Println("Successfully created jail.local from jail.conf.")
file, err = os.Open(jailFile)
if err != nil {
return err
}
} else {
return err // Other error
}
} }
defer file.Close() defer file.Close()
@@ -246,6 +264,24 @@ func setupGeoCustomAction() error {
return os.WriteFile(jailFile, []byte(output), 0644) return os.WriteFile(jailFile, []byte(output), 0644)
} }
// copyFile copies a file from src to dst. If the destination file does not exist, it will be created.
func copyFile(src, dst string) error {
sourceFile, err := os.Open(src)
if err != nil {
return err
}
defer sourceFile.Close()
destFile, err := os.Create(dst)
if err != nil {
return err
}
defer destFile.Close()
_, err = io.Copy(destFile, sourceFile)
return err
}
// ensureJailDConfig checks if the jail.d file exists and creates it if necessary // ensureJailDConfig checks if the jail.d file exists and creates it if necessary
func ensureJailDConfig() error { func ensureJailDConfig() error {
// Check if the file already exists // Check if the file already exists

View File

@@ -37,7 +37,7 @@ func GetJails() ([]string, error) {
cmd := exec.Command("fail2ban-client", "status") cmd := exec.Command("fail2ban-client", "status")
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
if err != nil { if err != nil {
return nil, fmt.Errorf("could not get jail information. is fail2ban running? error: %v", err) return nil, fmt.Errorf("error: unable to retrieve jail information. is your fail2ban service running? details: %v", err)
} }
var jails []string var jails []string