From d6b78612df49b9a415c640d71c53ee13775bb3bf Mon Sep 17 00:00:00 2001 From: satti-hari-krishna-reddy Date: Tue, 16 Jul 2024 20:27:09 +0530 Subject: [PATCH] making enable / disable button to work only when connected to the siem --- frontend/src/views/Detection.jsx | 100 ++----------- frontend/src/views/DetectionDashboard.jsx | 174 ++++++++++++++-------- frontend/src/views/RuleCard.jsx | 78 +++++----- 3 files changed, 164 insertions(+), 188 deletions(-) diff --git a/frontend/src/views/Detection.jsx b/frontend/src/views/Detection.jsx index 3f909758..c86eeba2 100644 --- a/frontend/src/views/Detection.jsx +++ b/frontend/src/views/Detection.jsx @@ -1,4 +1,4 @@ -import React, { useState, useRef } from "react"; +import React, { useState } from "react"; import { Container, Box, @@ -7,12 +7,16 @@ import { Typography, Button, } from "@mui/material"; -import { Publish as PublishIcon } from "@mui/icons-material"; import { toast } from "react-toastify"; import RuleCard from "./RuleCard"; import CircularProgress from "@material-ui/core/CircularProgress"; -const handleDirectoryChange = (folderDisabled, setFolderDisabled, globalUrl) => { +const handleDirectoryChange = (folderDisabled, setFolderDisabled, globalUrl, isTenzirActive) => { + + if (!isTenzirActive) { + toast("connect to siem first for global enable/disable to work"); + return; + } const action = folderDisabled ? "enable_folder" : "disable_folder"; const url = `${globalUrl}/api/v1/files/detection/${action}`; @@ -44,94 +48,11 @@ const Detection = ({ ruleInfo, folderDisabled, setFolderDisabled, - openEditBar, isTenzirActive, }) => { const [searchQuery, setSearchQuery] = useState(""); - const uploadRef = useRef(null); const [loading, setLoading] = useState(false); - const uploadFiles = (files) => { - for (const key in files) { - try { - const filename = files[key].name; - const filedata = new FormData(); - filedata.append("shuffle_file", files[key]); - - if (typeof files[key] === "object") { - handleCreateFile(filename, filedata); - } - } catch (e) { - console.log("Error in dropzone: ", e); - } - } - - setTimeout(() => { - // Additional logic if needed - }, 2500); - }; - - const handleCreateFile = (filename, file) => { - const data = { - filename: filename, - org_id: "default", - workflow_id: "global", - namespace: "sigma", - }; - - fetch(globalUrl + "/api/v1/files/create", { - method: "POST", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", - body: JSON.stringify(data), - }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for apps :O!"); - return; - } - - return response.json(); - }) - .then((responseJson) => { - if (responseJson.success === true) { - handleFileUpload(responseJson.id, file); - } else { - toast("Failed to upload file ", filename); - } - }) - .catch((error) => { - toast("Failed to upload file ", filename); - console.log(error.toString()); - }); - }; - - const handleFileUpload = (file_id, file) => { - fetch(`${globalUrl}/api/v1/files/${file_id}/upload`, { - method: "POST", - credentials: "include", - body: file, - }) - .then((response) => { - if (response.status !== 200 && response.status !== 201) { - console.log("Status not 200 for apps :O!"); - toast("File was created, but failed to upload."); - return; - } - - return response.json(); - }) - .then((responseJson) => { - // Handle the response as needed - }) - .catch((error) => { - toast(error.toString()); - }); - }; - const handleConnectClick = () => { if (!isTenzirActive) { setLoading(true); @@ -150,7 +71,7 @@ const Detection = ({ setTimeout(() => { setLoading(false); window.location.reload(); - }, 5000); + }, 15000); } else { setLoading(false); toast("Failed to connect to SIEM"); @@ -240,8 +161,9 @@ const Detection = ({ - handleDirectoryChange(folderDisabled, setFolderDisabled, globalUrl) + handleDirectoryChange(folderDisabled, setFolderDisabled, globalUrl, isTenzirActive) } + disabled={!isTenzirActive} /> @@ -263,7 +185,7 @@ const Detection = ({ file_id={card.file_id} globalUrl={globalUrl} folderDisabled={folderDisabled} - openEditBar={() => openEditBar(card)} + isTenzirActive={isTenzirActive} {...card} /> ))} diff --git a/frontend/src/views/DetectionDashboard.jsx b/frontend/src/views/DetectionDashboard.jsx index e09814e4..4b2b1b06 100644 --- a/frontend/src/views/DetectionDashboard.jsx +++ b/frontend/src/views/DetectionDashboard.jsx @@ -1,68 +1,45 @@ import React, { useState, useEffect } from "react"; -import { Container} from "@mui/material"; +import { Container, CircularProgress, Typography } from "@mui/material"; import { toast } from "react-toastify"; import Detection from "./Detection"; -import EditComponent from "./EditRules"; - -const getSigmaInfo = (globalUrl, setRuleInfo, setFolderDisabled, setIsTenzirActive) => { - const url = globalUrl + "/api/v1/files/detection/sigma_rules"; - - fetch(url, { - method: "GET", - credentials: "include", - headers: { - "Content-Type": "application/json", - }, - }) - .then((response) => - response.json().then((responseJson) => { - if (responseJson["success"] === false) { - toast("Failed to get sigma rules"); - } else { - setRuleInfo(responseJson.sigma_info); - setFolderDisabled(responseJson.folder_disabled); - setIsTenzirActive(responseJson.is_tenzir_active); - - } - }) - ) - .catch((error) => { - console.log("Error in getting sigma files: ", error); - toast("An error occurred while fetching sigma rules"); - }); -}; const DetectionDashBoard = (props) => { const { globalUrl } = props; - const [ruleInfo, setRuleInfo] = useState([]); - const [selectedRule, setSelectedRule] = useState(null); - const [fileData, setFileData] = React.useState(""); - const [isTenzirActive, setIsTenzirActive] = React.useState(false); - + const [ruleInfo, setRuleInfo] = useState(null); + const [, setSelectedRule] = useState(null); + const [, setFileData] = useState(""); + const [isTenzirActive, setIsTenzirActive] = useState(false); const [folderDisabled, setFolderDisabled] = useState(false); + const [isLoading, setIsLoading] = useState(false); + const [importAttempts, setImportAttempts] = useState(0); + const maxImportAttempts = 2; useEffect(() => { - getSigmaInfo(globalUrl, setRuleInfo, setFolderDisabled, setIsTenzirActive); - }, [folderDisabled]); + const fetchTimeout = setTimeout(() => { + fetchSigmaInfo(); + }, 1000); // Delay by 1 second + + return () => clearTimeout(fetchTimeout); + }, [globalUrl]); useEffect(() => { - if (ruleInfo?.length > 0) { - openEditBar(ruleInfo[0]); + if (ruleInfo && ruleInfo.length === 0 && importAttempts < maxImportAttempts) { + importSigmaFromUrl(); } }, [ruleInfo]); const openEditBar = (rule) => { setSelectedRule(rule); - getFileContent(rule.file_id) + fetchFileContent(rule.file_id); }; const handleSave = (updatedContent) => { - toast("this will be saved"); + toast("This will be saved"); }; - const getFileContent = (file_id) => { + const fetchFileContent = (file_id) => { setFileData(""); - fetch(globalUrl + "/api/v1/files/" + file_id + "/content", { + fetch(`${globalUrl}/api/v1/files/${file_id}/content`, { method: "GET", headers: { "Content-Type": "application/json", @@ -77,38 +54,109 @@ const DetectionDashBoard = (props) => { } return response.text(); }) - .then((respdata) => { + .then((respdata) => { if (respdata.length === 0) { toast("Failed getting file. Is it deleted?"); return; } - return respdata - }) - .then((responseData) => { - - setFileData(responseData); + setFileData(respdata); }) .catch((error) => { toast(error.toString()); }); }; + const fetchSigmaInfo = () => { + const url = `${globalUrl}/api/v1/files/detection/sigma_rules`; + setIsLoading(true); + + fetch(url, { + method: "GET", + credentials: "include", + headers: { + "Content-Type": "application/json", + }, + }) + .then((response) => response.json()) + .then((responseJson) => { + if (responseJson["success"] === false) { + toast("Failed to get sigma rules"); + } else { + setRuleInfo(responseJson.sigma_info || []); + setFolderDisabled(responseJson.folder_disabled); + setIsTenzirActive(responseJson.is_tenzir_active); + } + setIsLoading(false); + }) + .catch((error) => { + setIsLoading(false); + console.log("Error in getting sigma files: ", error); + toast("An error occurred while fetching sigma rules"); + setRuleInfo([]); + }); + }; + + const importSigmaFromUrl = () => { + setIsLoading(true); + setImportAttempts((prevAttempts) => prevAttempts + 1); + + const url = "https://github.com/satti-hari-krishna-reddy/shuffle_sigma"; + const folder = "sigma"; + + const parsedData = { + url: url, + path: folder, + field_3: "main", + }; + + toast(`Getting files from url ${url}. This may take a while if the repository is large. Please wait...`); + fetch(`${globalUrl}/api/v2/files/download_remote`, { + method: "POST", + mode: "cors", + headers: { + Accept: "application/json", + }, + body: JSON.stringify(parsedData), + credentials: "include", + }) + .then((response) => response.json()) + .then((responseJson) => { + if (responseJson.success) { + toast("Successfully loaded files from " + url); + fetchSigmaInfo(); // Fetch again after successful import + } else { + toast(responseJson.reason ? `Failed loading: ${responseJson.reason}` : "Failed loading"); + } + setIsLoading(false); + }) + .catch((error) => { + toast(error.toString()); + setIsLoading(false); + }); + }; + + if (isLoading && (!ruleInfo || ruleInfo.length === 0)) { + return ( + +
+ + Downloading rules, please wait... +
+
+ ); + } + return ( - - {/* {selectedRule ? ( - - ) : null} */} - + + - ); + ); }; export default DetectionDashBoard; diff --git a/frontend/src/views/RuleCard.jsx b/frontend/src/views/RuleCard.jsx index fe334f85..b35d993a 100644 --- a/frontend/src/views/RuleCard.jsx +++ b/frontend/src/views/RuleCard.jsx @@ -10,7 +10,7 @@ import EditIcon from "@mui/icons-material/Edit"; import { toast } from "react-toastify"; import ShuffleCodeEditor from "../components/ShuffleCodeEditor1.jsx"; -const RuleCard = ({ ruleName, description, file_id, globalUrl, folderDisabled, ...otherProps }) => { +const RuleCard = ({ ruleName, description, file_id, globalUrl, folderDisabled, isTenzirActive, ...otherProps }) => { const [openCodeEditor, setOpenCodeEditor] = React.useState(false); const [fileData, setFileData] = React.useState(""); const [isEnabled, setIsEnabled] = React.useState(otherProps.is_enabled); @@ -22,6 +22,10 @@ const RuleCard = ({ ruleName, description, file_id, globalUrl, folderDisabled, . toast("enable the directory to enable individual rules"); return; } + if (!isTenzirActive) { + toast("connect to the siem to enable/disable the rule"); + return; + } const newIsEnabled = event.target.checked; toggleRule(file_id, !newIsEnabled, globalUrl, () => { setIsEnabled(newIsEnabled); @@ -73,6 +77,7 @@ const RuleCard = ({ ruleName, description, file_id, globalUrl, folderDisabled, . @@ -121,42 +126,43 @@ const toggleRule = (fileId, isCurrentlyEnabled, globalUrl, callback) => { toast(`An error occurred while ${action}ing the rule`); }); }; - const openEditBar = (file_id, setOpenCodeEditor, setFileData, globalUrl) => { - getFileContent(file_id, setFileData, globalUrl); + +const openEditBar = (file_id, setOpenCodeEditor, setFileData, globalUrl) => { + getFileContent(file_id, setFileData, globalUrl) + setOpenCodeEditor(true); - }; +}; - const getFileContent = (file_id, setFileData, globalUrl) => { - setFileData(""); - fetch(globalUrl + "/api/v1/files/" + file_id + "/content", { - method: "GET", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", +const getFileContent = (file_id, setFileData, globalUrl) => { + setFileData(""); + fetch(globalUrl + "/api/v1/files/" + file_id + "/content", { + method: "GET", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for file :O!"); + return ""; + } + return response.text(); }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for file :O!"); - return ""; - } - return response.text(); - }) - .then((respdata) => { - if (respdata.length === 0) { - toast("Failed getting file. Is it deleted?"); - return; - } - return respdata - }) - .then((responseData) => { - - setFileData(responseData); - }) - .catch((error) => { - toast(error.toString()); - }); - }; - + .then((respdata) => { + if (respdata.length === 0) { + toast("Failed getting file. Is it deleted?"); + return; + } + return respdata + }) + .then((responseData) => { + + setFileData(responseData); + }) + .catch((error) => { + toast(error.toString()); + }); +}; export default RuleCard;