2018-04-02 05:25:32 +02:00
|
|
|
package rule
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
2020-05-10 17:33:39 +02:00
|
|
|
"os"
|
2018-04-08 16:36:12 +02:00
|
|
|
"path"
|
2018-04-02 05:25:32 +02:00
|
|
|
"path/filepath"
|
2020-10-21 08:13:41 +02:00
|
|
|
"sort"
|
2018-04-08 16:36:12 +02:00
|
|
|
"strings"
|
2018-04-02 05:25:32 +02:00
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
2020-12-09 18:18:42 +01:00
|
|
|
"github.com/evilsocket/opensnitch/daemon/conman"
|
|
|
|
"github.com/evilsocket/opensnitch/daemon/core"
|
|
|
|
"github.com/evilsocket/opensnitch/daemon/log"
|
2023-09-22 00:36:26 +02:00
|
|
|
"github.com/evilsocket/opensnitch/daemon/procmon"
|
2018-04-08 16:36:12 +02:00
|
|
|
|
|
|
|
"github.com/fsnotify/fsnotify"
|
2018-04-02 05:25:32 +02:00
|
|
|
)
|
|
|
|
|
2020-05-10 17:33:39 +02:00
|
|
|
// Loader is the object that holds the rules loaded from disk, as well as the
|
|
|
|
// rules watcher.
|
2018-04-02 05:25:32 +02:00
|
|
|
type Loader struct {
|
2024-01-14 20:44:49 +01:00
|
|
|
watcher *fsnotify.Watcher
|
2018-04-08 16:36:12 +02:00
|
|
|
rules map[string]*Rule
|
2023-09-22 00:36:26 +02:00
|
|
|
rulesKeys []string
|
improved rules reloading, cli parameters
- When reloading rules from a path:
stop existing (domains,ips,regexp) lists monitors, stop rules
watcher and start watching the new dir for changes, delete existing
rules from memory, etc.
- Previously, cli parameters (queue number, log file, etc) were taking
into account before loading the configuration.
Now the configuration file is loaded first (default-config.json), and
if any of the cli parameter has been specified, it'll overwrite the
loaded configuration from file.
This means for example that if you use "-process-monitor-method proc",
and "ebpf" is configured in default-config.json, firstly "ebpf" will
be configured, and later "proc".
(-queue-num option for now requires to match config option
cfg.FwOptions.QueueNumber)
2024-05-22 00:47:54 +02:00
|
|
|
Path string
|
2018-04-08 16:36:12 +02:00
|
|
|
liveReload bool
|
|
|
|
liveReloadRunning bool
|
2023-09-22 00:36:26 +02:00
|
|
|
checkSums bool
|
improved rules reloading, cli parameters
- When reloading rules from a path:
stop existing (domains,ips,regexp) lists monitors, stop rules
watcher and start watching the new dir for changes, delete existing
rules from memory, etc.
- Previously, cli parameters (queue number, log file, etc) were taking
into account before loading the configuration.
Now the configuration file is loaded first (default-config.json), and
if any of the cli parameter has been specified, it'll overwrite the
loaded configuration from file.
This means for example that if you use "-process-monitor-method proc",
and "ebpf" is configured in default-config.json, firstly "ebpf" will
be configured, and later "proc".
(-queue-num option for now requires to match config option
cfg.FwOptions.QueueNumber)
2024-05-22 00:47:54 +02:00
|
|
|
stopLiveReload chan struct{}
|
2024-01-14 20:44:49 +01:00
|
|
|
|
|
|
|
sync.RWMutex
|
2018-04-02 05:25:32 +02:00
|
|
|
}
|
|
|
|
|
2020-05-10 17:33:39 +02:00
|
|
|
// NewLoader loads rules from disk, and watches for changes made to the rules files
|
|
|
|
// on disk.
|
2018-04-08 16:36:12 +02:00
|
|
|
func NewLoader(liveReload bool) (*Loader, error) {
|
|
|
|
watcher, err := fsnotify.NewWatcher()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2018-04-02 05:25:32 +02:00
|
|
|
}
|
2018-04-08 16:36:12 +02:00
|
|
|
return &Loader{
|
improved rules reloading, cli parameters
- When reloading rules from a path:
stop existing (domains,ips,regexp) lists monitors, stop rules
watcher and start watching the new dir for changes, delete existing
rules from memory, etc.
- Previously, cli parameters (queue number, log file, etc) were taking
into account before loading the configuration.
Now the configuration file is loaded first (default-config.json), and
if any of the cli parameter has been specified, it'll overwrite the
loaded configuration from file.
This means for example that if you use "-process-monitor-method proc",
and "ebpf" is configured in default-config.json, firstly "ebpf" will
be configured, and later "proc".
(-queue-num option for now requires to match config option
cfg.FwOptions.QueueNumber)
2024-05-22 00:47:54 +02:00
|
|
|
Path: "",
|
2018-04-08 16:36:12 +02:00
|
|
|
rules: make(map[string]*Rule),
|
|
|
|
liveReload: liveReload,
|
|
|
|
watcher: watcher,
|
|
|
|
liveReloadRunning: false,
|
improved rules reloading, cli parameters
- When reloading rules from a path:
stop existing (domains,ips,regexp) lists monitors, stop rules
watcher and start watching the new dir for changes, delete existing
rules from memory, etc.
- Previously, cli parameters (queue number, log file, etc) were taking
into account before loading the configuration.
Now the configuration file is loaded first (default-config.json), and
if any of the cli parameter has been specified, it'll overwrite the
loaded configuration from file.
This means for example that if you use "-process-monitor-method proc",
and "ebpf" is configured in default-config.json, firstly "ebpf" will
be configured, and later "proc".
(-queue-num option for now requires to match config option
cfg.FwOptions.QueueNumber)
2024-05-22 00:47:54 +02:00
|
|
|
stopLiveReload: make(chan struct{}),
|
2018-04-08 16:36:12 +02:00
|
|
|
}, nil
|
2018-04-02 05:25:32 +02:00
|
|
|
}
|
|
|
|
|
2020-05-10 17:33:39 +02:00
|
|
|
// NumRules returns he number of loaded rules.
|
2018-04-02 05:25:32 +02:00
|
|
|
func (l *Loader) NumRules() int {
|
2020-06-20 18:58:59 +02:00
|
|
|
l.RLock()
|
|
|
|
defer l.RUnlock()
|
2018-04-02 05:25:32 +02:00
|
|
|
return len(l.rules)
|
|
|
|
}
|
|
|
|
|
2021-03-01 12:41:35 +01:00
|
|
|
// GetAll returns the loaded rules.
|
|
|
|
func (l *Loader) GetAll() map[string]*Rule {
|
|
|
|
l.RLock()
|
|
|
|
defer l.RUnlock()
|
|
|
|
return l.rules
|
|
|
|
}
|
|
|
|
|
2023-09-22 00:36:26 +02:00
|
|
|
// EnableChecksums enables checksums field for rules globally.
|
|
|
|
func (l *Loader) EnableChecksums(enable bool) {
|
2023-09-22 01:21:27 +02:00
|
|
|
log.Debug("[rules loader] EnableChecksums: %v", enable)
|
2023-09-22 00:36:26 +02:00
|
|
|
l.checkSums = enable
|
|
|
|
procmon.EventsCache.SetComputeChecksums(enable)
|
2023-11-10 11:28:54 +01:00
|
|
|
procmon.EventsCache.AddChecksumHash(string(OpProcessHashMD5))
|
2023-09-22 00:36:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// HasChecksums checks if the rule will check for binary checksum matches
|
|
|
|
func (l *Loader) HasChecksums(op Operand) {
|
|
|
|
if op == OpProcessHashMD5 {
|
|
|
|
log.Debug("[rules loader] Adding MD5")
|
|
|
|
procmon.EventsCache.AddChecksumHash(string(OpProcessHashMD5))
|
|
|
|
} else if op == OpProcessHashSHA1 {
|
|
|
|
log.Debug("[rules loader] Adding SHA1")
|
|
|
|
procmon.EventsCache.AddChecksumHash(string(OpProcessHashSHA1))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-02 21:14:59 +02:00
|
|
|
// Reload loads rules from the specified path, deleting existing loaded
|
|
|
|
// rules from memory.
|
|
|
|
func (l *Loader) Reload(path string) error {
|
improved rules reloading, cli parameters
- When reloading rules from a path:
stop existing (domains,ips,regexp) lists monitors, stop rules
watcher and start watching the new dir for changes, delete existing
rules from memory, etc.
- Previously, cli parameters (queue number, log file, etc) were taking
into account before loading the configuration.
Now the configuration file is loaded first (default-config.json), and
if any of the cli parameter has been specified, it'll overwrite the
loaded configuration from file.
This means for example that if you use "-process-monitor-method proc",
and "ebpf" is configured in default-config.json, firstly "ebpf" will
be configured, and later "proc".
(-queue-num option for now requires to match config option
cfg.FwOptions.QueueNumber)
2024-05-22 00:47:54 +02:00
|
|
|
log.Info("rules.Loader.Reload(): %s", path)
|
|
|
|
|
|
|
|
// check that the new path exists before reloading
|
|
|
|
if core.Exists(path) == false {
|
|
|
|
return fmt.Errorf("The new path '%s' does not exist", path)
|
|
|
|
}
|
|
|
|
|
|
|
|
// stop monitors
|
|
|
|
if l.liveReloadRunning {
|
|
|
|
l.stopLiveReload <- struct{}{}
|
|
|
|
}
|
|
|
|
if l.watcher != nil {
|
|
|
|
l.watcher.Remove(l.Path)
|
|
|
|
}
|
|
|
|
for _, r := range l.rules {
|
|
|
|
l.cleanListsRule(r)
|
|
|
|
}
|
|
|
|
|
|
|
|
// then delete the rules, and reload everything
|
|
|
|
l.Lock()
|
2024-05-02 21:14:59 +02:00
|
|
|
l.rulesKeys = make([]string, 0)
|
|
|
|
l.rules = make(map[string]*Rule)
|
improved rules reloading, cli parameters
- When reloading rules from a path:
stop existing (domains,ips,regexp) lists monitors, stop rules
watcher and start watching the new dir for changes, delete existing
rules from memory, etc.
- Previously, cli parameters (queue number, log file, etc) were taking
into account before loading the configuration.
Now the configuration file is loaded first (default-config.json), and
if any of the cli parameter has been specified, it'll overwrite the
loaded configuration from file.
This means for example that if you use "-process-monitor-method proc",
and "ebpf" is configured in default-config.json, firstly "ebpf" will
be configured, and later "proc".
(-queue-num option for now requires to match config option
cfg.FwOptions.QueueNumber)
2024-05-22 00:47:54 +02:00
|
|
|
l.Unlock()
|
2024-05-02 21:14:59 +02:00
|
|
|
return l.Load(path)
|
|
|
|
}
|
|
|
|
|
2020-05-10 17:33:39 +02:00
|
|
|
// Load loads rules files from disk.
|
2018-04-02 05:25:32 +02:00
|
|
|
func (l *Loader) Load(path string) error {
|
improved rules reloading, cli parameters
- When reloading rules from a path:
stop existing (domains,ips,regexp) lists monitors, stop rules
watcher and start watching the new dir for changes, delete existing
rules from memory, etc.
- Previously, cli parameters (queue number, log file, etc) were taking
into account before loading the configuration.
Now the configuration file is loaded first (default-config.json), and
if any of the cli parameter has been specified, it'll overwrite the
loaded configuration from file.
This means for example that if you use "-process-monitor-method proc",
and "ebpf" is configured in default-config.json, firstly "ebpf" will
be configured, and later "proc".
(-queue-num option for now requires to match config option
cfg.FwOptions.QueueNumber)
2024-05-22 00:47:54 +02:00
|
|
|
log.Debug("rules.Loader.Load(): %s", path)
|
2018-04-02 05:25:32 +02:00
|
|
|
if core.Exists(path) == false {
|
2023-12-17 00:22:07 +01:00
|
|
|
return fmt.Errorf("Path '%s' does not exist\nCreate it if you want to save rules to disk", path)
|
2022-10-23 11:36:51 +02:00
|
|
|
}
|
|
|
|
path, err := core.ExpandPath(path)
|
|
|
|
if err != nil {
|
2023-12-17 00:22:07 +01:00
|
|
|
return fmt.Errorf("Error accessing rules path: %s.\nCreate it if you want to save rules to disk", err)
|
2018-04-02 05:25:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
expr := filepath.Join(path, "*.json")
|
|
|
|
matches, err := filepath.Glob(expr)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Error globbing '%s': %s", expr, err)
|
|
|
|
}
|
|
|
|
|
improved rules reloading, cli parameters
- When reloading rules from a path:
stop existing (domains,ips,regexp) lists monitors, stop rules
watcher and start watching the new dir for changes, delete existing
rules from memory, etc.
- Previously, cli parameters (queue number, log file, etc) were taking
into account before loading the configuration.
Now the configuration file is loaded first (default-config.json), and
if any of the cli parameter has been specified, it'll overwrite the
loaded configuration from file.
This means for example that if you use "-process-monitor-method proc",
and "ebpf" is configured in default-config.json, firstly "ebpf" will
be configured, and later "proc".
(-queue-num option for now requires to match config option
cfg.FwOptions.QueueNumber)
2024-05-22 00:47:54 +02:00
|
|
|
l.Path = path
|
2019-08-13 19:19:17 +02:00
|
|
|
if len(l.rules) == 0 {
|
|
|
|
l.rules = make(map[string]*Rule)
|
|
|
|
}
|
2018-04-02 05:25:32 +02:00
|
|
|
|
|
|
|
for _, fileName := range matches {
|
2018-04-10 20:04:59 +02:00
|
|
|
log.Debug("Reading rule from %s", fileName)
|
2018-04-02 05:25:32 +02:00
|
|
|
|
2021-02-27 01:39:04 +01:00
|
|
|
if err := l.loadRule(fileName); err != nil {
|
|
|
|
log.Warning("%s", err)
|
2020-05-11 10:39:56 +02:00
|
|
|
continue
|
2018-04-02 05:25:32 +02:00
|
|
|
}
|
2019-08-13 19:19:17 +02:00
|
|
|
}
|
2018-04-02 05:25:32 +02:00
|
|
|
|
2018-04-08 16:36:12 +02:00
|
|
|
if l.liveReload && l.liveReloadRunning == false {
|
|
|
|
go l.liveReloadWorker()
|
|
|
|
}
|
|
|
|
|
2018-04-02 05:25:32 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
rules: improved operator list parsing and conversion
Previously when creating a new rule we followed these steps:
- Create a new protobuf Rule object from the ruleseditor or the
pop-ups.
- If the rule contained more than one operator, we converted the
list of operators to a JSON string.
- This JSON string was sent back to the daemon, and saved to the
DB.
- The list of operators were never expanded on the GUI, i.e., they
were not saved as a list of protobuf Operator objects.
- Once received in the daemon, the JSON string was parsed and
converted to a protobuf Operator list of objects.
Both, the JSON string and the list of protobuf Operator objects were
saved to disk, but the JSON string was ignored when loading the
rules.
Saving the list of operators as a JSON string was a problem if you
wanted to create or modify rules without the GUI.
Now when creating or modifying rules from the GUI, the list of operators
is no longer converted to JSON string. Instead the list is sent to the
daemon as a list of protobuf Operators, and saved as JSON objects.
Notes:
- The JSON string is no longer saved to disk as part of the rules.
- The list of operators is still saved as JSON string to the DB.
- About not enabled rules:
Previously, not enabled rules only had the list of operators as JSON
string, with the field list:[] empty.
Now the list of operators is saved as JSON objects, but if the rule
is not enabled, it won't be parsed/loaded.
Closes #1047
2023-10-09 14:55:15 +02:00
|
|
|
// Add adds a rule to the list of rules, and optionally saves it to disk.
|
|
|
|
func (l *Loader) Add(rule *Rule, saveToDisk bool) error {
|
|
|
|
l.addUserRule(rule)
|
|
|
|
if saveToDisk {
|
improved rules reloading, cli parameters
- When reloading rules from a path:
stop existing (domains,ips,regexp) lists monitors, stop rules
watcher and start watching the new dir for changes, delete existing
rules from memory, etc.
- Previously, cli parameters (queue number, log file, etc) were taking
into account before loading the configuration.
Now the configuration file is loaded first (default-config.json), and
if any of the cli parameter has been specified, it'll overwrite the
loaded configuration from file.
This means for example that if you use "-process-monitor-method proc",
and "ebpf" is configured in default-config.json, firstly "ebpf" will
be configured, and later "proc".
(-queue-num option for now requires to match config option
cfg.FwOptions.QueueNumber)
2024-05-22 00:47:54 +02:00
|
|
|
fileName := filepath.Join(l.Path, fmt.Sprintf("%s.json", rule.Name))
|
rules: improved operator list parsing and conversion
Previously when creating a new rule we followed these steps:
- Create a new protobuf Rule object from the ruleseditor or the
pop-ups.
- If the rule contained more than one operator, we converted the
list of operators to a JSON string.
- This JSON string was sent back to the daemon, and saved to the
DB.
- The list of operators were never expanded on the GUI, i.e., they
were not saved as a list of protobuf Operator objects.
- Once received in the daemon, the JSON string was parsed and
converted to a protobuf Operator list of objects.
Both, the JSON string and the list of protobuf Operator objects were
saved to disk, but the JSON string was ignored when loading the
rules.
Saving the list of operators as a JSON string was a problem if you
wanted to create or modify rules without the GUI.
Now when creating or modifying rules from the GUI, the list of operators
is no longer converted to JSON string. Instead the list is sent to the
daemon as a list of protobuf Operators, and saved as JSON objects.
Notes:
- The JSON string is no longer saved to disk as part of the rules.
- The list of operators is still saved as JSON string to the DB.
- About not enabled rules:
Previously, not enabled rules only had the list of operators as JSON
string, with the field list:[] empty.
Now the list of operators is saved as JSON objects, but if the rule
is not enabled, it won't be parsed/loaded.
Closes #1047
2023-10-09 14:55:15 +02:00
|
|
|
return l.Save(rule, fileName)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Replace adds a rule to the list of rules, and optionally saves it to disk.
|
|
|
|
func (l *Loader) Replace(rule *Rule, saveToDisk bool) error {
|
|
|
|
if err := l.replaceUserRule(rule); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if saveToDisk {
|
|
|
|
l.Lock()
|
|
|
|
defer l.Unlock()
|
|
|
|
|
improved rules reloading, cli parameters
- When reloading rules from a path:
stop existing (domains,ips,regexp) lists monitors, stop rules
watcher and start watching the new dir for changes, delete existing
rules from memory, etc.
- Previously, cli parameters (queue number, log file, etc) were taking
into account before loading the configuration.
Now the configuration file is loaded first (default-config.json), and
if any of the cli parameter has been specified, it'll overwrite the
loaded configuration from file.
This means for example that if you use "-process-monitor-method proc",
and "ebpf" is configured in default-config.json, firstly "ebpf" will
be configured, and later "proc".
(-queue-num option for now requires to match config option
cfg.FwOptions.QueueNumber)
2024-05-22 00:47:54 +02:00
|
|
|
fileName := filepath.Join(l.Path, fmt.Sprintf("%s.json", rule.Name))
|
rules: improved operator list parsing and conversion
Previously when creating a new rule we followed these steps:
- Create a new protobuf Rule object from the ruleseditor or the
pop-ups.
- If the rule contained more than one operator, we converted the
list of operators to a JSON string.
- This JSON string was sent back to the daemon, and saved to the
DB.
- The list of operators were never expanded on the GUI, i.e., they
were not saved as a list of protobuf Operator objects.
- Once received in the daemon, the JSON string was parsed and
converted to a protobuf Operator list of objects.
Both, the JSON string and the list of protobuf Operator objects were
saved to disk, but the JSON string was ignored when loading the
rules.
Saving the list of operators as a JSON string was a problem if you
wanted to create or modify rules without the GUI.
Now when creating or modifying rules from the GUI, the list of operators
is no longer converted to JSON string. Instead the list is sent to the
daemon as a list of protobuf Operators, and saved as JSON objects.
Notes:
- The JSON string is no longer saved to disk as part of the rules.
- The list of operators is still saved as JSON string to the DB.
- About not enabled rules:
Previously, not enabled rules only had the list of operators as JSON
string, with the field list:[] empty.
Now the list of operators is saved as JSON objects, but if the rule
is not enabled, it won't be parsed/loaded.
Closes #1047
2023-10-09 14:55:15 +02:00
|
|
|
return l.Save(rule, fileName)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Save a rule to disk.
|
|
|
|
func (l *Loader) Save(rule *Rule, path string) error {
|
|
|
|
rule.Updated = time.Now()
|
|
|
|
raw, err := json.MarshalIndent(rule, "", " ")
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Error while saving rule %s to %s: %s", rule, path, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = ioutil.WriteFile(path, raw, 0600); err != nil {
|
|
|
|
return fmt.Errorf("Error while saving rule %s to %s: %s", rule, path, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete deletes a rule from the list by name.
|
|
|
|
// If the duration is Always (i.e: saved on disk), it'll attempt to delete
|
|
|
|
// it from disk.
|
|
|
|
func (l *Loader) Delete(ruleName string) error {
|
|
|
|
l.Lock()
|
|
|
|
defer l.Unlock()
|
|
|
|
|
|
|
|
rule := l.rules[ruleName]
|
|
|
|
if rule == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
l.cleanListsRule(rule)
|
|
|
|
|
|
|
|
delete(l.rules, ruleName)
|
|
|
|
l.sortRules()
|
|
|
|
|
|
|
|
if rule.Duration != Always {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Info("Delete() rule: %s", rule)
|
|
|
|
return l.deleteRuleFromDisk(ruleName)
|
|
|
|
}
|
|
|
|
|
2021-02-27 01:39:04 +01:00
|
|
|
func (l *Loader) loadRule(fileName string) error {
|
|
|
|
raw, err := ioutil.ReadFile(fileName)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Error while reading %s: %s", fileName, err)
|
|
|
|
}
|
2021-03-01 12:41:35 +01:00
|
|
|
l.Lock()
|
|
|
|
defer l.Unlock()
|
2021-02-27 01:39:04 +01:00
|
|
|
|
|
|
|
var r Rule
|
|
|
|
err = json.Unmarshal(raw, &r)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Error parsing rule from %s: %s", fileName, err)
|
|
|
|
}
|
2021-03-01 12:41:35 +01:00
|
|
|
raw = nil
|
|
|
|
|
|
|
|
if oldRule, found := l.rules[r.Name]; found {
|
|
|
|
l.cleanListsRule(oldRule)
|
|
|
|
}
|
2021-02-27 01:39:04 +01:00
|
|
|
|
rules: improved operator list parsing and conversion
Previously when creating a new rule we followed these steps:
- Create a new protobuf Rule object from the ruleseditor or the
pop-ups.
- If the rule contained more than one operator, we converted the
list of operators to a JSON string.
- This JSON string was sent back to the daemon, and saved to the
DB.
- The list of operators were never expanded on the GUI, i.e., they
were not saved as a list of protobuf Operator objects.
- Once received in the daemon, the JSON string was parsed and
converted to a protobuf Operator list of objects.
Both, the JSON string and the list of protobuf Operator objects were
saved to disk, but the JSON string was ignored when loading the
rules.
Saving the list of operators as a JSON string was a problem if you
wanted to create or modify rules without the GUI.
Now when creating or modifying rules from the GUI, the list of operators
is no longer converted to JSON string. Instead the list is sent to the
daemon as a list of protobuf Operators, and saved as JSON objects.
Notes:
- The JSON string is no longer saved to disk as part of the rules.
- The list of operators is still saved as JSON string to the DB.
- About not enabled rules:
Previously, not enabled rules only had the list of operators as JSON
string, with the field list:[] empty.
Now the list of operators is saved as JSON objects, but if the rule
is not enabled, it won't be parsed/loaded.
Closes #1047
2023-10-09 14:55:15 +02:00
|
|
|
if !r.Enabled {
|
|
|
|
// XXX: we only parse and load the Data field if the rule is disabled and the Data field is not empty
|
|
|
|
// the rule will remain disabled.
|
|
|
|
if err = l.unmarshalOperatorList(&r.Operator); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
} else {
|
2021-03-01 12:41:35 +01:00
|
|
|
if err := r.Operator.Compile(); err != nil {
|
|
|
|
log.Warning("Operator.Compile() error: %s: %s", err, r.Operator.Data)
|
2021-11-12 12:08:31 +01:00
|
|
|
return fmt.Errorf("(1) Error compiling rule: %s", err)
|
2021-03-01 12:41:35 +01:00
|
|
|
}
|
2021-02-27 01:39:04 +01:00
|
|
|
if r.Operator.Type == List {
|
|
|
|
for i := 0; i < len(r.Operator.List); i++ {
|
|
|
|
if err := r.Operator.List[i].Compile(); err != nil {
|
|
|
|
log.Warning("Operator.Compile() error: %s: ", err)
|
2021-11-12 12:08:31 +01:00
|
|
|
return fmt.Errorf("(1) Error compiling list rule: %s", err)
|
2021-02-27 01:39:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-03-01 12:41:35 +01:00
|
|
|
if oldRule, found := l.rules[r.Name]; found {
|
|
|
|
l.deleteOldRuleFromDisk(oldRule, &r)
|
|
|
|
}
|
2021-02-27 01:39:04 +01:00
|
|
|
|
|
|
|
log.Debug("Loaded rule from %s: %s", fileName, r.String())
|
|
|
|
l.rules[r.Name] = &r
|
2021-03-01 12:41:35 +01:00
|
|
|
l.sortRules()
|
|
|
|
|
|
|
|
if l.isTemporary(&r) {
|
2021-06-03 17:35:48 +02:00
|
|
|
err = l.scheduleTemporaryRule(r)
|
2021-03-01 12:41:35 +01:00
|
|
|
}
|
2021-02-27 01:39:04 +01:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-03-01 12:41:35 +01:00
|
|
|
// deleteRule deletes a rule from memory if it has been deleted from disk.
|
|
|
|
// This is only called if fsnotify's Remove event is fired, thus it doesn't
|
|
|
|
// have to delete temporary rules (!Always).
|
2021-02-27 01:39:04 +01:00
|
|
|
func (l *Loader) deleteRule(filePath string) {
|
|
|
|
fileName := filepath.Base(filePath)
|
2021-03-01 12:41:35 +01:00
|
|
|
ruleName := fileName[:len(fileName)-5]
|
2021-06-05 16:33:50 +02:00
|
|
|
|
|
|
|
l.RLock()
|
|
|
|
rule, found := l.rules[ruleName]
|
|
|
|
delRule := found && rule.Duration == Always
|
|
|
|
l.RUnlock()
|
|
|
|
if delRule {
|
2021-03-01 12:41:35 +01:00
|
|
|
l.Delete(ruleName)
|
|
|
|
}
|
2021-02-27 01:39:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Loader) deleteRuleFromDisk(ruleName string) error {
|
improved rules reloading, cli parameters
- When reloading rules from a path:
stop existing (domains,ips,regexp) lists monitors, stop rules
watcher and start watching the new dir for changes, delete existing
rules from memory, etc.
- Previously, cli parameters (queue number, log file, etc) were taking
into account before loading the configuration.
Now the configuration file is loaded first (default-config.json), and
if any of the cli parameter has been specified, it'll overwrite the
loaded configuration from file.
This means for example that if you use "-process-monitor-method proc",
and "ebpf" is configured in default-config.json, firstly "ebpf" will
be configured, and later "proc".
(-queue-num option for now requires to match config option
cfg.FwOptions.QueueNumber)
2024-05-22 00:47:54 +02:00
|
|
|
path := fmt.Sprint(l.Path, "/", ruleName, ".json")
|
2021-02-27 01:39:04 +01:00
|
|
|
return os.Remove(path)
|
|
|
|
}
|
|
|
|
|
|
|
|
// deleteOldRuleFromDisk deletes a rule from disk if the Duration changes
|
|
|
|
// from Always (saved on disk), to !Always (temporary).
|
2021-03-01 12:41:35 +01:00
|
|
|
func (l *Loader) deleteOldRuleFromDisk(oldRule, newRule *Rule) {
|
|
|
|
if oldRule.Duration == Always && newRule.Duration != Always {
|
|
|
|
if err := l.deleteRuleFromDisk(oldRule.Name); err != nil {
|
|
|
|
log.Error("Error deleting old rule from disk: %s", oldRule.Name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
improved rules reloading, cli parameters
- When reloading rules from a path:
stop existing (domains,ips,regexp) lists monitors, stop rules
watcher and start watching the new dir for changes, delete existing
rules from memory, etc.
- Previously, cli parameters (queue number, log file, etc) were taking
into account before loading the configuration.
Now the configuration file is loaded first (default-config.json), and
if any of the cli parameter has been specified, it'll overwrite the
loaded configuration from file.
This means for example that if you use "-process-monitor-method proc",
and "ebpf" is configured in default-config.json, firstly "ebpf" will
be configured, and later "proc".
(-queue-num option for now requires to match config option
cfg.FwOptions.QueueNumber)
2024-05-22 00:47:54 +02:00
|
|
|
// cleanListsRule erases the lists loaded of an Operator of type Lists,
|
|
|
|
// and stops the workers monitoring the lists.
|
2021-03-01 12:41:35 +01:00
|
|
|
func (l *Loader) cleanListsRule(oldRule *Rule) {
|
|
|
|
if oldRule.Operator.Type == Lists {
|
|
|
|
oldRule.Operator.StopMonitoringLists()
|
|
|
|
} else if oldRule.Operator.Type == List {
|
|
|
|
for i := 0; i < len(oldRule.Operator.List); i++ {
|
|
|
|
if oldRule.Operator.List[i].Type == Lists {
|
|
|
|
oldRule.Operator.List[i].StopMonitoringLists()
|
|
|
|
break
|
2021-02-27 01:39:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-01 12:41:35 +01:00
|
|
|
func (l *Loader) isTemporary(r *Rule) bool {
|
|
|
|
return r.Duration != Restart && r.Duration != Always && r.Duration != Once
|
2020-05-10 17:33:39 +02:00
|
|
|
}
|
|
|
|
|
2018-04-03 14:51:58 +02:00
|
|
|
func (l *Loader) isUniqueName(name string) bool {
|
|
|
|
_, found := l.rules[name]
|
|
|
|
return !found
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Loader) setUniqueName(rule *Rule) {
|
2020-05-10 17:33:39 +02:00
|
|
|
l.Lock()
|
|
|
|
defer l.Unlock()
|
|
|
|
|
2018-04-03 14:51:58 +02:00
|
|
|
idx := 1
|
2018-04-05 16:27:48 +02:00
|
|
|
base := rule.Name
|
2018-04-03 14:51:58 +02:00
|
|
|
for l.isUniqueName(rule.Name) == false {
|
|
|
|
idx++
|
2018-04-05 16:27:48 +02:00
|
|
|
rule.Name = fmt.Sprintf("%s-%d", base, idx)
|
2018-04-03 14:51:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
rules: improved operator list parsing and conversion
Previously when creating a new rule we followed these steps:
- Create a new protobuf Rule object from the ruleseditor or the
pop-ups.
- If the rule contained more than one operator, we converted the
list of operators to a JSON string.
- This JSON string was sent back to the daemon, and saved to the
DB.
- The list of operators were never expanded on the GUI, i.e., they
were not saved as a list of protobuf Operator objects.
- Once received in the daemon, the JSON string was parsed and
converted to a protobuf Operator list of objects.
Both, the JSON string and the list of protobuf Operator objects were
saved to disk, but the JSON string was ignored when loading the
rules.
Saving the list of operators as a JSON string was a problem if you
wanted to create or modify rules without the GUI.
Now when creating or modifying rules from the GUI, the list of operators
is no longer converted to JSON string. Instead the list is sent to the
daemon as a list of protobuf Operators, and saved as JSON objects.
Notes:
- The JSON string is no longer saved to disk as part of the rules.
- The list of operators is still saved as JSON string to the DB.
- About not enabled rules:
Previously, not enabled rules only had the list of operators as JSON
string, with the field list:[] empty.
Now the list of operators is saved as JSON objects, but if the rule
is not enabled, it won't be parsed/loaded.
Closes #1047
2023-10-09 14:55:15 +02:00
|
|
|
// Deprecated: rule.Operator.Data no longer holds the operator list in json format as string.
|
|
|
|
func (l *Loader) unmarshalOperatorList(op *Operator) error {
|
|
|
|
if op.Type == List && len(op.List) == 0 && op.Data != "" {
|
|
|
|
if err := json.Unmarshal([]byte(op.Data), &op.List); err != nil {
|
|
|
|
return fmt.Errorf("error loading rule of type list: %s", err)
|
|
|
|
}
|
|
|
|
op.Data = ""
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-10-21 08:13:41 +02:00
|
|
|
func (l *Loader) sortRules() {
|
|
|
|
l.rulesKeys = make([]string, 0, len(l.rules))
|
|
|
|
for k := range l.rules {
|
|
|
|
l.rulesKeys = append(l.rulesKeys, k)
|
|
|
|
}
|
|
|
|
sort.Strings(l.rulesKeys)
|
|
|
|
}
|
|
|
|
|
2018-04-03 14:51:58 +02:00
|
|
|
func (l *Loader) addUserRule(rule *Rule) {
|
2019-11-09 01:35:13 +01:00
|
|
|
if rule.Duration == Once {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-04-03 14:51:58 +02:00
|
|
|
l.setUniqueName(rule)
|
2020-05-10 17:33:39 +02:00
|
|
|
l.replaceUserRule(rule)
|
|
|
|
}
|
|
|
|
|
2021-01-04 12:48:05 +01:00
|
|
|
func (l *Loader) replaceUserRule(rule *Rule) (err error) {
|
2021-03-04 12:10:53 +01:00
|
|
|
l.Lock()
|
|
|
|
oldRule, found := l.rules[rule.Name]
|
|
|
|
l.Unlock()
|
|
|
|
|
|
|
|
if found {
|
2021-03-01 12:41:35 +01:00
|
|
|
// If the rule has changed from Always (saved on disk) to !Always (temporary),
|
|
|
|
// we need to delete the rule from disk and keep it in memory.
|
|
|
|
l.deleteOldRuleFromDisk(oldRule, rule)
|
2021-01-04 12:48:05 +01:00
|
|
|
|
2021-03-01 12:41:35 +01:00
|
|
|
// delete loaded lists, if this is a rule of type Lists
|
|
|
|
l.cleanListsRule(oldRule)
|
|
|
|
}
|
2021-02-25 13:38:48 +01:00
|
|
|
|
rules: improved operator list parsing and conversion
Previously when creating a new rule we followed these steps:
- Create a new protobuf Rule object from the ruleseditor or the
pop-ups.
- If the rule contained more than one operator, we converted the
list of operators to a JSON string.
- This JSON string was sent back to the daemon, and saved to the
DB.
- The list of operators were never expanded on the GUI, i.e., they
were not saved as a list of protobuf Operator objects.
- Once received in the daemon, the JSON string was parsed and
converted to a protobuf Operator list of objects.
Both, the JSON string and the list of protobuf Operator objects were
saved to disk, but the JSON string was ignored when loading the
rules.
Saving the list of operators as a JSON string was a problem if you
wanted to create or modify rules without the GUI.
Now when creating or modifying rules from the GUI, the list of operators
is no longer converted to JSON string. Instead the list is sent to the
daemon as a list of protobuf Operators, and saved as JSON objects.
Notes:
- The JSON string is no longer saved to disk as part of the rules.
- The list of operators is still saved as JSON string to the DB.
- About not enabled rules:
Previously, not enabled rules only had the list of operators as JSON
string, with the field list:[] empty.
Now the list of operators is saved as JSON objects, but if the rule
is not enabled, it won't be parsed/loaded.
Closes #1047
2023-10-09 14:55:15 +02:00
|
|
|
if err := l.unmarshalOperatorList(&rule.Operator); err != nil {
|
|
|
|
log.Error(err.Error())
|
|
|
|
}
|
|
|
|
|
2021-03-01 12:41:35 +01:00
|
|
|
if rule.Enabled {
|
2021-02-25 20:09:23 +01:00
|
|
|
if err := rule.Operator.Compile(); err != nil {
|
2021-02-27 01:39:04 +01:00
|
|
|
log.Warning("Operator.Compile() error: %s: %s", err, rule.Operator.Data)
|
rules: improved operator list parsing and conversion
Previously when creating a new rule we followed these steps:
- Create a new protobuf Rule object from the ruleseditor or the
pop-ups.
- If the rule contained more than one operator, we converted the
list of operators to a JSON string.
- This JSON string was sent back to the daemon, and saved to the
DB.
- The list of operators were never expanded on the GUI, i.e., they
were not saved as a list of protobuf Operator objects.
- Once received in the daemon, the JSON string was parsed and
converted to a protobuf Operator list of objects.
Both, the JSON string and the list of protobuf Operator objects were
saved to disk, but the JSON string was ignored when loading the
rules.
Saving the list of operators as a JSON string was a problem if you
wanted to create or modify rules without the GUI.
Now when creating or modifying rules from the GUI, the list of operators
is no longer converted to JSON string. Instead the list is sent to the
daemon as a list of protobuf Operators, and saved as JSON objects.
Notes:
- The JSON string is no longer saved to disk as part of the rules.
- The list of operators is still saved as JSON string to the DB.
- About not enabled rules:
Previously, not enabled rules only had the list of operators as JSON
string, with the field list:[] empty.
Now the list of operators is saved as JSON objects, but if the rule
is not enabled, it won't be parsed/loaded.
Closes #1047
2023-10-09 14:55:15 +02:00
|
|
|
return fmt.Errorf("(2) error compiling rule: %s", err)
|
2021-02-25 20:09:23 +01:00
|
|
|
}
|
2021-02-25 13:38:48 +01:00
|
|
|
|
2021-03-01 12:41:35 +01:00
|
|
|
if rule.Operator.Type == List {
|
|
|
|
for i := 0; i < len(rule.Operator.List); i++ {
|
|
|
|
if err := rule.Operator.List[i].Compile(); err != nil {
|
|
|
|
log.Warning("Operator.Compile() error: %s: ", err)
|
rules: improved operator list parsing and conversion
Previously when creating a new rule we followed these steps:
- Create a new protobuf Rule object from the ruleseditor or the
pop-ups.
- If the rule contained more than one operator, we converted the
list of operators to a JSON string.
- This JSON string was sent back to the daemon, and saved to the
DB.
- The list of operators were never expanded on the GUI, i.e., they
were not saved as a list of protobuf Operator objects.
- Once received in the daemon, the JSON string was parsed and
converted to a protobuf Operator list of objects.
Both, the JSON string and the list of protobuf Operator objects were
saved to disk, but the JSON string was ignored when loading the
rules.
Saving the list of operators as a JSON string was a problem if you
wanted to create or modify rules without the GUI.
Now when creating or modifying rules from the GUI, the list of operators
is no longer converted to JSON string. Instead the list is sent to the
daemon as a list of protobuf Operators, and saved as JSON objects.
Notes:
- The JSON string is no longer saved to disk as part of the rules.
- The list of operators is still saved as JSON string to the DB.
- About not enabled rules:
Previously, not enabled rules only had the list of operators as JSON
string, with the field list:[] empty.
Now the list of operators is saved as JSON objects, but if the rule
is not enabled, it won't be parsed/loaded.
Closes #1047
2023-10-09 14:55:15 +02:00
|
|
|
return fmt.Errorf("(2) error compiling list rule: %s", err)
|
2021-03-01 12:41:35 +01:00
|
|
|
}
|
2021-02-25 13:38:48 +01:00
|
|
|
}
|
2021-02-19 01:03:45 +01:00
|
|
|
}
|
2021-01-04 12:48:05 +01:00
|
|
|
}
|
2021-03-01 12:41:35 +01:00
|
|
|
l.Lock()
|
|
|
|
l.rules[rule.Name] = rule
|
|
|
|
l.sortRules()
|
|
|
|
l.Unlock()
|
2019-11-09 01:35:13 +01:00
|
|
|
|
2021-03-01 12:41:35 +01:00
|
|
|
if l.isTemporary(rule) {
|
2021-06-03 17:35:48 +02:00
|
|
|
err = l.scheduleTemporaryRule(*rule)
|
2019-11-09 01:35:13 +01:00
|
|
|
}
|
|
|
|
|
2021-03-01 12:41:35 +01:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-06-03 17:35:48 +02:00
|
|
|
func (l *Loader) scheduleTemporaryRule(rule Rule) error {
|
2021-03-01 12:41:35 +01:00
|
|
|
tTime, err := time.ParseDuration(string(rule.Duration))
|
2019-11-09 01:35:13 +01:00
|
|
|
if err != nil {
|
2021-01-04 12:48:05 +01:00
|
|
|
return err
|
2019-11-09 01:35:13 +01:00
|
|
|
}
|
|
|
|
|
2020-05-10 17:33:39 +02:00
|
|
|
time.AfterFunc(tTime, func() {
|
2019-11-09 01:35:13 +01:00
|
|
|
l.Lock()
|
2021-06-01 23:52:02 +02:00
|
|
|
defer l.Unlock()
|
|
|
|
|
2021-01-04 12:48:05 +01:00
|
|
|
log.Info("Temporary rule expired: %s - %s", rule.Name, rule.Duration)
|
2021-06-01 23:52:02 +02:00
|
|
|
if newRule, found := l.rules[rule.Name]; found {
|
|
|
|
if newRule.Duration != rule.Duration {
|
2021-06-03 17:35:48 +02:00
|
|
|
log.Debug("%s temporary rule expired, but has new Duration, old: %s, new: %s", rule.Name, rule.Duration, newRule.Duration)
|
2021-06-01 23:52:02 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
delete(l.rules, rule.Name)
|
|
|
|
l.sortRules()
|
|
|
|
}
|
2019-11-09 01:35:13 +01:00
|
|
|
})
|
2021-03-01 12:41:35 +01:00
|
|
|
return nil
|
2018-04-03 14:51:58 +02:00
|
|
|
}
|
|
|
|
|
rules: improved operator list parsing and conversion
Previously when creating a new rule we followed these steps:
- Create a new protobuf Rule object from the ruleseditor or the
pop-ups.
- If the rule contained more than one operator, we converted the
list of operators to a JSON string.
- This JSON string was sent back to the daemon, and saved to the
DB.
- The list of operators were never expanded on the GUI, i.e., they
were not saved as a list of protobuf Operator objects.
- Once received in the daemon, the JSON string was parsed and
converted to a protobuf Operator list of objects.
Both, the JSON string and the list of protobuf Operator objects were
saved to disk, but the JSON string was ignored when loading the
rules.
Saving the list of operators as a JSON string was a problem if you
wanted to create or modify rules without the GUI.
Now when creating or modifying rules from the GUI, the list of operators
is no longer converted to JSON string. Instead the list is sent to the
daemon as a list of protobuf Operators, and saved as JSON objects.
Notes:
- The JSON string is no longer saved to disk as part of the rules.
- The list of operators is still saved as JSON string to the DB.
- About not enabled rules:
Previously, not enabled rules only had the list of operators as JSON
string, with the field list:[] empty.
Now the list of operators is saved as JSON objects, but if the rule
is not enabled, it won't be parsed/loaded.
Closes #1047
2023-10-09 14:55:15 +02:00
|
|
|
func (l *Loader) liveReloadWorker() {
|
|
|
|
l.liveReloadRunning = true
|
2020-05-10 17:33:39 +02:00
|
|
|
|
improved rules reloading, cli parameters
- When reloading rules from a path:
stop existing (domains,ips,regexp) lists monitors, stop rules
watcher and start watching the new dir for changes, delete existing
rules from memory, etc.
- Previously, cli parameters (queue number, log file, etc) were taking
into account before loading the configuration.
Now the configuration file is loaded first (default-config.json), and
if any of the cli parameter has been specified, it'll overwrite the
loaded configuration from file.
This means for example that if you use "-process-monitor-method proc",
and "ebpf" is configured in default-config.json, firstly "ebpf" will
be configured, and later "proc".
(-queue-num option for now requires to match config option
cfg.FwOptions.QueueNumber)
2024-05-22 00:47:54 +02:00
|
|
|
log.Debug("Rules watcher started on path %s ...", l.Path)
|
|
|
|
if err := l.watcher.Add(l.Path); err != nil {
|
rules: improved operator list parsing and conversion
Previously when creating a new rule we followed these steps:
- Create a new protobuf Rule object from the ruleseditor or the
pop-ups.
- If the rule contained more than one operator, we converted the
list of operators to a JSON string.
- This JSON string was sent back to the daemon, and saved to the
DB.
- The list of operators were never expanded on the GUI, i.e., they
were not saved as a list of protobuf Operator objects.
- Once received in the daemon, the JSON string was parsed and
converted to a protobuf Operator list of objects.
Both, the JSON string and the list of protobuf Operator objects were
saved to disk, but the JSON string was ignored when loading the
rules.
Saving the list of operators as a JSON string was a problem if you
wanted to create or modify rules without the GUI.
Now when creating or modifying rules from the GUI, the list of operators
is no longer converted to JSON string. Instead the list is sent to the
daemon as a list of protobuf Operators, and saved as JSON objects.
Notes:
- The JSON string is no longer saved to disk as part of the rules.
- The list of operators is still saved as JSON string to the DB.
- About not enabled rules:
Previously, not enabled rules only had the list of operators as JSON
string, with the field list:[] empty.
Now the list of operators is saved as JSON objects, but if the rule
is not enabled, it won't be parsed/loaded.
Closes #1047
2023-10-09 14:55:15 +02:00
|
|
|
log.Error("Could not watch path: %s", err)
|
|
|
|
l.liveReloadRunning = false
|
|
|
|
return
|
2020-10-21 08:13:41 +02:00
|
|
|
}
|
|
|
|
|
rules: improved operator list parsing and conversion
Previously when creating a new rule we followed these steps:
- Create a new protobuf Rule object from the ruleseditor or the
pop-ups.
- If the rule contained more than one operator, we converted the
list of operators to a JSON string.
- This JSON string was sent back to the daemon, and saved to the
DB.
- The list of operators were never expanded on the GUI, i.e., they
were not saved as a list of protobuf Operator objects.
- Once received in the daemon, the JSON string was parsed and
converted to a protobuf Operator list of objects.
Both, the JSON string and the list of protobuf Operator objects were
saved to disk, but the JSON string was ignored when loading the
rules.
Saving the list of operators as a JSON string was a problem if you
wanted to create or modify rules without the GUI.
Now when creating or modifying rules from the GUI, the list of operators
is no longer converted to JSON string. Instead the list is sent to the
daemon as a list of protobuf Operators, and saved as JSON objects.
Notes:
- The JSON string is no longer saved to disk as part of the rules.
- The list of operators is still saved as JSON string to the DB.
- About not enabled rules:
Previously, not enabled rules only had the list of operators as JSON
string, with the field list:[] empty.
Now the list of operators is saved as JSON objects, but if the rule
is not enabled, it won't be parsed/loaded.
Closes #1047
2023-10-09 14:55:15 +02:00
|
|
|
for {
|
|
|
|
select {
|
improved rules reloading, cli parameters
- When reloading rules from a path:
stop existing (domains,ips,regexp) lists monitors, stop rules
watcher and start watching the new dir for changes, delete existing
rules from memory, etc.
- Previously, cli parameters (queue number, log file, etc) were taking
into account before loading the configuration.
Now the configuration file is loaded first (default-config.json), and
if any of the cli parameter has been specified, it'll overwrite the
loaded configuration from file.
This means for example that if you use "-process-monitor-method proc",
and "ebpf" is configured in default-config.json, firstly "ebpf" will
be configured, and later "proc".
(-queue-num option for now requires to match config option
cfg.FwOptions.QueueNumber)
2024-05-22 00:47:54 +02:00
|
|
|
case <-l.stopLiveReload:
|
|
|
|
goto Exit
|
rules: improved operator list parsing and conversion
Previously when creating a new rule we followed these steps:
- Create a new protobuf Rule object from the ruleseditor or the
pop-ups.
- If the rule contained more than one operator, we converted the
list of operators to a JSON string.
- This JSON string was sent back to the daemon, and saved to the
DB.
- The list of operators were never expanded on the GUI, i.e., they
were not saved as a list of protobuf Operator objects.
- Once received in the daemon, the JSON string was parsed and
converted to a protobuf Operator list of objects.
Both, the JSON string and the list of protobuf Operator objects were
saved to disk, but the JSON string was ignored when loading the
rules.
Saving the list of operators as a JSON string was a problem if you
wanted to create or modify rules without the GUI.
Now when creating or modifying rules from the GUI, the list of operators
is no longer converted to JSON string. Instead the list is sent to the
daemon as a list of protobuf Operators, and saved as JSON objects.
Notes:
- The JSON string is no longer saved to disk as part of the rules.
- The list of operators is still saved as JSON string to the DB.
- About not enabled rules:
Previously, not enabled rules only had the list of operators as JSON
string, with the field list:[] empty.
Now the list of operators is saved as JSON objects, but if the rule
is not enabled, it won't be parsed/loaded.
Closes #1047
2023-10-09 14:55:15 +02:00
|
|
|
case event := <-l.watcher.Events:
|
|
|
|
// a new rule json file has been created or updated
|
|
|
|
if event.Op&fsnotify.Write == fsnotify.Write {
|
|
|
|
if strings.HasSuffix(event.Name, ".json") {
|
|
|
|
log.Important("Ruleset changed due to %s, reloading ...", path.Base(event.Name))
|
|
|
|
if err := l.loadRule(event.Name); err != nil {
|
|
|
|
log.Warning("%s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if event.Op&fsnotify.Remove == fsnotify.Remove {
|
|
|
|
if strings.HasSuffix(event.Name, ".json") {
|
|
|
|
log.Important("Rule deleted %s", path.Base(event.Name))
|
|
|
|
// we only need to delete from memory rules of type Always,
|
|
|
|
// because the Remove event is of a file, i.e.: Duration == Always
|
|
|
|
l.deleteRule(event.Name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case err := <-l.watcher.Errors:
|
|
|
|
log.Error("File system watcher error: %s", err)
|
|
|
|
}
|
2020-05-10 17:33:39 +02:00
|
|
|
}
|
improved rules reloading, cli parameters
- When reloading rules from a path:
stop existing (domains,ips,regexp) lists monitors, stop rules
watcher and start watching the new dir for changes, delete existing
rules from memory, etc.
- Previously, cli parameters (queue number, log file, etc) were taking
into account before loading the configuration.
Now the configuration file is loaded first (default-config.json), and
if any of the cli parameter has been specified, it'll overwrite the
loaded configuration from file.
This means for example that if you use "-process-monitor-method proc",
and "ebpf" is configured in default-config.json, firstly "ebpf" will
be configured, and later "proc".
(-queue-num option for now requires to match config option
cfg.FwOptions.QueueNumber)
2024-05-22 00:47:54 +02:00
|
|
|
Exit:
|
|
|
|
log.Debug("[rules] liveReloadWorker() exited")
|
|
|
|
l.liveReloadRunning = false
|
2020-05-10 17:33:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// FindFirstMatch will try match the connection against the existing rule set.
|
2018-04-05 20:16:04 +02:00
|
|
|
func (l *Loader) FindFirstMatch(con *conman.Connection) (match *Rule) {
|
2018-04-02 05:25:32 +02:00
|
|
|
l.RLock()
|
|
|
|
defer l.RUnlock()
|
|
|
|
|
2020-12-15 16:09:28 +01:00
|
|
|
for _, idx := range l.rulesKeys {
|
|
|
|
rule, _ := l.rules[idx]
|
2020-12-18 16:42:34 +01:00
|
|
|
if rule.Enabled == false {
|
|
|
|
continue
|
|
|
|
}
|
2023-09-22 00:36:26 +02:00
|
|
|
if rule.Match(con, l.checkSums) {
|
2020-12-15 16:09:28 +01:00
|
|
|
// We have a match.
|
|
|
|
// Save the rule in order to don't ask the user to take action,
|
|
|
|
// and keep iterating until a Deny or a Priority rule appears.
|
2018-04-05 20:16:04 +02:00
|
|
|
match = rule
|
2021-09-12 10:54:24 +02:00
|
|
|
if rule.Action == Reject || rule.Action == Deny || rule.Precedence == true {
|
2020-12-15 16:09:28 +01:00
|
|
|
return rule
|
2018-04-05 20:16:04 +02:00
|
|
|
}
|
2018-04-02 05:25:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-05 20:16:04 +02:00
|
|
|
return match
|
2018-04-02 05:25:32 +02:00
|
|
|
}
|