Skip to content

Commit

Permalink
chore(merge): merge master into dev
Browse files Browse the repository at this point in the history
Signed-off-by: Frederico Araujo <[email protected]>
  • Loading branch information
araujof committed Aug 9, 2022
2 parents 171f7d6 + fe52807 commit 27b4644
Show file tree
Hide file tree
Showing 10 changed files with 305 additions and 30 deletions.
21 changes: 19 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
## [Unreleased]

## [0.5.0] - 2022-07-31
## [0.5.0] - 2022-08-21

### Added

Expand All @@ -26,6 +26,22 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).

- Fix bug in exists predicate

## [0.4.4] - 2022-08-01

### Added

- Add rate limiting filter with time decaying

### Changed

- Bump UBI to 8.6-855
- Update reference to sf-apis

### Fixed

- Fix exists predicate
- Fix handling of integers and booleans in MatStr function

## [0.4.3] - 2022-06-21

### Changed
Expand Down Expand Up @@ -149,7 +165,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
- First release of SysFlow Processor.

[Unreleased]: https://github.com/sysflow-telemetry/sf-processor/compare/0.5.0-rc1...HEAD
[0.5.0]: https://github.com/sysflow-telemetry/sf-processor/compare/0.4.3...0.5.0-rc1
[0.5.0]: https://github.com/sysflow-telemetry/sf-processor/compare/0.4.4...0.5.0-rc1
[0.4.4]: https://github.com/sysflow-telemetry/sf-processor/compare/0.4.3...0.4.4
[0.4.3]: https://github.com/sysflow-telemetry/sf-processor/compare/0.4.2...0.4.3
[0.4.2]: https://github.com/sysflow-telemetry/sf-processor/compare/0.4.1...0.4.2
[0.4.1]: https://github.com/sysflow-telemetry/sf-processor/compare/0.4.0...0.4.1
Expand Down
28 changes: 26 additions & 2 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
```

Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Expand Down Expand Up @@ -175,4 +175,28 @@
of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS
```

APPENDIX: How to apply the Apache License to your work.

To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2019 The Falco Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
82 changes: 82 additions & 0 deletions core/flattener/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//
// Copyright (C) 2022 IBM Corporation.
//
// Authors:
// Frederico Araujo <[email protected]>
// Teryl Taylor <[email protected]>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package flattener flattens input telemetry in a flattened representation.
package flattener

import (
"strconv"
"time"
)

// Configuration keys.
const (
FilterOnOffKey string = "filter.enabled"
FilterMaxAgeKey string = "filter.maxage"
)

// Config defines a configuration object for the engine.
type Config struct {
FilterOnOff OnOff
FilterMaxAge time.Duration
}

// CreateConfig creates a new config object from config dictionary.
func CreateConfig(conf map[string]interface{}) (Config, error) {
var c Config = Config{FilterOnOff: Off, FilterMaxAge: 24 * time.Hour} // default values
var err error
if v, ok := conf[FilterOnOffKey].(string); ok {
c.FilterOnOff = parseOnOffType(v)
}
if v, ok := conf[FilterMaxAgeKey].(string); ok {
var duration int
duration, err = strconv.Atoi(v)
if err == nil {
c.FilterMaxAge = time.Duration(duration) * time.Second
}
}
return c, err
}

// OnOff defines an On-Off state type.
type OnOff int32

// OnOff types.
const (
Off OnOff = iota
On
)

func (s OnOff) String() string {
return [...]string{"off", "on"}[s]
}

func (s OnOff) Enabled() bool {
return s == On
}

func parseOnOffType(s string) OnOff {
if Off.String() == s {
return Off
}
if On.String() == s {
return On
}
return Off
}
126 changes: 126 additions & 0 deletions core/flattener/filter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
//
// Copyright (C) 2022 IBM Corporation.
//
// Authors:
// Frederico Araujo <[email protected]>
// Teryl Taylor <[email protected]>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package flattener flattens input telemetry in a flattened representation.
package flattener

import (
"container/list"
"encoding/binary"
"time"

"github.com/cespare/xxhash/v2"
"github.com/sysflow-telemetry/sf-apis/go/sfgo"
)

var byteInt64 []byte = make([]byte, 8)

// Filter is a time decaying filter with a TTL per entry.
type Filter struct {
m map[uint64]int64
q *list.List
ttl time.Duration
}

// Entry encodes a hash value with the time it was first added to the filter.
type Entry struct {
h uint64
firstSeen time.Time
}

// NewFilter creates a new time decaying filter that evicts entries that have been seen longer than t duration.
func NewFilter(t time.Duration) *Filter {
return &Filter{m: make(map[uint64]int64), q: list.New(), ttl: t}
}

// Test tests if hash h has been seen since maximum ttl.
func (f *Filter) Test(h uint64) bool {
f.evictAgedEntries()
_, ok := f.m[h]
return ok
}

// TestAndAdd tests if hash h has been seen since maximum ttl and adds or increments the element in the filter cache.
func (f *Filter) TestAndAdd(h uint64) bool {
f.evictAgedEntries()
_, ok := f.m[h]
f.Add(h)
return ok
}

// Contains returns how many times hash h has been seen during its ttl time.
func (f *Filter) Count(h uint64) int64 {
f.evictAgedEntries()
if count, ok := f.m[h]; ok {
return count
}
return 0
}

// Add adds hash h to the filter.
func (f *Filter) Add(h uint64) {
if v, ok := f.m[h]; !ok {
f.m[h] = 1
f.q.PushBack(Entry{h: h, firstSeen: time.Now()})
} else {
f.m[h] = v + 1
}
}

func (f *Filter) evictAgedEntries() {
for f.q.Len() > 0 {
e := f.q.Front()
entry := e.Value.(Entry)
if time.Since(entry.firstSeen) < f.ttl {
break
}
f.q.Remove(e)
delete(f.m, entry.h)
}
}

// semanticHash computes a hash value over record attributes denoting the semantics of the record (used in the time decay filter).
func semanticHash(fr *sfgo.FlatRecord) uint64 {
h := xxhash.New()
h.Write([]byte(fr.Strs[sfgo.SYSFLOW_SRC][sfgo.PROC_EXE_STR]))
h.Write([]byte(fr.Strs[sfgo.SYSFLOW_SRC][sfgo.PROC_EXEARGS_STR]))
binary.LittleEndian.PutUint64(byteInt64, uint64(fr.Ints[sfgo.SYSFLOW_SRC][sfgo.PROC_UID_INT]))
h.Write(byteInt64)
binary.LittleEndian.PutUint64(byteInt64, uint64(fr.Ints[sfgo.SYSFLOW_SRC][sfgo.PROC_GID_INT]))
h.Write(byteInt64)
binary.LittleEndian.PutUint64(byteInt64, uint64(fr.Ints[sfgo.SYSFLOW_SRC][sfgo.OPFLAGS_INT]))
h.Write(byteInt64)
binary.LittleEndian.PutUint64(byteInt64, uint64(fr.Ints[sfgo.SYSFLOW_SRC][sfgo.PROC_TTY_INT]))
h.Write(byteInt64)
sfType := fr.Ints[sfgo.SYSFLOW_IDX][sfgo.SF_REC_TYPE]
if sfType == sfgo.NET_FLOW {
binary.LittleEndian.PutUint64(byteInt64, uint64(fr.Ints[sfgo.SYSFLOW_SRC][sfgo.FL_NETW_SIP_INT]))
h.Write(byteInt64)
binary.LittleEndian.PutUint64(byteInt64, uint64(fr.Ints[sfgo.SYSFLOW_SRC][sfgo.FL_NETW_DIP_INT]))
h.Write(byteInt64)
binary.LittleEndian.PutUint64(byteInt64, uint64(fr.Ints[sfgo.SYSFLOW_SRC][sfgo.FL_NETW_DPORT_INT]))
h.Write(byteInt64)
binary.LittleEndian.PutUint64(byteInt64, uint64(fr.Ints[sfgo.SYSFLOW_SRC][sfgo.FL_NETW_PROTO_INT]))
h.Write(byteInt64)
}
if sfType == sfgo.FILE_FLOW || sfType == sfgo.FILE_EVT {
h.Write([]byte(fr.Strs[sfgo.SYSFLOW_SRC][sfgo.FILE_PATH_STR]))
}
return h.Sum64()
}
35 changes: 22 additions & 13 deletions core/flattener/flattener.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ func NewFlattenerChan(size int) interface{} {

// Flattener defines the main class for the flatterner plugin.
type Flattener struct {
outCh []chan *sfgo.FlatRecord
config Config
filter *Filter
outCh []chan *sfgo.FlatRecord
}

// NewFlattener creates a new Flattener instance.
Expand All @@ -68,6 +70,11 @@ func (s *Flattener) RegisterHandler(hc plugins.SFHandlerCache) {

// Init initializes the handler with a configuration map.
func (s *Flattener) Init(conf map[string]interface{}) error {
s.config, _ = CreateConfig(conf) // no err check, assuming defaults
if s.config.FilterOnOff.Enabled() {
s.filter = NewFilter(s.config.FilterMaxAge)
logger.Info.Printf("Initialized rate limiter with %s time decay", s.config.FilterMaxAge)
}
return nil
}

Expand All @@ -83,6 +90,16 @@ func (s *Flattener) SetOutChan(chObj []interface{}) {
}
}

// out sends a record to every output channel in the plugin.
func (s *Flattener) out(fr *sfgo.FlatRecord) {
if s.config.FilterOnOff.Enabled() && s.filter != nil && s.filter.TestAndAdd(semanticHash(fr)) {
return
}
for _, c := range s.outCh {
c <- fr
}
}

// Cleanup tears down resources.
func (s *Flattener) Cleanup() {
logger.Trace.Println("Calling Cleanup on Flattener channel")
Expand Down Expand Up @@ -154,9 +171,7 @@ func (s *Flattener) HandleNetFlow(sf *plugins.CtxSysFlow, nf *sfgo.NetworkFlow)
fr.Ints[sfgo.SYSFLOW_IDX][sfgo.FL_NETW_NUMWSENDBYTES_INT] = nf.NumWSendBytes
fr.Ptree = sf.PTree
fr.GraphletID = sf.GraphletID
for _, ch := range s.outCh {
ch <- fr
}
s.out(fr)
return nil
}

Expand All @@ -177,9 +192,7 @@ func (s *Flattener) HandleFileFlow(sf *plugins.CtxSysFlow, ff *sfgo.FileFlow) er
fr.Ints[sfgo.SYSFLOW_IDX][sfgo.FL_FILE_NUMWSENDBYTES_INT] = ff.NumWSendBytes
fr.Ptree = sf.PTree
fr.GraphletID = sf.GraphletID
for _, ch := range s.outCh {
ch <- fr
}
s.out(fr)
return nil
}

Expand Down Expand Up @@ -213,9 +226,7 @@ func (s *Flattener) HandleFileEvt(sf *plugins.CtxSysFlow, fe *sfgo.FileEvent) er
fr.Ints[sfgo.SYSFLOW_IDX][sfgo.EV_FILE_RET_INT] = int64(fe.Ret)
fr.Ptree = sf.PTree
fr.GraphletID = sf.GraphletID
for _, ch := range s.outCh {
ch <- fr
}
s.out(fr)
return nil
}

Expand All @@ -240,9 +251,7 @@ func (s *Flattener) HandleProcEvt(sf *plugins.CtxSysFlow, pe *sfgo.ProcessEvent)
fr.Ints[sfgo.SYSFLOW_IDX][sfgo.EV_PROC_RET_INT] = int64(pe.Ret)
fr.Ptree = sf.PTree
fr.GraphletID = sf.GraphletID
for _, ch := range s.outCh {
ch <- fr
}
s.out(fr)
return nil
}

Expand Down
3 changes: 0 additions & 3 deletions core/policyengine/engine/fieldmapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,6 @@ func (m FieldMapper) MapStr(attr string) StrFieldMap {
if v, ok := o.(string); ok {
if isPathExp && v != "" && jsonpath != "" {
return gjson.Get(v, jsonpath).String()
//res := gjson.Get(v, jsonpath).String()
//logger.Trace.Printf("%s[%s] = %s", baseattr, jsonpath, res)
//return res
}
return trimBoundingQuotes(v)
} else if v, ok := o.(int64); ok {
Expand Down
Loading

0 comments on commit 27b4644

Please sign in to comment.