diff --git a/internal/capability/openc2/openc2.go b/internal/capability/openc2/openc2.go new file mode 100644 index 00000000..9e13160f --- /dev/null +++ b/internal/capability/openc2/openc2.go @@ -0,0 +1,63 @@ +package openc2 + +import ( + "reflect" + + "soarca/logger" + "soarca/models/cacao" + "soarca/models/execution" + "soarca/utils/http" +) + +type OpenC2Capability struct { + httpRequest http.IHttpRequest +} + +type Empty struct{} + +const ( + openc2ResultVariableName = "__soarca_openc2_http_result__" + openc2capabilityName = "soarca-openc2-http" +) + +var ( + component = reflect.TypeOf(Empty{}).PkgPath() + log *logger.Log +) + +func init() { + log = logger.Logger(component, logger.Info, "", logger.Json) +} + +func New(httpRequest http.IHttpRequest) *OpenC2Capability { + return &OpenC2Capability{httpRequest: httpRequest} +} + +func (OpenC2Capability *OpenC2Capability) GetType() string { + return openc2capabilityName +} + +func (OpenC2Capability *OpenC2Capability) Execute( + metadata execution.Metadata, + command cacao.Command, + authentication cacao.AuthenticationInformation, + target cacao.AgentTarget, + variables cacao.Variables, +) (cacao.Variables, error) { + log.Trace(metadata.ExecutionId) + + httpOptions := http.HttpOptions{ + Command: &command, + Target: &target, + Auth: &authentication, + } + response, err := OpenC2Capability.httpRequest.Request(httpOptions) + if err != nil { + log.Error(err) + return cacao.NewVariables(), err + } + + results := cacao.NewVariables(cacao.Variable{Name: openc2ResultVariableName, Value: string(response)}) + log.Trace("Finished openc2 execution, will return the variables: ", results) + return results, nil +} diff --git a/test/unittest/capability/openc2/openc2_test.go b/test/unittest/capability/openc2/openc2_test.go new file mode 100644 index 00000000..08806152 --- /dev/null +++ b/test/unittest/capability/openc2/openc2_test.go @@ -0,0 +1,78 @@ +package openc2_test + +import ( + "testing" + + openc2 "soarca/internal/capability/openc2" + "soarca/models/cacao" + "soarca/models/execution" + mockRequest "soarca/test/unittest/mocks/mock_utils/http" + "soarca/utils/http" + + assert "github.com/go-playground/assert/v2" + "github.com/google/uuid" +) + +func TestOpenC2Request(t *testing.T) { + mockHttp := &mockRequest.MockHttpRequest{} + openc2 := openc2.New(mockHttp) + + authId, _ := uuid.Parse("6aa7b810-9dad-11d1-81b4-00c04fd430c8") + executionId, _ := uuid.Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8") + playbookId, _ := uuid.Parse("d09351a2-a075-40c8-8054-0b7c423db83f") + stepId, _ := uuid.Parse("81eff59f-d084-4324-9e0a-59e353dbd28f") + + target := cacao.AgentTarget{ + HttpUrl: "https://soarca.tno.nl", + AuthInfoIdentifier: authId.String(), + } + + auth := cacao.AuthenticationInformation{ + ID: authId.String(), + Type: "oauth2", + Token: "this-is-a-test", + } + + command := cacao.Command{ + Type: "http-api", + Command: "POST / HTTP/1.1", + Headers: map[string]string{"accept": "application/json"}, + } + + cacaoVariable := cacao.Variable{ + Type: "string", + Name: "test request building", + Value: "", + } + + metadata := execution.Metadata{ + ExecutionId: executionId, + PlaybookId: playbookId.String(), + StepId: stepId.String(), + } + + httpOptions := http.HttpOptions{ + Command: &command, + Target: &target, + Auth: &auth, + } + + payload := "test payload" + + payloadBytes := []byte(payload) + + mockHttp.On("Request", httpOptions).Return(payloadBytes, nil) + + results, err := openc2.Execute( + metadata, + command, + auth, + target, + cacao.NewVariables(cacaoVariable)) + if err != nil { + t.Log(err) + t.Fail() + } + t.Log(results) + assert.Equal(t, results["__soarca_openc2_http_result__"].Value, payload) +}