Skip to content

Commit

Permalink
Added decomposer tests for condition step
Browse files Browse the repository at this point in the history
  • Loading branch information
MaartendeKruijf committed May 3, 2024
1 parent cde5d9b commit 07f9a9d
Show file tree
Hide file tree
Showing 4 changed files with 223 additions and 10 deletions.
10 changes: 7 additions & 3 deletions internal/decomposer/decomposer.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,16 @@ 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 {
Expand Down Expand Up @@ -158,7 +162,7 @@ func (decomposer *Decomposer) ExecuteStep(step cacao.Step, scopeVariables cacao.
case cacao.StepTypePlaybookAction:
return decomposer.playbookActionExecutor.Execute(metadata, step, variables)
case cacao.StepTypeIfCondition:
stepId, branch, err := decomposer.conditionExecutor.Execute(metadata, step)
stepId, branch, err := decomposer.conditionExecutor.Execute(metadata, step, variables)
if err != nil {
return cacao.NewVariables(), err
}
Expand Down
4 changes: 2 additions & 2 deletions internal/executors/condition/condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ func New(capabilities map[string]capability.ICapability) *Executor {

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

type Executor struct {
capabilities map[string]capability.ICapability
}

func (executor *Executor) Execute(meta execution.Metadata, step cacao.Step) (string, bool, error) {
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")
Expand Down
200 changes: 195 additions & 5 deletions test/unittest/decomposer/decomposer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"soarca/models/cacao"
"soarca/models/execution"
"soarca/test/unittest/mocks/mock_executor"
mock_condition_executor "soarca/test/unittest/mocks/mock_executor/condition"
mock_playbook_action_executor "soarca/test/unittest/mocks/mock_executor/playbook_action"
"soarca/test/unittest/mocks/mock_guid"
"soarca/test/unittest/mocks/mock_reporter"
Expand All @@ -21,6 +22,7 @@ import (
func TestExecutePlaybook(t *testing.T) {
mock_action_executor := new(mock_executor.Mock_Action_Executor)
mock_playbook_action_executor := new(mock_playbook_action_executor.Mock_PlaybookActionExecutor)
mock_condition_executor := new(mock_condition_executor.Mock_Condition)
uuid_mock := new(mock_guid.Mock_Guid)
mock_reporter := new(mock_reporter.Mock_Reporter)

Expand All @@ -37,7 +39,9 @@ func TestExecutePlaybook(t *testing.T) {

decomposer := decomposer.New(mock_action_executor,
mock_playbook_action_executor,
uuid_mock, mock_reporter)
mock_condition_executor,
uuid_mock,
mock_reporter)

step1 := cacao.Step{
Type: "action",
Expand Down Expand Up @@ -116,6 +120,7 @@ func TestExecutePlaybook(t *testing.T) {
func TestExecutePlaybookMultiStep(t *testing.T) {
mock_action_executor := new(mock_executor.Mock_Action_Executor)
mock_playbook_action_executor := new(mock_playbook_action_executor.Mock_PlaybookActionExecutor)
mock_condition_executor := new(mock_condition_executor.Mock_Condition)
uuid_mock := new(mock_guid.Mock_Guid)
mock_reporter := new(mock_reporter.Mock_Reporter)

Expand Down Expand Up @@ -143,7 +148,9 @@ func TestExecutePlaybookMultiStep(t *testing.T) {

decomposer := decomposer.New(mock_action_executor,
mock_playbook_action_executor,
uuid_mock, mock_reporter)
mock_condition_executor,
uuid_mock,
mock_reporter)

step1 := cacao.Step{
Type: "action",
Expand Down Expand Up @@ -260,6 +267,7 @@ Test with an Empty OnCompletion will result in not executing the step.
func TestExecuteEmptyMultiStep(t *testing.T) {
mock_action_executor2 := new(mock_executor.Mock_Action_Executor)
mock_playbook_action_executor2 := new(mock_playbook_action_executor.Mock_PlaybookActionExecutor)
mock_condition_executor := new(mock_condition_executor.Mock_Condition)
uuid_mock2 := new(mock_guid.Mock_Guid)
mock_reporter := new(mock_reporter.Mock_Reporter)

Expand All @@ -286,7 +294,9 @@ func TestExecuteEmptyMultiStep(t *testing.T) {

decomposer2 := decomposer.New(mock_action_executor2,
mock_playbook_action_executor2,
uuid_mock2, mock_reporter)
mock_condition_executor,
uuid_mock2,
mock_reporter)

step1 := cacao.Step{
Type: "ssh",
Expand Down Expand Up @@ -329,6 +339,7 @@ Test with an not occuring on completion id will result in not executing the step
func TestExecuteIllegalMultiStep(t *testing.T) {
mock_action_executor2 := new(mock_executor.Mock_Action_Executor)
mock_playbook_action_executor2 := new(mock_playbook_action_executor.Mock_PlaybookActionExecutor)
mock_condition_executor := new(mock_condition_executor.Mock_Condition)
uuid_mock2 := new(mock_guid.Mock_Guid)
mock_reporter := new(mock_reporter.Mock_Reporter)

Expand All @@ -345,7 +356,9 @@ func TestExecuteIllegalMultiStep(t *testing.T) {

decomposer2 := decomposer.New(mock_action_executor2,
mock_playbook_action_executor2,
uuid_mock2, mock_reporter)
mock_condition_executor,
uuid_mock2,
mock_reporter)

step1 := cacao.Step{
Type: "action",
Expand Down Expand Up @@ -382,6 +395,7 @@ func TestExecuteIllegalMultiStep(t *testing.T) {
func TestExecutePlaybookAction(t *testing.T) {
mock_action_executor := new(mock_executor.Mock_Action_Executor)
mock_playbook_action_executor := new(mock_playbook_action_executor.Mock_PlaybookActionExecutor)
mock_condition_executor := new(mock_condition_executor.Mock_Condition)
uuid_mock := new(mock_guid.Mock_Guid)
mock_reporter := new(mock_reporter.Mock_Reporter)
expectedVariables := cacao.Variable{
Expand All @@ -392,7 +406,9 @@ func TestExecutePlaybookAction(t *testing.T) {

decomposer := decomposer.New(mock_action_executor,
mock_playbook_action_executor,
uuid_mock, mock_reporter)
mock_condition_executor,
uuid_mock,
mock_reporter)

step1 := cacao.Step{
Type: "playbook-action",
Expand Down Expand Up @@ -439,3 +455,177 @@ func TestExecutePlaybookAction(t *testing.T) {
assert.Equal(t, found, true)
assert.Equal(t, value.Value, "value")
}

func TestExecuteIfCondition(t *testing.T) {

mock_action_executor := new(mock_executor.Mock_Action_Executor)
mock_playbook_action_executor := new(mock_playbook_action_executor.Mock_PlaybookActionExecutor)
mock_condition_executor := new(mock_condition_executor.Mock_Condition)
uuid_mock := new(mock_guid.Mock_Guid)
mock_reporter := new(mock_reporter.Mock_Reporter)
expectedVariables := cacao.Variable{
Type: "string",
Name: "__var1__",
Value: "testing",
}

// returned from step
expectedVariables2 := cacao.Variable{
Type: "string",
Name: "__var2__",
Value: "testing2",
}

expectedCommand := cacao.Command{
Type: "ssh",
Command: "ssh ls -la",
}

expectedTarget := cacao.AgentTarget{
Name: "sometarget",
AuthInfoIdentifier: "id",
}

expectedAgent := cacao.AgentTarget{
Type: "soarca",
Name: "soarca-ssh",
}

decomposer := decomposer.New(mock_action_executor,
mock_playbook_action_executor,
mock_condition_executor,
uuid_mock,
mock_reporter)

end := cacao.Step{
Type: cacao.StepTypeEnd,
ID: "end--test",
Name: "end step",
}

endTrue := cacao.Step{
Type: cacao.StepTypeEnd,
ID: "end--true",
Name: "end branch true step",
}

stepTrue := cacao.Step{
Type: cacao.StepTypeAction,
ID: "action--step-true",
Name: "ssh-tests",
Commands: []cacao.Command{expectedCommand},
Targets: []string{expectedTarget.ID},
StepVariables: cacao.NewVariables(expectedVariables),
OnCompletion: endTrue.ID,
}

endFalse := cacao.Step{
Type: cacao.StepTypeEnd,
ID: "end--false",
Name: "end branch false step",
}

stepFalse := cacao.Step{
Type: cacao.StepTypeAction,
ID: "action--step-false",
Name: "ssh-tests",
Commands: []cacao.Command{expectedCommand},
Targets: []string{expectedTarget.ID},
StepVariables: cacao.NewVariables(expectedVariables),
OnCompletion: endFalse.ID,
}

stepCompletion := cacao.Step{
Type: cacao.StepTypeAction,
ID: "action--step-completion",
Name: "ssh-tests",
Commands: []cacao.Command{expectedCommand},
Targets: []string{expectedTarget.ID},
StepVariables: cacao.NewVariables(expectedVariables),
OnCompletion: end.ID,
}

stepIf := cacao.Step{
Type: cacao.StepTypeIfCondition,
ID: "if-condition--test",
Name: "if condition",
StepVariables: cacao.NewVariables(expectedVariables),
Condition: "__var1__:value = testing",
OnTrue: stepTrue.ID,
OnFalse: stepFalse.ID,
OnCompletion: stepCompletion.ID,
}

start := cacao.Step{
Type: cacao.StepTypeStart,
ID: "start--test",
Name: "start step",
OnCompletion: stepIf.ID,
}

playbook := cacao.Playbook{
ID: "test",
Type: "test",
Name: "playbook-test",
WorkflowStart: start.ID,
Workflow: map[string]cacao.Step{start.ID: start,
stepIf.ID: stepIf,
stepTrue.ID: stepTrue,
stepFalse.ID: stepFalse,
stepCompletion.ID: stepCompletion,
end.ID: end,
endTrue.ID: endTrue,
endFalse.ID: endFalse},
AgentDefinitions: map[string]cacao.AgentTarget{expectedAgent.ID: expectedAgent},
TargetDefinitions: map[string]cacao.AgentTarget{expectedTarget.ID: expectedTarget},
}

executionId, _ := uuid.Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
metaStepIf := execution.Metadata{ExecutionId: executionId, PlaybookId: "test", StepId: stepIf.ID}

uuid_mock.On("New").Return(executionId)
mock_reporter.On("ReportWorkflow", executionId, playbook).Return()

mock_condition_executor.On("Execute",
metaStepIf,
stepIf,
cacao.NewVariables(expectedVariables)).Return(stepTrue.ID, true, nil)

stepTrueDetails := action.PlaybookStepMetadata{
Step: stepTrue,
Targets: playbook.TargetDefinitions,
Auth: playbook.AuthenticationInfoDefinitions,
Agent: expectedAgent,
Variables: cacao.NewVariables(expectedVariables),
}

metaStepTrue := execution.Metadata{ExecutionId: executionId, PlaybookId: "test", StepId: stepTrue.ID}

mock_action_executor.On("Execute",
metaStepTrue,
stepTrueDetails).Return(cacao.NewVariables(expectedVariables2), nil)

stepCompletionDetails := action.PlaybookStepMetadata{
Step: stepCompletion,
Targets: playbook.TargetDefinitions,
Auth: playbook.AuthenticationInfoDefinitions,
Agent: expectedAgent,
Variables: cacao.NewVariables(expectedVariables, expectedVariables2),
}

metaStepCompletion := execution.Metadata{ExecutionId: executionId, PlaybookId: "test", StepId: stepCompletion.ID}

mock_action_executor.On("Execute",
metaStepCompletion,
stepCompletionDetails).Return(cacao.NewVariables(), nil)

details, err := decomposer.Execute(playbook)
uuid_mock.AssertExpectations(t)
fmt.Println(err)
assert.Equal(t, err, nil)
assert.Equal(t, details.ExecutionId, executionId)
mock_reporter.AssertExpectations(t)
mock_condition_executor.AssertExpectations(t)
mock_action_executor.AssertExpectations(t)

}
19 changes: 19 additions & 0 deletions test/unittest/mocks/mock_executor/condition/condition_executor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package mock_condition_executor

import (
"soarca/models/cacao"
"soarca/models/execution"

"github.com/stretchr/testify/mock"
)

type Mock_Condition struct {
mock.Mock
}

func (executer *Mock_Condition) Execute(metadata execution.Metadata,
step cacao.Step,
variables cacao.Variables) (string, bool, error) {
args := executer.Called(metadata, step, variables)
return args.String(0), args.Bool(1), args.Error(2)
}

0 comments on commit 07f9a9d

Please sign in to comment.