diff --git a/.env b/.env
index 687fcf58..33c6c318 100644
--- a/.env
+++ b/.env
@@ -55,7 +55,7 @@ SHUFFLE_ORBORUS_STARTUP_DELAY= # Used for setting up a startup delay for Orbor
SHUFFLE_BASE_IMAGE_NAME=shuffle
SHUFFLE_BASE_IMAGE_REGISTRY=ghcr.io
-SHUFFLE_BASE_IMAGE_TAG_SUFFIX="-1.0.0"
+SHUFFLE_BASE_IMAGE_TAG_SUFFIX="-1.1.0"
# Used for auto-cleanup of containers. REALLY important at scale.
SHUFFLE_CONTAINER_AUTO_CLEANUP=false
diff --git a/frontend/src/components/AppGrid.jsx b/frontend/src/components/AppGrid.jsx
index 562146c0..690d7cb4 100644
--- a/frontend/src/components/AppGrid.jsx
+++ b/frontend/src/components/AppGrid.jsx
@@ -1,6 +1,6 @@
import React, {useEffect, useState} from 'react';
-import ReactGA from 'react-ga';
+import ReactGA from 'react-ga4';
import { useTheme } from '@material-ui/core/styles';
import {Link} from 'react-router-dom';
diff --git a/frontend/src/components/Appsearch.jsx b/frontend/src/components/Appsearch.jsx
index 9f219722..9da69a70 100644
--- a/frontend/src/components/Appsearch.jsx
+++ b/frontend/src/components/Appsearch.jsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react';
-import ReactGA from 'react-ga';
+import ReactGA from 'react-ga4';
import { useTheme } from '@material-ui/core/styles';
import {Link} from 'react-router-dom';
import { useAlert } from "react-alert";
diff --git a/frontend/src/components/CreatorGrid.jsx b/frontend/src/components/CreatorGrid.jsx
index f09f84a0..584e0f6e 100644
--- a/frontend/src/components/CreatorGrid.jsx
+++ b/frontend/src/components/CreatorGrid.jsx
@@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react';
-import ReactGA from 'react-ga';
+import ReactGA from 'react-ga4';
import { useTheme } from '@material-ui/core/styles';
import {Link} from 'react-router-dom';
diff --git a/frontend/src/components/DocsGrid.jsx b/frontend/src/components/DocsGrid.jsx
index 706c861a..ea20cd0e 100644
--- a/frontend/src/components/DocsGrid.jsx
+++ b/frontend/src/components/DocsGrid.jsx
@@ -1,6 +1,6 @@
import React, {useEffect, useState} from 'react';
-import ReactGA from 'react-ga';
+import ReactGA from 'react-ga4';
import { useTheme } from '@material-ui/core/styles';
import {Link} from 'react-router-dom';
diff --git a/frontend/src/components/Searchfield.jsx b/frontend/src/components/Searchfield.jsx
index 43fa7934..f1e3aa77 100644
--- a/frontend/src/components/Searchfield.jsx
+++ b/frontend/src/components/Searchfield.jsx
@@ -625,7 +625,7 @@ const SearchField = props => {
const CustomDocHits = connectHits(DocHits)
return (
-
+
{
console.log("CLICKED")
}}>
diff --git a/frontend/src/components/SecurityFramework.jsx b/frontend/src/components/SecurityFramework.jsx
index 7139f7a6..9e3a7b90 100644
--- a/frontend/src/components/SecurityFramework.jsx
+++ b/frontend/src/components/SecurityFramework.jsx
@@ -2,7 +2,7 @@ import React, {useState } from 'react';
import {isMobile} from "react-device-detect";
import AppFramework, { usecases } from "../components/AppFramework.jsx";
import {Link} from 'react-router-dom';
-import ReactGA from 'react-ga';
+import ReactGA from 'react-ga4';
import { Button, LinearProgress, Typography } from '@material-ui/core';
diff --git a/frontend/src/components/SuggestedWorkflows.jsx b/frontend/src/components/SuggestedWorkflows.jsx
index 69349846..6bbc15e7 100644
--- a/frontend/src/components/SuggestedWorkflows.jsx
+++ b/frontend/src/components/SuggestedWorkflows.jsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react';
-import ReactGA from 'react-ga';
+import ReactGA from 'react-ga4';
import theme from '../theme';
import PaperComponent from "../components/PaperComponent.jsx"
import UsecaseSearch, { usecaseTypes } from "../components/UsecaseSearch.jsx"
diff --git a/frontend/src/components/WelcomeForm2.jsx b/frontend/src/components/WelcomeForm2.jsx
index 79a89f06..f78f65aa 100644
--- a/frontend/src/components/WelcomeForm2.jsx
+++ b/frontend/src/components/WelcomeForm2.jsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react";
-import ReactGA from 'react-ga';
+import ReactGA from 'react-ga4';
import Button from "@material-ui/core/Button";
import Checkbox from '@mui/material/Checkbox';
diff --git a/frontend/src/components/Workflowsearch.jsx b/frontend/src/components/Workflowsearch.jsx
index 73539521..152fdd83 100644
--- a/frontend/src/components/Workflowsearch.jsx
+++ b/frontend/src/components/Workflowsearch.jsx
@@ -1,6 +1,5 @@
import React, { useState, useEffect } from 'react';
-import ReactGA from 'react-ga';
import { useTheme } from '@material-ui/core/styles';
import {Link} from 'react-router-dom';
@@ -159,25 +158,10 @@ const WorkflowSearch = props => {
return (
{
setMouseHoverIndex(index)
- /*
- ReactGA.event({
- category: "app_grid_view",
- action: `search_bar_click`,
- label: "",
- })
- */
}} onMouseOut={() => {
setMouseHoverIndex(-1)
}} onClick={() => {
setNewSelectedApp(data)
- //if (data.objectID !== data.objectID) {
- //}
-
- //ReactGA.event({
- // category: "app_search",
- // action: `app_${parsedname}_${data.id}_click`,
- // label: "",
- //})
}}>
{/*

*/}
diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx
index a821a0f3..f07c8497 100644
--- a/frontend/src/views/AngularWorkflow.jsx
+++ b/frontend/src/views/AngularWorkflow.jsx
@@ -415,7 +415,7 @@ const AngularWorkflow = (defaultprops) => {
// Set it from 2500 to 6000 to reduce overall load
const { start, stop } = useInterval({
duration: 3000,
- startImmediate: true,
+ startImmediate: false,
callback: () => {
fetchUpdates();
},
@@ -981,6 +981,9 @@ const AngularWorkflow = (defaultprops) => {
// Controls the colors and direction of execution results.
// Style is in defaultCytoscapeStyle.js
const handleUpdateResults = (responseJson, executionRequest) => {
+ if (responseJson === undefined || responseJson === null || responseJson.success === false) {
+ return
+ }
//console.log(responseJson)
// Loop nodes and find results
// Update on every interval? idk
@@ -2952,10 +2955,19 @@ const AngularWorkflow = (defaultprops) => {
getSettings();
} else if (data.app_name === "Webhook") {
if (workflow.triggers[trigger_index].parameters !== undefined && workflow.triggers[trigger_index].parameters !== null && workflow.triggers[trigger_index].parameters.length > 0) {
+ console.log("Can set params here!")
workflow.triggers[trigger_index].parameters[0] = {
name: "url",
value: referenceUrl + "webhook_" + workflow.triggers[trigger_index].id,
};
+
+ if (workflow.triggers[trigger_index].parameters.length < 5) {
+ console.log("Adding to webhook params!")
+ workflow.triggers[trigger_index].parameters.push({
+ name: "await_response",
+ value: "v1,"
+ })
+ }
}
}
@@ -10538,7 +10550,7 @@ const AngularWorkflow = (defaultprops) => {
}}
fullWidth
multiline
- rows="4"
+ rows="2"
defaultValue={trigger_header_auth}
color="primary"
disabled={selectedTrigger.status === "running"}
@@ -10557,7 +10569,44 @@ const AngularWorkflow = (defaultprops) => {
}}
/>
-
+ {isCloud && workflow.triggers[selectedTriggerIndex].parameters.length > 4 ?
+
+ {
+ if (selectedTrigger.parameters === null) {
+ selectedTrigger.parameters = [];
+ }
+
+ // Sets the webhook to run as version 2.. kinda
+ var value = "v2"
+ if (workflow.triggers[selectedTriggerIndex].parameters[4].value.includes("v2")) {
+ value = "v1"
+ }
+
+ workflow.triggers[selectedTriggerIndex].parameters[4] = {
+ name: "await_response",
+ value: value
+ }
+
+ setWorkflow(workflow)
+ setUpdate(Math.random())
+ }}
+ color="primary"
+ value="await_response"
+ />
+ }
+ label={Wait For Response
}
+ />
+
+ : null}
+
);
@@ -10707,12 +10756,7 @@ const AngularWorkflow = (defaultprops) => {
const branch = workflow.branches.find(
(branch) => branch.source_id === trigger.id
);
- if (
- branch === undefined &&
- (workflow.start === undefined ||
- workflow.start === null ||
- workflow.start.length === 0)
- ) {
+ if (branch === undefined && (workflow.start === undefined || workflow.start === null || workflow.start.length === 0)) {
alert.error("No webhook node defined");
}
@@ -10721,14 +10765,20 @@ const AngularWorkflow = (defaultprops) => {
startNode = branch.destination_id;
}
- const param = trigger.parameters.find(
- (param) => param.name === "auth_headers"
- );
+ const param = trigger.parameters.find((param) => param.name === "auth_headers");
var auth = "";
if (param !== undefined && param !== null) {
auth = param.value;
}
+
+ // Version: v2 = await response for 30 sec
+ const await_resp = trigger.parameters.find((param) => param.name === "await_response");
+ var version = "";
+ if (await_resp !== undefined && await_resp !== null) {
+ version = await_resp.value;
+ }
+
const customRespParam = trigger.parameters.find(
(param) => param.name === "custom_response_body"
)
@@ -10737,7 +10787,6 @@ const AngularWorkflow = (defaultprops) => {
custom_response = customRespParam.value;
}
- console.log("TRIG: ", trigger);
const data = {
name: hookname,
type: "webhook",
@@ -10747,8 +10796,12 @@ const AngularWorkflow = (defaultprops) => {
environment: trigger.environment,
auth: auth,
custom_response: custom_response,
+ version: version,
+ version_timeout: 15,
};
+ console.log("Trigger data: ", data)
+
fetch(globalUrl + "/api/v1/hooks/new", {
method: "POST",
headers: { "content-type": "application/json" },
diff --git a/frontend/src/views/AppCreator.jsx b/frontend/src/views/AppCreator.jsx
index 44b2f271..5719b39f 100644
--- a/frontend/src/views/AppCreator.jsx
+++ b/frontend/src/views/AppCreator.jsx
@@ -222,6 +222,55 @@ const parseCurl = (s) => {
return out;
};
+export const appCategories = [
+ {
+ "name": "Communication",
+ "color": "#FFC107",
+ "icon": "communication",
+ "action_labels": ["List Messages", "Send Message",],
+ }, {
+ "name": "SIEM",
+ "color": "#FFC107",
+ "icon": "siem",
+ "action_labels": ["Get alerts", "Search", "Create detection",],
+ }, {
+ "name": "Eradication",
+ "color": "#FFC107",
+ "icon": "eradication",
+ "action_labels": ["List tickets", "Update ticket", "Block hash", "Isolate host"],
+ }, {
+ "name": "Cases",
+ "color": "#FFC107",
+ "icon": "cases",
+ "action_labels": ["List tickets", "Get ticket", "Create ticket", "Update ticket",],
+ }, {
+ "name": "Assets",
+ "color": "#FFC107",
+ "icon": "assets",
+ "action_labels": [],
+ }, {
+ "name": "Intel",
+ "color": "#FFC107",
+ "icon": "intel",
+ "action_labels": [],
+ }, {
+ "name": "IAM",
+ "color": "#FFC107",
+ "icon": "iam",
+ "action_labels": [],
+ }, {
+ "name": "Network",
+ "color": "#FFC107",
+ "icon": "network",
+ "action_labels": ["Block IP",],
+ }, {
+ "name": "Other",
+ "color": "#FFC107",
+ "icon": "other",
+ "action_labels": [],
+ },
+]
+
export const base64_decode = (str) => {
return decodeURIComponent(
atob(str).split("").map(function (c) {
@@ -310,81 +359,8 @@ const AppCreator = (defaultprops) => {
// From 2023: Example to handle action labels
// Goal: Make this dynamically load from the backend
// and make categories + labels modifyable.
- //
// Categories are the main categories in the App Framework
- const [categories, setCategories] = useState([
- {
- "name": "Communication",
- "color": "#FFC107",
- "icon": "communication",
- "action_labels": [],
- }, {
- "name": "SIEM",
- "color": "#FFC107",
- "icon": "siem",
- "action_labels": ["Get alerts", "Search", "Create detection",],
- }, {
- "name": "Eradication",
- "color": "#FFC107",
- "icon": "eradication",
- "action_labels": ["List tickets", "Update ticket", "Block hash", "Isolate host"],
- }, {
- "name": "Cases",
- "color": "#FFC107",
- "icon": "cases",
- "action_labels": ["List tickets", "Get ticket", "Create ticket", "Update ticket",],
- }, {
- "name": "Assets",
- "color": "#FFC107",
- "icon": "assets",
- "action_labels": [],
- }, {
- "name": "Intel",
- "color": "#FFC107",
- "icon": "intel",
- "action_labels": [],
- }, {
- "name": "IAM",
- "color": "#FFC107",
- "icon": "iam",
- "action_labels": [],
- }, {
- "name": "Network",
- "color": "#FFC107",
- "icon": "network",
- "action_labels": ["Block IP",],
- }, {
- "name": "Other",
- "color": "#FFC107",
- "icon": "other",
- "action_labels": [],
- }
- ]);
-
- //const [actions, setActions] = useState([{
- // "name": "Get workflows",
- // "description": "Get workflows",
- // "url": "/workflows",
- // "headers": "",
- // "queries": [],
- // "paths": [],
- // "body": "",
- // "errors": ["wutface", "WOAH"],
- // "method": actionNonBodyRequest[0],
- //}, {
- // "name": "Get workflow",
- // "description": "Get workflow",
- // "url": "/workflows/{id}",
- // "headers": "",
- // "queries": [],
- // "paths": ["id"],
- // "body": "",
- // "errors": ["wutface", "WOAH"],
- // "method": actionNonBodyRequest[0],
- //},
- //
- //])
-
+ const [categories, setCategories] = useState(appCategories)
const [currentActionMethod, setCurrentActionMethod] = useState(
actionNonBodyRequest[0]
)
diff --git a/frontend/src/views/GettingStarted.jsx b/frontend/src/views/GettingStarted.jsx
index b42bddef..87dd1be0 100644
--- a/frontend/src/views/GettingStarted.jsx
+++ b/frontend/src/views/GettingStarted.jsx
@@ -2,7 +2,7 @@ import React, { useEffect, useContext } from "react";
import { makeStyles } from "@material-ui/core/styles";
import { useTheme } from "@material-ui/core/styles";
-import ReactGA from 'react-ga';
+import ReactGA from 'react-ga4';
import SecurityFramework from '../components/SecurityFramework.jsx';
import {
diff --git a/frontend/src/views/Welcome.jsx b/frontend/src/views/Welcome.jsx
index ab80c18e..06c6352f 100644
--- a/frontend/src/views/Welcome.jsx
+++ b/frontend/src/views/Welcome.jsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react';
-import ReactGA from 'react-ga';
+import ReactGA from 'react-ga4';
import WelcomeForm2 from "../components/WelcomeForm2.jsx";
import Stepper from "@material-ui/core/Stepper";
import Step from "@material-ui/core/Step";
diff --git a/frontend/src/views/Workflows.jsx b/frontend/src/views/Workflows.jsx
index 4d8adb23..5de0e799 100644
--- a/frontend/src/views/Workflows.jsx
+++ b/frontend/src/views/Workflows.jsx
@@ -551,7 +551,6 @@ const Workflows = (props) => {
const [deleteModalOpen, setDeleteModalOpen] = React.useState(false);
const [publishModalOpen, setPublishModalOpen] = React.useState(false);
const [editingWorkflow, setEditingWorkflow] = React.useState({});
- const [importLoading, setImportLoading] = React.useState(false);
const [isDropzone, setIsDropzone] = React.useState(false);
const [view, setView] = React.useState("grid");
const [filters, setFilters] = React.useState([]);
@@ -585,10 +584,10 @@ const Workflows = (props) => {
}
setGettingStartedItems(activeFiltered)
- const doneFiltered = activeFiltered.filter((item) => item.done === true)
- if (doneFiltered.length > 0) {
- console.log("DONE: ", doneFiltered)
- }
+ //const doneFiltered = activeFiltered.filter((item) => item.done === true)
+ //if (doneFiltered.length > 0) {
+ // console.log("DONE: ", doneFiltered)
+ //}
const sidebar = localStorage.getItem(sidebarKey);
if (sidebar === null || sidebar === undefined) {
@@ -597,13 +596,10 @@ const Workflows = (props) => {
localStorage.setItem(sidebarKey, "open");
setDrawerOpen(true)
} else {
- console.log("Got sidebar: ", sidebar)
-
if (sidebar === "open") {
console.log("OPEN the thingy!")
setDrawerOpen(true)
} else {
- console.log("Close the thingy!")
setDrawerOpen(false)
}
}
@@ -1229,7 +1225,6 @@ const Workflows = (props) => {
display: "flex",
flexWrap: "wrap",
alignContent: "space-between",
- marginTop: 5,
};
const paperAppStyle = {
@@ -2212,7 +2207,7 @@ const Workflows = (props) => {
setTimeout(() => {
getAvailableWorkflows();
}, 2500);
- setImportLoading(false);
+ setSubmitLoading(false)
setModalOpen(false);
} else {
//alert.info("Successfully changed basic info for workflow");
@@ -2223,7 +2218,7 @@ const Workflows = (props) => {
})
.catch((error) => {
alert.error(error.toString());
- setImportLoading(false);
+ setSubmitLoading(false)
setModalOpen(false);
setSubmitLoading(false);
});
@@ -2231,8 +2226,8 @@ const Workflows = (props) => {
const importFiles = (event) => {
console.log("Importing!");
+ setSubmitLoading(true)
- setImportLoading(true);
if (event.target.files.length > 0) {
console.log("Files: !", event.target.files.length);
for (var key in event.target.files) {
@@ -2240,7 +2235,7 @@ const Workflows = (props) => {
if (file.type !== "application/json") {
if (file.type !== undefined) {
alert.error("File has to contain valid json");
- setImportLoading(false);
+ setSubmitLoading(false)
}
continue;
@@ -2254,7 +2249,7 @@ const Workflows = (props) => {
data = JSON.parse(reader.result);
} catch (e) {
alert.error("Invalid JSON: " + e);
- setImportLoading(false);
+ setSubmitLoading(false)
return;
}
@@ -2981,20 +2976,15 @@ const Workflows = (props) => {
)}
- {importLoading ? (
-
- ) : (
-
- )}
+
{
}}
*/}
-
+
{!isMobile && usecases !== null && usecases !== undefined && usecases.length > 0 ?
: null}
-
+
+
{!isMobile &&
actionImageList !== undefined &&
actionImageList !== null &&
@@ -3435,44 +3426,48 @@ const Workflows = (props) => {
})}
) : null}
- {view === "grid" ? (
-
-
-
-
- {filteredWorkflows.map((data, index) => {
- // Shouldn't be a part of this list
- if (data.public === true) {
- return null
- }
- if (firstLoad) {
- workflowDelay += 75
- } else {
+
+ {view === "grid" ? (
+
+
+
+
+
+ {filteredWorkflows.map((data, index) => {
+ // Shouldn't be a part of this list
+ if (data.public === true) {
+ return null
+ }
+
+ if (firstLoad) {
+ workflowDelay += 75
+ } else {
+ return (
+
+
+
+ )
+ }
+
return (
-
-
-
+
+
+
+
+
)
- }
+ })}
+
+ ) : (
+
+ )}
+
- return (
-
-
-
-
-
- )
- })}
-
- ) : (
-
- )}
-
-
-
-
+
+
+
);
};
diff --git a/functions/onprem/orborus/orborus.go b/functions/onprem/orborus/orborus.go
index 9c5b9b69..8d1233a8 100644
--- a/functions/onprem/orborus/orborus.go
+++ b/functions/onprem/orborus/orborus.go
@@ -65,7 +65,8 @@ var newWorkerImage = os.Getenv("SHUFFLE_WORKER_IMAGE")
// var baseimagename = "shuffle/shuffle"
var baseimagename = os.Getenv("SHUFFLE_BASE_IMAGE_NAME")
var baseimageregistry = os.Getenv("SHUFFLE_BASE_IMAGE_REGISTRY")
-var baseimagetagsuffix = os.Getenv("SHUFFLE_BASE_IMAGE_TAG_SUFFIX")
+
+//var baseimagetagsuffix = os.Getenv("SHUFFLE_BASE_IMAGE_TAG_SUFFIX")
// Used for cloud with auth
var auth = os.Getenv("AUTH")