Skip to content

Commit

Permalink
chore (engine): split Init from NewEngine
Browse files Browse the repository at this point in the history
Previously data sources could not be registered after the NewEngine call
call and be used in signatures, due to the Init calls being made in
NewEngine.

Fix by moving the loadSignature and initial data source registers to
a new Init method from NewEngine.

In addition, export a method in tracee to prepare the builtin data
sources provided out of the box.
  • Loading branch information
NDStrahilevitz committed Jul 27, 2023
1 parent 68e9609 commit d588ce8
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 17 deletions.
4 changes: 4 additions & 0 deletions cmd/tracee-rules/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,11 @@ func main() {
c.Bool(server.PProfEndpointFlag),
c.Bool(server.PyroscopeAgentFlag),
)
if err != nil {
return err
}

err = e.Init()
if err != nil {
return err
}
Expand Down
15 changes: 14 additions & 1 deletion pkg/ebpf/signature_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ func (t *Tracee) engineEvents(ctx context.Context, in <-chan *trace.Event) (<-ch
engineInput := make(chan protocol.Event)
source := engine.EventSources{Tracee: engineInput}

t.config.EngineConfig.DataSources = append(t.config.EngineConfig.DataSources, containers.NewDataSource(t.containers))
// Prepare built in data sources
t.config.EngineConfig.DataSources = t.PrepareBuiltinDataSources()

sigEngine, err := engine.NewEngine(t.config.EngineConfig, source, engineOutput)
if err != nil {
Expand All @@ -36,6 +37,11 @@ func (t *Tracee) engineEvents(ctx context.Context, in <-chan *trace.Event) (<-ch
}
}

err = t.sigEngine.Init()
if err != nil {
logger.Fatalw("failed to initialize signature engine in \"everything is an event\" mode", "error", err)
}

go t.sigEngine.Start(ctx)

// TODO: in the upcoming releases, the rule engine should be changed to receive trace.Event,
Expand Down Expand Up @@ -110,3 +116,10 @@ func (t *Tracee) engineEvents(ctx context.Context, in <-chan *trace.Event) (<-ch

return out, errc
}

// PrepareBuiltinDataSources returns a list of all data sources tracee makes available built-in
func (t *Tracee) PrepareBuiltinDataSources() []detect.DataSource {
return []detect.DataSource{
containers.NewDataSource(t.containers),
}
}
35 changes: 22 additions & 13 deletions pkg/signatures/engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ func (engine *Engine) Stats() *metrics.Stats {

// NewEngine creates a new signatures-engine with the given arguments
// inputs and outputs are given as channels created by the consumer
// Signatures are not loaded at this point, Init must be called to perform config side effects.
func NewEngine(config Config, sources EventSources, output chan detect.Finding) (*Engine, error) {
if sources.Tracee == nil || output == nil {
return nil, fmt.Errorf("nil input received")
Expand All @@ -70,19 +71,6 @@ func NewEngine(config Config, sources EventSources, output chan detect.Finding)
engine.dataSources = map[string]map[string]detect.DataSource{}
engine.dataSourcesMutex.Unlock()

for _, datasource := range config.DataSources {
err := engine.RegisterDataSource(datasource)
if err != nil {
logger.Errorw("Loading signatures data source: " + err.Error())
}
}

for _, sig := range config.Signatures {
_, err := engine.loadSignature(sig)
if err != nil {
logger.Errorw("Loading signature: " + err.Error())
}
}
return &engine, nil
}

Expand All @@ -97,6 +85,27 @@ func signatureStart(signature detect.Signature, c chan protocol.Event, wg *sync.
wg.Done()
}

// Init loads and initializes signatures and data sources passed in NewEngine.
// The split allows the loading of additional signatures and data sources between
// NewEngine and Start if needed.
func (engine *Engine) Init() error {
for _, dataSource := range engine.config.DataSources {
err := engine.RegisterDataSource(dataSource)
if err != nil {
logger.Errorw("Loading signatures data source: " + err.Error())
}
}

for _, sig := range engine.config.Signatures {
_, err := engine.loadSignature(sig)
if err != nil {
logger.Errorw("Loading signature: " + err.Error())
}
}

return nil
}

// Start starts processing events and detecting signatures
// it runs continuously until stopped by the done channel
// once done, it cleans all internal resources, which means the engine is not reusable
Expand Down
12 changes: 9 additions & 3 deletions pkg/signatures/engine/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -357,9 +357,11 @@ func TestEngine_ConsumeSources(t *testing.T) {

e, err := NewEngine(tc.config, inputs, outputChan)
require.NoError(t, err, "constructing engine")
go func() {
e.Start(ctx)
}()

err = e.Init()
require.NoError(t, err, "initializing engine")

go e.Start(ctx)

// send a test event
e.inputs.Tracee <- tc.inputEvent
Expand Down Expand Up @@ -419,6 +421,10 @@ func TestEngine_GetSelectedEvents(t *testing.T) {
config := Config{Signatures: sigs}
e, err := NewEngine(config, EventSources{Tracee: make(chan protocol.Event)}, make(chan detect.Finding))
require.NoError(t, err, "constructing engine")

err = e.Init()
require.NoError(t, err, "initializing engine")

se := e.GetSelectedEvents()
expected := []detect.SignatureEventSelector{
{
Expand Down

0 comments on commit d588ce8

Please sign in to comment.