From 36508201adc2acb3db4cc7e027ea352b1d37ff9e Mon Sep 17 00:00:00 2001 From: d3m0k1d Date: Wed, 14 Jan 2026 17:20:08 +0300 Subject: [PATCH] feat: Add rule control command to cli interface --- cmd/banforge/main.go | 59 ++++++++++++++++++++++++++ internal/config/appconf.go | 84 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) diff --git a/cmd/banforge/main.go b/cmd/banforge/main.go index 3894a30..181fce4 100644 --- a/cmd/banforge/main.go +++ b/cmd/banforge/main.go @@ -14,6 +14,14 @@ import ( "github.com/spf13/cobra" ) +var ( + name string + service string + path string + status string + method string +) + var rootCmd = &cobra.Command{ Use: "banforge", Short: "IPS log-based written on Golang", @@ -193,6 +201,48 @@ var daemonCmd = &cobra.Command{ }, } +var ruleCmd = &cobra.Command{ + Use: "rule", + Short: "Manage rules", +} + +var addCmd = &cobra.Command{ + Use: "add", + Short: "CLI interface for add new rule to file /etc/banforge/rules.toml", + Run: func(cmd *cobra.Command, args []string) { + if name == "" { + fmt.Printf("Rule name can't be empty\n") + os.Exit(1) + } + if service == "" && path == "" && status == "" && method == "" { + fmt.Printf("At least 1 rule field must be filled in.") + os.Exit(1) + } + + err := config.NewRule(name, service, path, status, method) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + fmt.Println("Rule added successfully!") + }, +} + +var listCmd = &cobra.Command{ + Use: "list", + Short: "List rules", + Run: func(cmd *cobra.Command, args []string) { + r, err := config.LoadRuleConfig() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + for _, rule := range r { + fmt.Printf("Name: %s\nService: %s\nPath: %s\nStatus: %s\nMethod: %s\n\n", rule.Name, rule.ServiceName, rule.Path, rule.Status, rule.Method) + } + }, +} + func Init() { } @@ -200,6 +250,15 @@ func Init() { func Execute() { rootCmd.AddCommand(daemonCmd) rootCmd.AddCommand(initCmd) + rootCmd.AddCommand(ruleCmd) + // Rule comand block + ruleCmd.AddCommand(addCmd) + ruleCmd.AddCommand(listCmd) + addCmd.Flags().StringVarP(&name, "name", "n", "", "rule name (required)") + addCmd.Flags().StringVarP(&service, "service", "s", "", "service name") + addCmd.Flags().StringVarP(&path, "path", "p", "", "request path") + addCmd.Flags().StringVarP(&status, "status", "c", "", "HTTP status code") + addCmd.Flags().StringVarP(&method, "method", "m", "", "HTTP method") if err := rootCmd.Execute(); err != nil { fmt.Println(err) os.Exit(1) diff --git a/internal/config/appconf.go b/internal/config/appconf.go index c181121..68fd56a 100644 --- a/internal/config/appconf.go +++ b/internal/config/appconf.go @@ -2,6 +2,7 @@ package config import ( "fmt" + "os" "github.com/BurntSushi/toml" "github.com/d3m0k1d/BanForge/internal/logger" @@ -20,3 +21,86 @@ func LoadRuleConfig() ([]Rule, error) { log.Info(fmt.Sprintf("loaded %d rules", len(cfg.Rules))) return cfg.Rules, nil } + +func NewRule(Name string, ServiceName string, Path string, Status string, Method string) error { + r, err := LoadRuleConfig() + if err != nil { + r = []Rule{} + } + if Name == "" { + fmt.Printf("Rule name can't be empty\n") + return nil + } + r = append(r, Rule{Name: Name, ServiceName: ServiceName, Path: Path, Status: Status, Method: Method}) + file, err := os.Create("/etc/banforge/rules.toml") + if err != nil { + return err + } + defer func() { + err = file.Close() + if err != nil { + fmt.Println(err) + } + }() + cfg := Rules{Rules: r} + + err = toml.NewEncoder(file).Encode(cfg) + if err != nil { + return err + } + return nil +} + +func EditRule(Name string, ServiceName string, Path string, Status string, Method string) error { + if Name == "" { + return fmt.Errorf("Rule name can't be empty") + } + + r, err := LoadRuleConfig() + if err != nil { + return fmt.Errorf("rules is empty, please use 'banforge add rule' or create rules.toml") + } + + found := false + for i, rule := range r { + if rule.Name == Name { + found = true + + if ServiceName != "" { + r[i].ServiceName = ServiceName + } + if Path != "" { + r[i].Path = Path + } + if Status != "" { + r[i].Status = Status + } + if Method != "" { + r[i].Method = Method + } + break + } + } + + if !found { + return fmt.Errorf("rule '%s' not found", Name) + } + + file, err := os.Create("/etc/banforge/rules.toml") + if err != nil { + return err + } + defer func() { + err = file.Close() + if err != nil { + fmt.Println(err) + } + }() + + cfg := Rules{Rules: r} + if err := toml.NewEncoder(file).Encode(cfg); err != nil { + return fmt.Errorf("failed to encode config: %w", err) + } + + return nil +}