Sync + Added dashboard for stats API
This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import {
|
||||
Button,
|
||||
ButtonGroup,
|
||||
CircularProgress,
|
||||
Tooltip,
|
||||
} from "@mui/material";
|
||||
|
||||
import {
|
||||
Check as CheckIcon,
|
||||
OpenInNew as OpenInNewIcon,
|
||||
} from "@mui/icons-material";
|
||||
import { green, yellow, red } from '../views/AngularWorkflow.jsx'
|
||||
|
||||
const RunDetectionTest = (props) => {
|
||||
const {
|
||||
globalUrl,
|
||||
pipelines,
|
||||
workflows,
|
||||
ticketWebhook,
|
||||
detectionWorkflowId,
|
||||
|
||||
changePipelineState,
|
||||
submitPipelineWrapper,
|
||||
} = props
|
||||
|
||||
const [executions, setExecutions] = React.useState([]);
|
||||
const [detectionTestRunning, setDetectionTestRunning] = React.useState(false);
|
||||
const [detectionTestExecutionId, setDetectionTestExecutionId] = React.useState("");
|
||||
|
||||
useEffect(() => {
|
||||
if (detectionWorkflowId !== "") {
|
||||
handleLoadExecutions(detectionWorkflowId)
|
||||
}
|
||||
}, [detectionWorkflowId])
|
||||
|
||||
if (workflows === undefined || workflows === null || workflows.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
const handleLoadExecutions = (workflowId, detectionTestRunning) => {
|
||||
const url = `${globalUrl}/api/v2/workflows/${workflowId}/executions`
|
||||
|
||||
fetch(url, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
}).then((response) => {
|
||||
if (response.status !== 200) {
|
||||
console.log("Status not 200 for getting all executions");
|
||||
}
|
||||
|
||||
return response.json();
|
||||
})
|
||||
.then((responseJson) => {
|
||||
if (responseJson.success !== false && responseJson?.executions?.length > 0) {
|
||||
if (detectionTestRunning === true) {
|
||||
console.log("Checking executions in workflow: ", workflowId, responseJson.executions)
|
||||
for (var executionKey in responseJson.executions) {
|
||||
const curExec = responseJson.executions[executionKey]
|
||||
|
||||
if (curExec.execution_id === detectionTestExecutionId) {
|
||||
continue
|
||||
}
|
||||
|
||||
// started_at = unix timestamp
|
||||
// check within the last 60 seconds
|
||||
const datecomparison = (Date.now() / 1000) - 60
|
||||
if (curExec.started_at >= datecomparison) {
|
||||
if (curExec?.execution_argument?.includes("rule") && curExec?.execution_argument?.includes("Test Notepad Event")) {
|
||||
setDetectionTestRunning(false)
|
||||
setDetectionTestExecutionId(curExec.execution_id)
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setExecutions(responseJson.executions || [])
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
toast(error.toString());
|
||||
})
|
||||
}
|
||||
|
||||
const runDetectionTest = () => {
|
||||
setDetectionTestRunning(true)
|
||||
if (ticketWebhook === "") {
|
||||
setDetectionTestRunning(false)
|
||||
toast.error("No ticketing webhook found. Please enable the ticketing workflow first.")
|
||||
return
|
||||
}
|
||||
|
||||
if (detectionWorkflowId === "") {
|
||||
setDetectionTestRunning(false)
|
||||
toast.error("No ticketing workflow found. Please enable the ticketing workflow first.")
|
||||
return
|
||||
}
|
||||
|
||||
if (haveDetectionPipelines() === false) {
|
||||
setDetectionTestRunning(false)
|
||||
toast.error("No detection pipelines found. Please deploy the Syslog (TCP) & Sigma pipelines first.")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// 1. Run a new pipeline which exits.
|
||||
const detectionTest = `from {message: "<165>1 2025-10-06T12:34:56.789Z myhost.example.com myapp 1234 ID47 [huh eventSource=\\\"App\\\" EventID=\\\"4688\\\" NewProcessName=\\\"notepad.exe\\\" Context=\\\"Testing\\\"] This is a test log message"} | this = message.parse_syslog() | import`
|
||||
|
||||
for (var pipelineKey in pipelines) {
|
||||
const curPipeline = pipelines[pipelineKey]
|
||||
if (curPipeline.definition === detectionTest && changePipelineState !== undefined) {
|
||||
changePipelineState(curPipeline, "stop");
|
||||
}
|
||||
}
|
||||
|
||||
// 1. Submit it to run
|
||||
// 2. Check executions if they happened recently~
|
||||
if (submitPipelineWrapper !== undefined) {
|
||||
submitPipelineWrapper(detectionTest)
|
||||
}
|
||||
|
||||
for (var i = 0; i < 10; i++) {
|
||||
setTimeout(() => {
|
||||
handleLoadExecutions(detectionWorkflowId, true)
|
||||
}, i * 5000)
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
setDetectionTestRunning(false)
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
const haveDetectionPipelines = () => {
|
||||
if (pipelines === undefined) {
|
||||
toast.warn("No pipelines found. Please create the Syslog (TCP) & Sigma pipelines first.")
|
||||
return false
|
||||
}
|
||||
|
||||
var foundCorrect = 0
|
||||
for (var pipelineKey in pipelines) {
|
||||
const curPipeline = pipelines[pipelineKey]
|
||||
//if (curPipeline?.definition?.includes("load_tcp") && curPipeline?.definition?.includes("import")) {
|
||||
// foundCorrect += 1
|
||||
//}
|
||||
|
||||
if (curPipeline?.definition?.includes("sigma") && curPipeline?.definition?.includes("export")) {
|
||||
foundCorrect += 1
|
||||
}
|
||||
}
|
||||
|
||||
if (foundCorrect >= 1) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{display: "flex", }}>
|
||||
<ButtonGroup style={{minWidth: 150, maxWidth: 225,}}>
|
||||
<Tooltip title={"Run a detection test with Sigma rules on your Tenzir Orborus instance. Requires: TCPC Syslog- & Sigma pipeline"} style={{}} aria-label={"Run detection test"}>
|
||||
<div>
|
||||
<Button
|
||||
style={{minWidth: 150, maxWidth: 150, minHeight: 40, maxHeight: 40, }}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
disabled={haveDetectionPipelines() == false || ticketWebhook === "" || detectionWorkflowId === "" || detectionTestRunning}
|
||||
onClick={() => {
|
||||
//setPipelineModalOpen(true)
|
||||
runDetectionTest()
|
||||
}}
|
||||
>
|
||||
{
|
||||
detectionTestRunning === true ? <CircularProgress size={20} style={{marginRight: 10, }} /> : "Run Detection Test"
|
||||
}
|
||||
</Button>
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
||||
{detectionTestRunning === false && detectionTestExecutionId !== "" && detectionTestExecutionId !== undefined ?
|
||||
<Tooltip title={`Go to detection test: ${detectionTestExecutionId}`} style={{}} aria-label={"Go to logs"}>
|
||||
<a href={`/workflows/${detectionWorkflowId}?execution_id=${detectionTestExecutionId}`} target="_blank" rel="noopener noreferrer">
|
||||
<Button
|
||||
color="secondary"
|
||||
style={{
|
||||
minWidth: 75, maxWidth: 75,
|
||||
minHeight: 40, maxHeight: 40,
|
||||
}}
|
||||
>
|
||||
<CheckIcon style={{color: green}}/>
|
||||
</Button>
|
||||
</a>
|
||||
</Tooltip>
|
||||
: null}
|
||||
</ButtonGroup>
|
||||
|
||||
{window?.location?.href?.includes("/detections/") === true ? null :
|
||||
<Tooltip title={"Open Detection Tab"} style={{}} aria-label={""}>
|
||||
<a href={`/detections/sigma`} target="_blank" rel="noopener noreferrer">
|
||||
<OpenInNewIcon
|
||||
color="secondary"
|
||||
style={{
|
||||
marginLeft: 20,
|
||||
top: 8,
|
||||
position: 'relative',
|
||||
}}
|
||||
/>
|
||||
</a>
|
||||
</Tooltip>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default RunDetectionTest
|
||||
Reference in New Issue
Block a user