Skip to content

Commit

Permalink
Feature/116 add if condition executor (#138)
Browse files Browse the repository at this point in the history
  • Loading branch information
MaartendeKruijf authored May 13, 2024
1 parent 7460eff commit 8f39ce8
Show file tree
Hide file tree
Showing 10 changed files with 1,127 additions and 9 deletions.
6 changes: 5 additions & 1 deletion docs/content/en/docs/core-components/executer.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,11 @@ The result of the step comparison will be returned to the decomposer. A result c
### While condition executor
The if-condition executor will process a cacao while-condition step and determine it's output.

The result of the step comparison will be returned to the decomposer. A result can be either a next step id and/or error status.
The result of the step comparison will be returned to the decomposer. A result can be either a next step id and/or error status. Only STIX comparison expressions are implemented at this time.

{{% alert title="Warning" color="warning" %}}
Note only [Comparison Expression](http://docs.oasis-open.org/cti/stix/v2.0/cs01/part5-stix-patterning/stix-v2.0-cs01-part5-stix-patterning.html#_Toc496717749) are implemented for all CACAO variable types.
{{% /alert %}}

### Parallel step executor
The parallel executor will execute the parallel step. This wil be done in sequence to simplify implementation. As parallel steps must not be depended on each other sequential execution is possible. Later this will be changed.
10 changes: 9 additions & 1 deletion internal/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ import (
"soarca/internal/capability/ssh"
"soarca/internal/decomposer"
"soarca/internal/executors/action"
"soarca/internal/executors/condition"
"soarca/internal/executors/playbook_action"
"soarca/internal/fin/protocol"
"soarca/internal/guid"
"soarca/internal/reporter"
"soarca/logger"
"soarca/utils"
httpUtil "soarca/utils/http"
"soarca/utils/stix/expression/comparison"

downstreamReporter "soarca/internal/reporter/downstream_reporter"

Expand Down Expand Up @@ -78,8 +80,14 @@ func (controller *Controller) NewDecomposer() decomposer.IDecomposer {

actionExecutor := action.New(capabilities, reporter)
playbookActionExecutor := playbook_action.New(controller, controller, reporter)
stixComparison := comparison.New()
conditionExecutor := condition.New(stixComparison, reporter)
guid := new(guid.Guid)
decompose := decomposer.New(actionExecutor, playbookActionExecutor, guid, reporter)
decompose := decomposer.New(actionExecutor,
playbookActionExecutor,
conditionExecutor,
guid,
reporter)
return decompose
}

Expand Down
19 changes: 17 additions & 2 deletions internal/decomposer/decomposer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"soarca/internal/executors"
"soarca/internal/executors/action"
"soarca/internal/executors/condition"
"soarca/internal/guid"
"soarca/internal/reporter"
"soarca/logger"
Expand Down Expand Up @@ -39,19 +40,24 @@ func init() {

func New(actionExecutor action.IExecuter,
playbookActionExecutor executors.IPlaybookExecuter,
guid guid.IGuid, reporter reporter.IWorkflowReporter) *Decomposer {
condition condition.IExecuter,
guid guid.IGuid,
reporter reporter.IWorkflowReporter) *Decomposer {

return &Decomposer{actionExecutor: actionExecutor,
playbookActionExecutor: playbookActionExecutor,
conditionExecutor: condition,
guid: guid,
reporter: reporter}
reporter: reporter,
}
}

type Decomposer struct {
playbook cacao.Playbook
details ExecutionDetails
actionExecutor action.IExecuter
playbookActionExecutor executors.IPlaybookExecuter
conditionExecutor condition.IExecuter
guid guid.IGuid
reporter reporter.IWorkflowReporter
}
Expand Down Expand Up @@ -157,6 +163,15 @@ func (decomposer *Decomposer) ExecuteStep(step cacao.Step, scopeVariables cacao.
return decomposer.actionExecutor.Execute(metadata, actionMetadata)
case cacao.StepTypePlaybookAction:
return decomposer.playbookActionExecutor.Execute(metadata, step, variables)
case cacao.StepTypeIfCondition:
stepId, branch, err := decomposer.conditionExecutor.Execute(metadata, step, variables)
if err != nil {
return cacao.NewVariables(), err
}
if branch {
return decomposer.ExecuteBranch(stepId, variables)
}
return variables, nil
default:
// NOTE: This currently silently handles unknown step types. Should we return an error instead?
return cacao.NewVariables(), nil
Expand Down
76 changes: 76 additions & 0 deletions internal/executors/condition/condition.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package condition

import (
"errors"
"fmt"
"reflect"
"soarca/internal/reporter"
"soarca/logger"
"soarca/models/cacao"
"soarca/models/execution"
"soarca/utils/stix/expression/comparison"
)

var component = reflect.TypeOf(Executor{}).PkgPath()
var log *logger.Log

func init() {
log = logger.Logger(component, logger.Info, "", logger.Json)
}

func New(comparison comparison.IComparison,
reporter reporter.IStepReporter) *Executor {
return &Executor{comparison: comparison,
reporter: reporter}
}

type IExecuter interface {
Execute(metadata execution.Metadata,
step cacao.Step, variables cacao.Variables) (string, bool, error)
}

type Executor struct {
comparison comparison.IComparison
reporter reporter.IStepReporter
}

func (executor *Executor) Execute(meta execution.Metadata, step cacao.Step, variables cacao.Variables) (string, bool, error) {

if step.Type != cacao.StepTypeIfCondition {
err := errors.New("the provided step type is not compatible with this executor")
log.Error(err)
return step.OnFailure, false, err
}

executor.reporter.ReportStepStart(meta.ExecutionId, step, variables)

result, err := executor.comparison.Evaluate(step.Condition, variables)

// We are reporting early to not have double reporting
executor.reporter.ReportStepEnd(meta.ExecutionId,
step,
variables,
err)

if err != nil {
log.Error(err)
return "", false, err
}

log.Debug("the result was: ", fmt.Sprint(result))

if result {
if step.OnTrue != "" {
log.Trace("will return on true step ", step.OnTrue)
return step.OnTrue, true, nil
}
} else {
if step.OnFalse != "" {
log.Trace("will return on false step ", step.OnFalse)
return step.OnFalse, true, nil
}
}
log.Trace("will return on completion step ", step.OnCompletion)

return step.OnCompletion, false, nil
}
Loading

0 comments on commit 8f39ce8

Please sign in to comment.