8000 feat: Add flag for prepared events by simar7 · Pull Request #984 · aquasecurity/tracee · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat: Add flag for prepared events #984

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Sep 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 29 additions & 7 deletions tracee-rules/benchmark/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,37 @@ func BenchmarkOnEventWithCodeInjectionSignature(b *testing.B) {

func BenchmarkEngineWithCodeInjectionSignature(b *testing.B) {
benches := []struct {
name string
sigFunc func() (types.Signature, error)
name string
sigFunc func() (types.Signature, error)
preparedEvents bool
}{
{
name: "rego",
sigFunc: rego.NewCodeInjectionSignature,
},
{
name: "rego + prepared events",
sigFunc: rego.NewCodeInjectionSignature,
preparedEvents: true,
},
{
name: "golang",
sigFunc: golang.NewCodeInjectionSignature,
},
{
name: "golang + prepared events",
sigFunc: golang.NewCodeInjectionSignature,
preparedEvents: true,
},
{
name: "wasm",
sigFunc: wasm.NewCodeInjectionSignature,
},
{
name: "wasm + prepared events",
sigFunc: wasm.NewCodeInjectionSignature,
preparedEvents: true,
},
}

for _, bc := range benches {
Expand All @@ -82,7 +98,7 @@ func BenchmarkEngineWithCodeInjectionSignature(b *testing.B) {
s, err := bc.sigFunc()
require.NoError(b, err, bc.name)

e, err := engine.NewEngine([]types.Signature{s}, inputs, output, os.Stderr)
e, err := engine.NewEngine([]types.Signature{s}, inputs, output, os.Stderr, bc.preparedEvents)
require.NoError(b, err, "constructing engine")
b.StartTimer()

Expand All @@ -95,13 +111,19 @@ func BenchmarkEngineWithCodeInjectionSignature(b *testing.B) {

func BenchmarkEngineWithMultipleSignatures(b *testing.B) {
benches := []struct {
name string
sigFuncs []func() (types.Signature, error)
name string
sigFuncs []func() (types.Signature, error)
preparedEvents bool
}{
{
name: "rego and golang",
sigFuncs: []func() (types.Signature, error){rego.NewCodeInjectionSignature, golang.NewCodeInjectionSignature},
},
{
name: "rego and golang, with prepared events",
sigFuncs: []func() (types.Signature, error){rego.NewCodeInjectionSignature, golang.NewCodeInjectionSignature},
preparedEvents: true,
},
{
name: "wasm and golang",
sigFuncs: []func() (types.Signature, error){wasm.NewCodeInjectionSignature, golang.NewCodeInjectionSignature},
Expand Down Expand Up @@ -131,7 +153,7 @@ func BenchmarkEngineWithMultipleSignatures(b *testing.B) {
inputs := ProduceEventsInMemory(inputEventsCount)
output := make(chan types.Finding, inputEventsCount*len(sigs))

e, err := engine.NewEngine(sigs, inputs, output, os.Stderr)
e, err := engine.NewEngine(sigs, inputs, output, os.Stderr, bc.preparedEvents)
require.NoError(b, err, "constructing engine")
b.StartTimer()

Expand Down Expand Up @@ -191,7 +213,7 @@ func BenchmarkEngineWithNSignatures(b *testing.B) {
b.StopTimer()
inputs := ProduceEventsInMemory(inputEventsCount)
output := make(chan types.Finding, inputEventsCount*len(sigs))
e, err := engine.NewEngine(sigs, inputs, output, os.Stderr)
e, err := engine.NewEngine(sigs, inputs, output, os.Stderr, false)
require.NoError(b, err, "constructing engine")
b.StartTimer()

Expand Down
1 change: 1 addition & 0 deletions tracee-rules/benchmark/signature/wasm/signatures.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/aquasecurity/tracee/tracee-rules/types"
"github.com/open-policy-agent/opa/ast"
_ "github.com/open-policy-agent/opa/features/wasm"
"github.com/open-policy-agent/opa/rego"
)

Expand Down
34 changes: 19 additions & 15 deletions tracee-rules/engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type Engine struct {
inputs EventSources
output chan types.Find 10000 ing
waitGroup sync.WaitGroup
parsedEvents bool
}

//EventSources is a bundle of input sources used to configure the Engine
Expand All @@ -37,7 +38,7 @@ type EventSources struct {

// NewEngine creates a new rules-engine with the given arguments
// inputs and outputs are given as channels created by the consumer
func NewEngine(sigs []types.Signature, sources EventSources, output chan types.Finding, logWriter io.Writer) (*Engine, error) {
func NewEngine(sigs []types.Signature, sources EventSources, output chan types.Finding, logWriter io.Writer, parsedEvents bool) (*Engine, error) {
if sources.Tracee == nil || output == nil || logWriter == nil {
return nil, fmt.Errorf("nil input received")
}
Expand All @@ -46,6 +47,7 @@ func NewEngine(sigs []types.Signature, sources EventSources, output chan types.F
engine.logger = *log.New(logWriter, "", 0)
engine.inputs = sources
engine.output = output
engine.parsedEvents = parsedEvents
engine.signaturesMutex.Lock()
engine.signatures = make(map[types.Signature]chan types.Event)
engine.signaturesIndex = make(map[types.SignatureEventSelector][]types.Signature)
Expand Down Expand Up @@ -182,25 +184,18 @@ func (engine *Engine) consumeSources(done <-chan bool) {
continue
}

pe, err := ToParsedEvent(traceeEvt)
if err != nil {
engine.logger.Printf("error converting tracee event to OPA ast.Value: %v", err)
engine.signaturesMutex.RUnlock()
continue
}

eventOrigin := analyzeEventOrigin(traceeEvt)
for _, s := range engine.signaturesIndex[types.SignatureEventSelector{Source: "tracee", Name: traceeEvt.EventName, Origin: eventOrigin}] {
engine.dispatchEvent(s, pe)
engine.dispatchEvent(s, traceeEvt)
}
for _, s := range engine.signaturesIndex[types.SignatureEventSelector{Source: "tracee", Name: traceeEvt.EventName, Origin: ALL_EVENT_ORIGINS}] {
engine.dispatchEvent(s, pe)
engine.dispatchEvent(s, traceeEvt)
}
for _, s := range engine.signaturesIndex[types.SignatureEventSelector{Source: "tracee", Name: ALL_EVENT_TYPES, Origin: eventOrigin}] {
engine.dispatchEvent(s, pe)
engine.dispatchEvent(s, traceeEvt)
}
for _, s := range engine.signaturesIndex[types.SignatureEventSelector{Source: "tracee", Name: ALL_EVENT_TYPES, Origin: ALL_EVENT_ORIGINS}] {
engine.dispatchEvent(s, pe)
engine.dispatchEvent(s, traceeEvt)
}
engine.signaturesMutex.RUnlock()
}
Expand All @@ -210,12 +205,21 @@ func (engine *Engine) consumeSources(done <-chan bool) {
}
}

func (engine *Engine) dispatchEvent(s types.Signature, pe ParsedEvent) {
func (engine *Engine) dispatchEvent(s types.Signature, event tracee.Event) {
switch {
case strings.Contains(reflect.TypeOf(s).String(), "rego"):
engine.signatures[s] <- pe
if engine.parsedEvents {
pe, err := ToParsedEvent(event)
if err != nil {
engine.logger.Printf("error converting tracee event to OPA ast.Value: %v", err)
return
}
engine.signatures[s] <- pe
} else {
engine.signatures[s] <- event
}
default:
engine.signatures[s] <- pe.Event
engine.signatures[s] <- event
}
}

Expand Down
85 changes: 56 additions & 29 deletions tracee-rules/engine/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,11 @@ func TestConsumeSources(t *testing.T) {
inputSignature regoFakeSignature
expectedNumEvents int
expectedError string
expectedEvent ParsedEvent
expectedEvent interface{}
enableParsedEvent bool
}{
{
name: "happy path - with one matching selector",
name: "happy path - with one matching selector, parsed event enabled",
inputEvent: tracee.Event{
EventName: "test_event",
ProcessID: 2,
Expand All @@ -96,12 +97,42 @@ func TestConsumeSources(t *testing.T) {
},
},
expectedNumEvents: 1,
expectedEvent: ParsedEvent{
Event: tracee.Event{
ProcessID: 2, ParentProcessID: 1, Args: []external.Argument{{ArgMeta: external.ArgMeta{Name: "pathname", Type: ""}, Value: "/proc/self/mem"}},
EventName: "test_event",
expectedEvent: tracee.Event{
ProcessID: 2, ParentProcessID: 1, Args: []external.Argument{{ArgMeta: external.ArgMeta{Name: "pathname", Type: ""}, Value: "/proc/self/mem"}},
EventName: "test_event",
},
enableParsedEvent: true,
},
{
name: "happy path - with one matching selector",
inputEvent: tracee.Event{
EventName: "test_event",
ProcessID: 2,
ParentProcessID: 1,
Args: []tracee.Argument{
{
ArgMeta: tracee.ArgMeta{
Name: "pathname",
},
Value: "/proc/self/mem",
},
},
},
inputSignature: regoFakeSignature{
getSelectedEvents: func() ([]types.SignatureEventSelector, error) {
return []types.SignatureEventSelector{
{
Name: "test_event",
Source: "tracee",
},
}, nil
},
},
expectedNumEvents: 1,
expectedEvent: tracee.Event{
ProcessID: 2, ParentProcessID: 1, Args: []external.Argument{{ArgMeta: external.ArgMeta{Name: "pathname", Type: ""}, Value: "/proc/self/mem"}},
EventName: "test_event",
},
},
{
name: "happy path - with no matching event selector",
Expand Down Expand Up @@ -136,8 +167,8 @@ func TestConsumeSources(t *testing.T) {
},
},
expectedNumEvents: 1,
expectedEvent: ParsedEvent{
Event: tracee.Event{EventName: "execve"},
expectedEvent: tracee.Event{
EventName: "execve",
},
},
{
Expand All @@ -153,9 +184,7 @@ func TestConsumeSources(t *testing.T) {
},
},
expectedNumEvents: 1,
expectedEvent: ParsedEvent{
Event: tracee.Event{EventName: "execve"},
},
expectedEvent: tracee.Event{EventName: "execve"},
},
{
name: "happy path - with one matching selector including event origin from container",
Expand Down Expand Up @@ -185,11 +214,9 @@ func TestConsumeSources(t *testing.T) {
},
},
expectedNumEvents: 1,
expectedEvent: ParsedEvent{
Event: tracee.Event{
ProcessID: 2, ParentProcessID: 1, ContainerID: "container ID", Args: []external.Argument{{ArgMeta: external.ArgMeta{Name: "pathname", Type: ""}, Value: "/proc/self/mem"}},
EventName: "test_event",
},
expectedEvent: tracee.Event{
ProcessID: 2, ParentProcessID: 1, ContainerID: "container ID", Args: []external.Argument{{ArgMeta: external.ArgMeta{Name: "pathname", Type: ""}, Value: "/proc/self/mem"}},
EventName: "test_event",
},
},
{
Expand Down Expand Up @@ -248,11 +275,9 @@ func TestConsumeSources(t *testing.T) {
},
},
expectedNumEvents: 1,
expectedEvent: ParsedEvent{
Event: tracee.Event{
ProcessID: 2, ParentProcessID: 2, Args: []external.Argument{{ArgMeta: external.ArgMeta{Name: "pathname", Type: ""}, Value: "/proc/self/mem"}},
EventName: "test_event",
},
expectedEvent: tracee.Event{
ProcessID: 2, ParentProcessID: 2, Args: []external.Argument{{ArgMeta: external.ArgMeta{Name: "pathname", Type: ""}, Value: "/proc/self/mem"}},
EventName: "test_event",
},
},
{
Expand Down Expand Up @@ -323,11 +348,9 @@ func TestConsumeSources(t *testing.T) {
},
},
expectedNumEvents: 1,
expectedEvent: ParsedEvent{
Event: tracee.Event{
ProcessID: 2, ParentProcessID: 1, Args: []external.Argument{{ArgMeta: external.ArgMeta{Name: "pathname", Type: ""}, Value: "/proc/self/mem"}},
EventName: "test_event",
},
expectedEvent: tracee.Event{
ProcessID: 2, ParentProcessID: 1, Args: []external.Argument{{ArgMeta: external.ArgMeta{Name: "pathname", Type: ""}, Value: "/proc/self/mem"}},
EventName: "test_event",
},
},
}
Expand Down Expand Up @@ -356,12 +379,16 @@ func TestConsumeSources(t *testing.T) {

var gotNumEvents int
tc.inputSignature. types.Event) error {
assert.Equal(t, tc.expectedEvent.Event, event.(ParsedEvent).Event, tc.name)
if tc.enableParsedEvent {
assert.Equal(t, tc.expectedEvent, event.(ParsedEvent).Event, tc.name)
} else {
assert.Equal(t, tc.expectedEvent, event.(tracee.Event), tc.name)
}
gotNumEvents++
return nil
}

e, err := NewEngine(sigs, inputs, outputChan, logger)
e, err := NewEngine(sigs, inputs, outputChan, logger, tc.enableParsedEvent)
require.NoError(t, err, "constructing engine")
go func() {
e.Start(done)
Expand Down Expand Up @@ -420,7 +447,7 @@ func TestGetSelectedEvents(t *testing.T) {
},
},
}
e, err := NewEngine(sigs, EventSources{Tracee: make(chan types.Event)}, make(chan types.Finding), &bytes.Buffer{})
e, err := NewEngine(sigs, EventSources{Tracee: make(chan types.Event)}, make(chan types.Finding), &bytes.Buffer{}, false)
require.NoError(t, err, "constructing engine")
se := e.GetSelectedEvents()
expected := []types.SignatureEventSelector{
Expand Down
6 changes: 5 additions & 1 deletion tracee-rules/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func main() {
if err != nil {
return err
}
e, err := engine.NewEngine(sigs, inputs, output, os.Stderr)
e, err := engine.NewEngine(sigs, inputs, output, os.Stderr, c.Bool("rego-enable-parsed-events"))
if err != nil {
return fmt.Errorf("constructing engine: %w", err)
}
Expand Down Expand Up @@ -146,6 +146,10 @@ func main() {
Usage: "listening address of the pprof endpoints server",
Value: ":7777",
},
&cli.BoolFlag{
Name: "rego-enable-parsed-events",
Usage: "enables pre parsing of input events to rego prior to evaluation",
},
},
}
err := app.Run(os.Args)
Expand Down
0