Skip to content
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

analyze: enable sigs consuming sigs #4327

Merged
merged 4 commits into from
Nov 5, 2024
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
204 changes: 109 additions & 95 deletions cmd/tracee/cmd/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import (
"github.com/spf13/viper"

"github.com/aquasecurity/tracee/pkg/cmd/flags"
"github.com/aquasecurity/tracee/pkg/cmd/initialize"
tracee "github.com/aquasecurity/tracee/pkg/ebpf"
"github.com/aquasecurity/tracee/pkg/cmd/initialize/sigs"
"github.com/aquasecurity/tracee/pkg/events"
"github.com/aquasecurity/tracee/pkg/events/findings"
"github.com/aquasecurity/tracee/pkg/logger"
"github.com/aquasecurity/tracee/pkg/signatures/engine"
"github.com/aquasecurity/tracee/pkg/signatures/signature"
Expand Down Expand Up @@ -77,127 +77,141 @@ tracee analyze --events anti_debugging events.json`,
bindViperFlag(cmd, "rego")
bindViperFlag(cmd, "signatures-dir")
},
Run: func(cmd *cobra.Command, args []string) {
logFlags := viper.GetStringSlice("log")
Run: command,
DisableFlagsInUseLine: true,
}

logCfg, err := flags.PrepareLogger(logFlags, true)
if err != nil {
logger.Fatalw("Failed to prepare logger", "error", err)
}
logger.Init(logCfg)
func command(cmd *cobra.Command, args []string) {
logFlags := viper.GetStringSlice("log")

inputFile, err := os.Open(args[0])
if err != nil {
logger.Fatalw("Failed to get signatures-dir flag", "err", err)
}
logCfg, err := flags.PrepareLogger(logFlags, true)
if err != nil {
logger.Fatalw("Failed to prepare logger", "error", err)
}
logger.Init(logCfg)

// Rego command line flags
inputFile, err := os.Open(args[0])
if err != nil {
logger.Fatalw("Failed to get signatures-dir flag", "err", err)
}

rego, err := flags.PrepareRego(viper.GetStringSlice("rego"))
if err != nil {
logger.Fatalw("Failed to parse rego flags", "err", err)
}
// Rego command line flags

// Signature directory command line flags
rego, err := flags.PrepareRego(viper.GetStringSlice("rego"))
if err != nil {
logger.Fatalw("Failed to parse rego flags", "err", err)
}

signatureEvents := viper.GetStringSlice("events")
// if no event was passed, load all events
if len(signatureEvents) == 0 {
signatureEvents = nil
}
// Signature directory command line flags

sigs, _, err := signature.Find(
rego.RuntimeTarget,
rego.PartialEval,
viper.GetStringSlice("signatures-dir"),
signatureEvents,
rego.AIO,
)
signatureEvents := viper.GetStringSlice("events")
// if no event was passed, load all events
if len(signatureEvents) == 0 {
signatureEvents = nil
}

if err != nil {
logger.Fatalw("Failed to find signature event", "err", err)
}
signatures, _, err := signature.Find(
rego.RuntimeTarget,
rego.PartialEval,
viper.GetStringSlice("signatures-dir"),
signatureEvents,
rego.AIO,
)

if len(sigs) == 0 {
logger.Fatalw("No signature event loaded")
}
if err != nil {
logger.Fatalw("Failed to find signature event", "err", err)
}

logger.Infow(
"Signatures loaded",
"total", len(sigs),
"signatures", getSigsNames(sigs),
)
if len(signatures) == 0 {
logger.Fatalw("No signature event loaded")
}

_ = initialize.CreateEventsFromSignatures(events.StartSignatureID, sigs)
logger.Infow(
"Signatures loaded",
"total", len(signatures),
"signatures", getSigsNames(signatures),
)

engineConfig := engine.Config{
Signatures: sigs,
SignatureBufferSize: 1000,
}
_ = sigs.CreateEventsFromSignatures(events.StartSignatureID, signatures)

ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
engineConfig := engine.Config{
Signatures: signatures,
SignatureBufferSize: 1000,
}

engineOutput := make(chan *detect.Finding)
engineInput := make(chan protocol.Event)
// two seperate contexts.
// 1. signal notifiable context that can terminate both analyze and engine work
// 2. signal solely to notify internally inside analyze once file input is over
signalCtx, _ := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
fileReadCtx, stop := context.WithCancel(signalCtx)

source := engine.EventSources{Tracee: engineInput}
sigEngine, err := engine.NewEngine(engineConfig, source, engineOutput)
if err != nil {
logger.Fatalw("Failed to create engine", "err", err)
}
engineOutput := make(chan *detect.Finding)
engineInput := make(chan protocol.Event)

err = sigEngine.Init()
if err != nil {
logger.Fatalw("failed to initialize signature engine", "err", err)
}
source := engine.EventSources{Tracee: engineInput}
sigEngine, err := engine.NewEngine(engineConfig, source, engineOutput)
if err != nil {
logger.Fatalw("Failed to create engine", "err", err)
}

go sigEngine.Start(ctx)
err = sigEngine.Init()
if err != nil {
logger.Fatalw("failed to initialize signature engine", "err", err)
}

// producer
go produce(ctx, inputFile, engineInput)
go sigEngine.Start(signalCtx)

// consumer
for {
select {
case finding, ok := <-engineOutput:
if !ok {
return
}
process(finding)
case <-ctx.Done():
goto drain
// producer
go produce(fileReadCtx, stop, inputFile, engineInput)

// consumer
for {
select {
case finding, ok := <-engineOutput:
if !ok {
return
}
process(finding)
case <-fileReadCtx.Done():
// ensure the engineInput channel will be closed
goto drain
case <-signalCtx.Done():
// ensure the engineInput channel will be closed
goto drain
}
drain:
// drain
for {
select {
case finding, ok := <-engineOutput:
if !ok {
return
}
process(finding)
default:
}
drain:
// drain
defer close(engineInput)
for {
select {
case finding, ok := <-engineOutput:
if !ok {
return
}

process(finding)
default:
return
}
},
DisableFlagsInUseLine: true,
}
}

func produce(ctx context.Context, inputFile *os.File, engineInput chan protocol.Event) {
// ensure the engineInput channel will be closed
defer close(engineInput)

func produce(ctx context.Context, cancel context.CancelFunc, inputFile *os.File, engineInput chan<- protocol.Event) {
scanner := bufio.NewScanner(inputFile)
scanner.Split(bufio.ScanLines)
for {
select {
case <-ctx.Done():
// if terminated from above
return
default:
if !scanner.Scan() { // if EOF or error close the done channel and return
if err := scanner.Err(); err != nil {
logger.Errorw("Error while scanning input file", "error", err)
}
// terminate analysis here and proceed to draining
cancel()
return
}

Expand All @@ -212,7 +226,7 @@ func produce(ctx context.Context, inputFile *os.File, engineInput chan protocol.
}

func process(finding *detect.Finding) {
event, err := tracee.FindingToEvent(finding)
event, err := findings.FindingToEvent(finding)
if err != nil {
logger.Fatalw("Failed to convert finding to event", "err", err)
}
Expand All @@ -232,15 +246,15 @@ func bindViperFlag(cmd *cobra.Command, flag string) {
}
}

func getSigsNames(sigs []detect.Signature) []string {
var sigsNames []string
for _, sig := range sigs {
func getSigsNames(signatures []detect.Signature) []string {
var sigNames []string
for _, sig := range signatures {
sigMeta, err := sig.GetMetadata()
if err != nil {
logger.Warnw("Failed to get signature metadata", "err", err)
continue
}
sigsNames = append(sigsNames, sigMeta.Name)
sigNames = append(sigNames, sigMeta.Name)
}
return sigsNames
return sigNames
}
6 changes: 3 additions & 3 deletions cmd/tracee/cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/spf13/cobra"

"github.com/aquasecurity/tracee/pkg/cmd"
"github.com/aquasecurity/tracee/pkg/cmd/initialize"
"github.com/aquasecurity/tracee/pkg/cmd/initialize/sigs"
"github.com/aquasecurity/tracee/pkg/events"
"github.com/aquasecurity/tracee/pkg/logger"
"github.com/aquasecurity/tracee/pkg/signatures/signature"
Expand Down Expand Up @@ -41,7 +41,7 @@ var listCmd = &cobra.Command{
os.Exit(1)
}

sigs, _, err := signature.Find(
signatures, _, err := signature.Find(
compile.TargetRego,
false,
sigsDir,
Expand All @@ -53,7 +53,7 @@ var listCmd = &cobra.Command{
os.Exit(1)
}

initialize.CreateEventsFromSignatures(events.StartSignatureID, sigs)
sigs.CreateEventsFromSignatures(events.StartSignatureID, signatures)

includeSigs := true
wideOutput := c.Flags().Lookup("wide").Value.String() == "true"
Expand Down
7 changes: 4 additions & 3 deletions pkg/cmd/cobra/cobra.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/aquasecurity/tracee/pkg/cmd/flags"
"github.com/aquasecurity/tracee/pkg/cmd/flags/server"
"github.com/aquasecurity/tracee/pkg/cmd/initialize"
"github.com/aquasecurity/tracee/pkg/cmd/initialize/sigs"
"github.com/aquasecurity/tracee/pkg/cmd/printer"
"github.com/aquasecurity/tracee/pkg/config"
"github.com/aquasecurity/tracee/pkg/errfmt"
Expand Down Expand Up @@ -56,7 +57,7 @@ func GetTraceeRunner(c *cobra.Command, version string) (cmd.Runner, error) {

// Signature directory command line flags

sigs, dataSources, err := signature.Find(
signatures, dataSources, err := signature.Find(
rego.RuntimeTarget,
rego.PartialEval,
viper.GetStringSlice("signatures-dir"),
Expand All @@ -67,7 +68,7 @@ func GetTraceeRunner(c *cobra.Command, version string) (cmd.Runner, error) {
return runner, err
}

sigNameToEventId := initialize.CreateEventsFromSignatures(events.StartSignatureID, sigs)
sigNameToEventId := sigs.CreateEventsFromSignatures(events.StartSignatureID, signatures)

// Initialize a tracee config structure

Expand Down Expand Up @@ -334,7 +335,7 @@ func GetTraceeRunner(c *cobra.Command, version string) (cmd.Runner, error) {
runner.TraceeConfig.EngineConfig = engine.Config{
Enabled: true,
SigNameToEventID: sigNameToEventId,
Signatures: sigs,
Signatures: signatures,
// This used to be a flag, we have removed the flag from this binary to test
// if users do use it or not.
SignatureBufferSize: 1000,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package initialize
package sigs

import (
"strconv"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package initialize
package sigs_test

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/aquasecurity/tracee/pkg/cmd/initialize/sigs"
"github.com/aquasecurity/tracee/pkg/events"
"github.com/aquasecurity/tracee/pkg/signatures/signature"
"github.com/aquasecurity/tracee/types/detect"
Expand Down Expand Up @@ -159,7 +160,7 @@ func Test_CreateEventsFromSigs(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
t.Parallel()

CreateEventsFromSignatures(test.startId, test.signatures)
sigs.CreateEventsFromSignatures(test.startId, test.signatures)

for _, expected := range test.expected {
eventDefID, ok := events.Core.GetDefinitionIDByName(expected.GetName())
Expand Down
3 changes: 2 additions & 1 deletion pkg/ebpf/signature_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/aquasecurity/tracee/pkg/containers"
"github.com/aquasecurity/tracee/pkg/dnscache"
"github.com/aquasecurity/tracee/pkg/events"
"github.com/aquasecurity/tracee/pkg/events/findings"
"github.com/aquasecurity/tracee/pkg/logger"
"github.com/aquasecurity/tracee/pkg/proctree"
"github.com/aquasecurity/tracee/pkg/signatures/engine"
Expand Down Expand Up @@ -124,7 +125,7 @@ func (t *Tracee) engineEvents(ctx context.Context, in <-chan *trace.Event) (<-ch
continue // might happen during initialization (ctrl+c seg faults)
}

event, err := FindingToEvent(finding)
event, err := findings.FindingToEvent(finding)
if err != nil {
t.handleError(err)
continue
Expand Down
6 changes: 4 additions & 2 deletions pkg/ebpf/finding.go → pkg/events/findings/findings.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package ebpf
package findings

import (
"maps"

"github.com/aquasecurity/tracee/pkg/errfmt"
"github.com/aquasecurity/tracee/pkg/events"
"github.com/aquasecurity/tracee/types/detect"
Expand Down Expand Up @@ -172,7 +174,7 @@ func getMetadataFromSignatureMetadata(sigMetadata detect.SignatureMetadata) *tra
metadata.Description = sigMetadata.Description
metadata.Tags = sigMetadata.Tags

properties := sigMetadata.Properties
properties := maps.Clone(sigMetadata.Properties)
if sigMetadata.Properties == nil {
properties = make(map[string]interface{})
}
Expand Down
Loading
Loading