mirror of
https://framagit.org/ppom/reaction
synced 2024-05-19 17:56:34 +02:00
Compare commits
3 commits
754d9ac13d
...
f85feb9007
Author | SHA1 | Date | |
---|---|---|---|
f85feb9007 | |||
711ce21559 | |||
d9f8b4e7ec |
111
app/client.go
111
app/client.go
|
@ -8,7 +8,6 @@ import (
|
|||
"net"
|
||||
"os"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"framagit.org/ppom/reaction/logger"
|
||||
|
@ -23,6 +22,8 @@ const (
|
|||
|
||||
type Request struct {
|
||||
Request int
|
||||
Stream string
|
||||
Filter string
|
||||
Pattern Match
|
||||
}
|
||||
|
||||
|
@ -67,7 +68,6 @@ type CompiledPattern struct{
|
|||
Regex string
|
||||
compiledRegex *regexp.Regexp
|
||||
}
|
||||
|
||||
type CPM map[string]CompiledPattern
|
||||
|
||||
func (mps MapPatternStatusFlush) MarshalJSON() ([]byte, error) {
|
||||
|
@ -97,7 +97,7 @@ func usage(err string) {
|
|||
}
|
||||
|
||||
func ClientShow(format, stream, filter string, regex *regexp.Regexp, kvpattern []string) {
|
||||
response := SendAndRetrieve(Request{Show, ""})
|
||||
response := SendAndRetrieve(Request{Show, stream, filter, ""})
|
||||
if response.Err != nil {
|
||||
logger.Fatalln("Received error from daemon:", response.Err)
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ func ClientShow(format, stream, filter string, regex *regexp.Regexp, kvpattern [
|
|||
// Limit to kvpatterns
|
||||
if kvpattern != nil {
|
||||
// Get pattern indices (as stored in DB) from config
|
||||
responseConfig := SendAndRetrieve(Request{Config, ""})
|
||||
responseConfig := SendAndRetrieve(Request{Config, stream, filter, ""})
|
||||
if responseConfig.Err != nil {
|
||||
logger.Fatalln("Received error from daemon:", responseConfig.Err)
|
||||
}
|
||||
|
@ -231,24 +231,101 @@ func ClientShow(format, stream, filter string, regex *regexp.Regexp, kvpattern [
|
|||
os.Exit(0)
|
||||
}
|
||||
|
||||
// TODO : Show values we just flushed - for now we got no details :
|
||||
/*
|
||||
* % ./reaction flush -l ssh.failedlogin login=".*t"
|
||||
* ssh:
|
||||
* failedlogin:
|
||||
* actions:
|
||||
* unban:
|
||||
* - "2024-04-30 15:27:28"
|
||||
* - "2024-04-30 15:27:28"
|
||||
* - "2024-04-30 15:27:28"
|
||||
* - "2024-04-30 15:27:28"
|
||||
*
|
||||
*/
|
||||
func ClientFlush(patterns []string, stream, filter, format string) {
|
||||
response := SendAndRetrieve(Request{Flush, JoinMatch(patterns)})
|
||||
if response.Err != nil {
|
||||
logger.Fatalln("Received error from daemon:", response.Err)
|
||||
responseConfig := SendAndRetrieve(Request{Config, stream, filter, ""})
|
||||
if responseConfig.Err != nil {
|
||||
logger.Fatalln("Received error from daemon:", responseConfig.Err)
|
||||
}
|
||||
|
||||
if _, found := responseConfig.Config.Streams[stream].Filters[filter]; filter != "" && found == false {
|
||||
logger.Println(logger.WARN, "No matching stream.filter items found. This does not mean it doesn't exist, maybe it just didn't receive any match.")
|
||||
os.Exit(1)
|
||||
}
|
||||
var text []byte
|
||||
var err error
|
||||
if format == "json" {
|
||||
text, err = json.MarshalIndent(ClientStatusFlush(response.ClientStatus), "", " ")
|
||||
} else {
|
||||
text, err = yaml.Marshal(ClientStatusFlush(response.ClientStatus))
|
||||
|
||||
processFilter := func(patterns []string, stream, filter, format string) {
|
||||
fpqty := len(responseConfig.Config.Streams[stream].Filters[filter].Pattern)
|
||||
|
||||
if len(patterns) > fpqty {
|
||||
logger.Fatalln("filter have 1 pattern")
|
||||
}
|
||||
|
||||
for _, kv := range patterns {
|
||||
if len(strings.Split(kv, "=")) != 2 && fpqty > 1 {
|
||||
logger.Fatalln("args should be in pattern=value format using more than one pattern in filter")
|
||||
}
|
||||
}
|
||||
|
||||
// Transform arg to k=v
|
||||
if fpqty == 1 && len(strings.Split(patterns[0], "=")) == 1 {
|
||||
patterns[0] = strings.Join([]string{responseConfig.Config.Streams[stream].Filters[filter].Pattern[0].Name, patterns[0]}, "=")
|
||||
}
|
||||
|
||||
// arg pattern map
|
||||
pmap := make(map[string]string)
|
||||
for _, p := range patterns {
|
||||
a := strings.Split(p, "=")
|
||||
pmap[a[0]] = a[1]
|
||||
}
|
||||
|
||||
// Check every arg pattern exist in filter
|
||||
for k, _ := range pmap {
|
||||
found := false
|
||||
for _, fp := range responseConfig.Config.Streams[stream].Filters[filter].Pattern {
|
||||
if strings.EqualFold(k, fp.Name) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
logger.Fatalf("pattern <%s> not found in filter %s.%s\n", k, stream, filter)
|
||||
}
|
||||
}
|
||||
|
||||
// Order arg patterns before JoinMatch
|
||||
var orderedPatterns []string
|
||||
for _, p := range responseConfig.Config.Streams[stream].Filters[filter].Pattern {
|
||||
if v, found := pmap[p.Name]; found {
|
||||
orderedPatterns = append(orderedPatterns, v)
|
||||
} else {
|
||||
orderedPatterns = append(orderedPatterns, "")
|
||||
}
|
||||
}
|
||||
response := SendAndRetrieve(Request{Flush, stream, filter, JoinMatch(orderedPatterns)})
|
||||
if response.Err != nil {
|
||||
logger.Fatalln(logger.ERROR, "Received error from daemon:", response.Err)
|
||||
}
|
||||
|
||||
var text []byte
|
||||
var err error
|
||||
if format == "json" {
|
||||
text, err = json.MarshalIndent(ClientStatusFlush(response.ClientStatus), "", " ")
|
||||
} else {
|
||||
text, err = yaml.Marshal(ClientStatusFlush(response.ClientStatus))
|
||||
}
|
||||
if err != nil {
|
||||
logger.Fatalln("Failed to convert daemon binary response to text format:", err)
|
||||
}
|
||||
fmt.Println(string(text))
|
||||
}
|
||||
if err != nil {
|
||||
logger.Fatalln("Failed to convert daemon binary response to text format:", err)
|
||||
|
||||
for streamName := range responseConfig.Config.Streams {
|
||||
for filterName := range responseConfig.Config.Streams[streamName].Filters {
|
||||
processFilter(patterns, streamName, filterName, format)
|
||||
}
|
||||
}
|
||||
fmt.Println(string(text))
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func TestRegex(confFilename, regex, line string) {
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
@ -200,15 +201,23 @@ func ActionsManager(concurrency int) {
|
|||
execAction(action, pattern)
|
||||
case fo := <-flushToActionsC:
|
||||
ret := make(ActionsMap)
|
||||
match := 0
|
||||
actionsLock.Lock()
|
||||
for pa := range actions {
|
||||
if pa.p == fo.p {
|
||||
ppa, pfo := pa.p.Split(), fo.p.Split()
|
||||
for i, p := range ppa {
|
||||
if m, err := regexp.MatchString(pfo[i], p); err == nil && m == true {
|
||||
match++
|
||||
}
|
||||
}
|
||||
if match == len(ppa) {
|
||||
for range actions[pa] {
|
||||
execAction(pa.a, pa.p)
|
||||
}
|
||||
ret[pa] = actions[pa]
|
||||
delete(actions, pa)
|
||||
}
|
||||
match = 0
|
||||
}
|
||||
actionsLock.Unlock()
|
||||
fo.ret <- ret
|
||||
|
@ -263,14 +272,22 @@ func MatchesManager() {
|
|||
|
||||
func matchesManagerHandleFlush(fo FlushMatchOrder) {
|
||||
ret := make(MatchesMap)
|
||||
match := 0
|
||||
matchesLock.Lock()
|
||||
for pf := range matches {
|
||||
if fo.p == pf.p {
|
||||
ppf, pfo := pf.p.Split(), fo.p.Split()
|
||||
for i, p := range ppf {
|
||||
if m, err := regexp.MatchString(pfo[i], p); err == nil && m == true {
|
||||
match++
|
||||
}
|
||||
}
|
||||
if match == len(ppf) {
|
||||
if fo.ret != nil {
|
||||
ret[pf] = matches[pf]
|
||||
}
|
||||
delete(matches, pf)
|
||||
}
|
||||
match = 0
|
||||
}
|
||||
matchesLock.Unlock()
|
||||
if fo.ret != nil {
|
||||
|
|
|
@ -100,9 +100,11 @@ func SocketManager(conf *Conf) {
|
|||
case Show:
|
||||
response.ClientStatus = genClientStatus(actions, matches, &actionsLock, &matchesLock)
|
||||
case Flush:
|
||||
le := LogEntry{time.Now(), 0, request.Pattern, "", "", 0, false}
|
||||
le := LogEntry{time.Now(), 0, request.Pattern, request.Stream, request.Filter, 0, false}
|
||||
|
||||
matchesC := FlushMatchOrder{request.Pattern, make(chan MatchesMap)}
|
||||
actionsC := FlushActionOrder{request.Pattern, make(chan ActionsMap)}
|
||||
|
||||
flushToMatchesC <- matchesC
|
||||
flushToActionsC <- actionsC
|
||||
flushToDatabaseC <- le
|
||||
|
|
Loading…
Reference in a new issue