From 681be88a3c81fe07eff4e7181d83013d368f5abe Mon Sep 17 00:00:00 2001 From: frikky Date: Sat, 6 Feb 2021 13:09:55 +0100 Subject: [PATCH] Added categories to workflows --- backend/go-app/main.go | 6 +-- backend/go-app/walkoff.go | 68 +++++++++++++++++++++++--- frontend/src/views/AngularWorkflow.jsx | 15 +++--- frontend/src/views/AppCreator.jsx | 20 ++++++-- frontend/src/views/Apps.jsx | 2 +- frontend/src/views/Workflows.jsx | 9 ++-- functions/onprem/orborus/orborus.go | 2 +- 7 files changed, 95 insertions(+), 27 deletions(-) diff --git a/backend/go-app/main.go b/backend/go-app/main.go index b7e9a7fd..1ffd334f 100644 --- a/backend/go-app/main.go +++ b/backend/go-app/main.go @@ -2877,8 +2877,8 @@ func fixUserOrg(ctx context.Context, user *User) *User { // Used for testing only. Shouldn't impact production. func handleCors(resp http.ResponseWriter, request *http.Request) bool { - //allowedOrigins := "http://localhost:3000" - allowedOrigins := "http://localhost:3002" + allowedOrigins := "http://localhost:3000" + //allowedOrigins := "http://localhost:3002" resp.Header().Set("Vary", "Origin") resp.Header().Set("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me, Authorization") @@ -4628,7 +4628,7 @@ func findAvailablePorts(startRange int64, endRange int64) string { func handleSendalert(resp http.ResponseWriter, request *http.Request) { user, err := handleApiAuthentication(resp, request) if err != nil { - log.Printf("Api authentication failed in getworkflows: %s", err) + log.Printf("Api authentication failed in sendalert: %s", err) resp.WriteHeader(401) resp.Write([]byte(`{"success": false}`)) return diff --git a/backend/go-app/walkoff.go b/backend/go-app/walkoff.go index c77f4345..a23a15a3 100644 --- a/backend/go-app/walkoff.go +++ b/backend/go-app/walkoff.go @@ -190,6 +190,10 @@ type WorkflowApp struct { Name string `json:"name" datastore:"name" yaml:"name"` Url string `json:"url" datastore:"url" yaml:"url"` } `json:"contact_info" datastore:"contact_info" yaml:"contact_info" required:false` + ReferenceInfo struct { + DocumentationUrl string `json:"documentation_url" datastore:"documentation_url"` + GithubUrl string `json:"github_url" datastore:"github_url"` + } Actions []WorkflowAppAction `json:"actions" yaml:"actions" required:true datastore:"actions,noindex"` Authentication Authentication `json:"authentication" yaml:"authentication" required:false datastore:"authentication"` Tags []string `json:"tags" yaml:"tags" required:false datastore:"activated"` @@ -317,6 +321,7 @@ type Action struct { AuthenticationId string `json:"authentication_id" datastore:"authentication_id"` Example string `json:"example,omitempty" datastore:"example"` AuthNotRequired bool `json:"auth_not_required,omitempty" datastore:"auth_not_required" yaml:"auth_not_required"` + Category string `json:"category" datastore:"category"` } // Added environment for location to execute @@ -406,8 +411,26 @@ type Workflow struct { Name string `json:"name" datastore:"name"` Value string `json:"value" datastore:"value,noindex"` } `json:"execution_variables,omitempty" datastore:"execution_variables"` - ExecutionEnvironment string `json:"execution_environment" datastore:"execution_environment"` - PreviouslySaved bool `json:"first_save" datastore:"first_save"` + ExecutionEnvironment string `json:"execution_environment" datastore:"execution_environment"` + PreviouslySaved bool `json:"first_save" datastore:"first_save"` + Categories Categories `json:"categories" datastore:"categories"` +} + +type Category struct { + Name string `json:"name" datastore:"name"` + Description string `json:"description" datastore:"description"` + Count int64 `json:"count" datastore:"count"` +} + +type Categories struct { + SIEM Category `json:"siem" datastore:"siem"` + Communication Category `json:"communication" datastore:"communication"` + Assets Category `json:"assets" datastore:"assets"` + Cases Category `json:"cases" datastore:"cases"` + Network Category `json:"network" datastore:"network"` + Intel Category `json:"intel" datastore:"intel"` + EDR Category `json:"edr" datastore:"edr"` + Other Category `json:"other" datastore:"other"` } type ActionResult struct { @@ -1641,13 +1664,16 @@ func getWorkflows(resp http.ResponseWriter, request *http.Request) { q = q.Limit(35) _, err = dbclient.GetAll(ctx, q, &workflows) if err != nil { - log.Printf("Failed getting workflows for user %s: %s", user.Username, err) + log.Printf("Failed getting workflows for user %s: %s (0)", user.Username, err) resp.WriteHeader(401) resp.Write([]byte(`{"success": false}`)) return } } else { - log.Printf("Failed getting workflows for user %s: %s", user.Username, err) + log.Printf("Failed getting workflows for user %s: %s (1)", user.Username, err) + //DeleteKey(ctx, "workflow", "5694357e-8063-4580-8529-301cc72df951") + + //log.Printf("Workflows: %#v", workflows) resp.WriteHeader(401) resp.Write([]byte(`{"success": false}`)) return @@ -2066,6 +2092,32 @@ func updateAppAuth(auth AppAuthenticationStorage, workflowId, nodeId string, add return nil } +func handleCategoryIncrease(workflow Workflow, action Action) Categories { + if action.Category == "" { + log.Printf("Should find app's categories as it's empty during save") + return workflow.Categories + } + + newCategory := "cases" + log.Printf("Adding %s category", newCategory) + switch category := newCategory; { + case category == "cases": + workflow.Categories.Cases.Count += 1 + default: + log.Printf("Can't handle category %s", category) + } + + //Categories Categories `json:"categories" datastore:"categories"` + //found := false + //for _, category := range workflow.Categories { + // if category == newCategory { + // log.Printf("Category %s already exists", category) + // return workflow + //} + //workflow.Categories = handleCategoryIncrease(workflow, action.Category) + return workflow.Categories +} + // Saves a workflow to an ID func saveWorkflow(resp http.ResponseWriter, request *http.Request) { cors := handleCors(resp, request) @@ -2166,6 +2218,7 @@ func saveWorkflow(resp http.ResponseWriter, request *http.Request) { // FIXME - this shouldn't be necessary with proper API checks newActions := []Action{} allNodes := []string{} + workflow.Categories = Categories{} //log.Printf("Action: %#v", action.Authentication) for _, action := range workflow.Actions { @@ -2193,6 +2246,7 @@ func saveWorkflow(resp http.ResponseWriter, request *http.Request) { action.Errors = []string{} } + workflow.Categories = handleCategoryIncrease(workflow, action) newActions = append(newActions, action) } @@ -2203,7 +2257,7 @@ func saveWorkflow(resp http.ResponseWriter, request *http.Request) { workflowapps, apperr := getAllWorkflowApps(ctx, 500) allAuths, err := getAllWorkflowAppAuth(ctx, user.ActiveOrg.Id) if err == nil && len(workflowapps) > 0 && apperr == nil { - log.Printf("Setting actions") + //log.Printf("Setting actions") actionFixing := []Action{} appsAdded := []string{} for _, action := range newActions { @@ -2533,7 +2587,7 @@ func saveWorkflow(resp http.ResponseWriter, request *http.Request) { // FIXME - might be a sploit to run someone elses app if getAllWorkflowApps // doesn't check sharing=true // Have to do it like this to add the user's apps - log.Println("Apps set starting") + //log.Println("Apps set starting") //log.Printf("EXIT ON ERROR: %#v", workflow.Configuration.ExitOnError) workflowApps := []WorkflowApp{} //memcacheName = "all_apps" @@ -4625,7 +4679,7 @@ func deleteWorkflowApp(resp http.ResponseWriter, request *http.Request) { user.PrivateApps = privateApps err = setUser(ctx, &user) if err != nil { - log.Printf("[ERROR]Failed removing %s app for user %s: %s", app.Name, user.Username, err) + log.Printf("[ERROR] Failed removing %s app for user %s: %s", app.Name, user.Username, err) resp.WriteHeader(401) resp.Write([]byte(fmt.Sprintf(`{"success": true"}`))) return diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index f4aca36c..598bef39 100644 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -433,7 +433,7 @@ const AngularWorkflow = (props) => { const abortExecution = () => { setExecutionRunning(false) - alert.info("Aborting execution") + //alert.info("Aborting execution") fetch(globalUrl+"/api/v1/workflows/"+props.match.params.key+"/executions/"+executionRequest.execution_id+"/abort", { method: 'GET', headers: { @@ -1859,13 +1859,6 @@ const AngularWorkflow = (props) => { height: "100%", } - const scrollStyle = { - marginTop: 10, - overflow: "scroll", - height: "100%", - overflowX: "auto", - overflowY: "auto", - } const paperAppStyle = { borderRadius: borderRadius, @@ -2429,8 +2422,11 @@ const AngularWorkflow = (props) => { authentication: [], execution_variable: undefined, example: example, + category: app.categories !== null && app.categories !== undefined && app.categories.length > 0 ? app.categories[0] : "" } + // FIXME: overwrite category if the ACTION chosen has a different category + // const image = "url("+app.large_image+")" // FIXME - find the cytoscape offset position @@ -2489,6 +2485,8 @@ const AngularWorkflow = (props) => { } workflow.actions.push(newAppData) + + console.log(workflow.categories) setWorkflow(workflow) if (newAppPopup) { @@ -2605,7 +2603,6 @@ const AngularWorkflow = (props) => { return null } - console.log("APP: ", app) return( ) diff --git a/frontend/src/views/AppCreator.jsx b/frontend/src/views/AppCreator.jsx index bc5128e7..f23d42ba 100644 --- a/frontend/src/views/AppCreator.jsx +++ b/frontend/src/views/AppCreator.jsx @@ -195,7 +195,7 @@ const AppCreator = (props) => { const alert = useAlert() var upload = "" - const increaseAmount = 30 + const increaseAmount = 50 const actionNonBodyRequest = ["GET", "HEAD", "DELETE", "CONNECT"] const actionBodyRequest = ["POST", "PUT", "PATCH",] const authenticationOptions = ["No authentication", "API key", "Bearer auth", "Basic auth", ] @@ -1230,6 +1230,11 @@ const AppCreator = (props) => { newAction.errors.push("Can't have the same name") actions.push(newAction) + + if (actions.length > actionAmount) { + setActionAmount(actions.length) + } + setActions(actions) setUpdate(Math.random()) } @@ -1539,6 +1544,11 @@ const AppCreator = (props) => { actions[actionIndex] = currentAction } + + if (actions.length > actionAmount) { + setActionAmount(actions.length) + } + setActions(actions) } @@ -1973,6 +1983,7 @@ const AppCreator = (props) => { setUrlPathQueries([]) setUrlPath("") setFileUploadEnabled(false) + }}> Submit @@ -2053,8 +2064,10 @@ const AppCreator = (props) => { setCurrentActionMethod(actionNonBodyRequest[0]) setActionsModalOpen(true) }}>New action + {/* + {actionAmount} {actions.length} {actionAmount > 0 && actionAmount < actions.length ? null : - } + */} @@ -2136,7 +2150,7 @@ const AppCreator = (props) => {

- {name} + {name} ({actions === null || actions === undefined ? 0 : actions.length})

diff --git a/frontend/src/views/Apps.jsx b/frontend/src/views/Apps.jsx index 9d6263e8..5ae1ee01 100644 --- a/frontend/src/views/Apps.jsx +++ b/frontend/src/views/Apps.jsx @@ -169,7 +169,7 @@ const Apps = (props) => { function sortByKey(array, key) { if (array === undefined || array === null) { - return [] + return array } return array.sort(function(a, b) { diff --git a/frontend/src/views/Workflows.jsx b/frontend/src/views/Workflows.jsx index 83616e2b..f28ad54a 100644 --- a/frontend/src/views/Workflows.jsx +++ b/frontend/src/views/Workflows.jsx @@ -191,18 +191,21 @@ const Workflows = (props) => { }) .then((response) => { if (response.status !== 200) { - console.log("Status not 200 for workflows :O!") + console.log("Status not 200 for workflows :O!: ", response.status) + alert.info("Failed getting workflows.") + setWorkflowDone(true) + return } return response.json() }) - .then((responseJson) => { + .then((responseJson) => { setSelectedExecution({}) setWorkflowExecutions([]) if (responseJson !== undefined) { setWorkflows(responseJson) - setWorkflowDone(true) + setWorkflowDone(true) } else { if (isLoggedIn) { alert.error("An error occurred while loading workflows") diff --git a/functions/onprem/orborus/orborus.go b/functions/onprem/orborus/orborus.go index f4f7f50a..fbfdf0eb 100644 --- a/functions/onprem/orborus/orborus.go +++ b/functions/onprem/orborus/orborus.go @@ -258,7 +258,7 @@ func initializeImages() { log.Printf("[WARNING] SHUFFLE_APP_SDK_VERSION not defined. Defaulting to %s", appSdkVersion) } if workerVersion == "" { - workerVersion = "0.8.54" + workerVersion = "0.8.56" log.Printf("[WARNING] SHUFFLE_WORKER_VERSION not defined. Defaulting to %s", workerVersion) }