making enable / disable button to work only when connected to the siem
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useRef } from "react";
|
import React, { useState } from "react";
|
||||||
import {
|
import {
|
||||||
Container,
|
Container,
|
||||||
Box,
|
Box,
|
||||||
@@ -7,12 +7,16 @@ import {
|
|||||||
Typography,
|
Typography,
|
||||||
Button,
|
Button,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { Publish as PublishIcon } from "@mui/icons-material";
|
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import RuleCard from "./RuleCard";
|
import RuleCard from "./RuleCard";
|
||||||
import CircularProgress from "@material-ui/core/CircularProgress";
|
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 action = folderDisabled ? "enable_folder" : "disable_folder";
|
||||||
const url = `${globalUrl}/api/v1/files/detection/${action}`;
|
const url = `${globalUrl}/api/v1/files/detection/${action}`;
|
||||||
|
|
||||||
@@ -44,94 +48,11 @@ const Detection = ({
|
|||||||
ruleInfo,
|
ruleInfo,
|
||||||
folderDisabled,
|
folderDisabled,
|
||||||
setFolderDisabled,
|
setFolderDisabled,
|
||||||
openEditBar,
|
|
||||||
isTenzirActive,
|
isTenzirActive,
|
||||||
}) => {
|
}) => {
|
||||||
const [searchQuery, setSearchQuery] = useState("");
|
const [searchQuery, setSearchQuery] = useState("");
|
||||||
const uploadRef = useRef(null);
|
|
||||||
const [loading, setLoading] = useState(false);
|
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 = () => {
|
const handleConnectClick = () => {
|
||||||
if (!isTenzirActive) {
|
if (!isTenzirActive) {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -150,7 +71,7 @@ const Detection = ({
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}, 5000);
|
}, 15000);
|
||||||
} else {
|
} else {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
toast("Failed to connect to SIEM");
|
toast("Failed to connect to SIEM");
|
||||||
@@ -240,8 +161,9 @@ const Detection = ({
|
|||||||
<Switch
|
<Switch
|
||||||
checked={!folderDisabled}
|
checked={!folderDisabled}
|
||||||
onChange={() =>
|
onChange={() =>
|
||||||
handleDirectoryChange(folderDisabled, setFolderDisabled, globalUrl)
|
handleDirectoryChange(folderDisabled, setFolderDisabled, globalUrl, isTenzirActive)
|
||||||
}
|
}
|
||||||
|
disabled={!isTenzirActive}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -263,7 +185,7 @@ const Detection = ({
|
|||||||
file_id={card.file_id}
|
file_id={card.file_id}
|
||||||
globalUrl={globalUrl}
|
globalUrl={globalUrl}
|
||||||
folderDisabled={folderDisabled}
|
folderDisabled={folderDisabled}
|
||||||
openEditBar={() => openEditBar(card)}
|
isTenzirActive={isTenzirActive}
|
||||||
{...card}
|
{...card}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -1,68 +1,45 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { Container} from "@mui/material";
|
import { Container, CircularProgress, Typography } from "@mui/material";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import Detection from "./Detection";
|
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 DetectionDashBoard = (props) => {
|
||||||
const { globalUrl } = props;
|
const { globalUrl } = props;
|
||||||
const [ruleInfo, setRuleInfo] = useState([]);
|
const [ruleInfo, setRuleInfo] = useState(null);
|
||||||
const [selectedRule, setSelectedRule] = useState(null);
|
const [, setSelectedRule] = useState(null);
|
||||||
const [fileData, setFileData] = React.useState("");
|
const [, setFileData] = useState("");
|
||||||
const [isTenzirActive, setIsTenzirActive] = React.useState(false);
|
const [isTenzirActive, setIsTenzirActive] = useState(false);
|
||||||
|
|
||||||
const [folderDisabled, setFolderDisabled] = useState(false);
|
const [folderDisabled, setFolderDisabled] = useState(false);
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [importAttempts, setImportAttempts] = useState(0);
|
||||||
|
const maxImportAttempts = 2;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getSigmaInfo(globalUrl, setRuleInfo, setFolderDisabled, setIsTenzirActive);
|
const fetchTimeout = setTimeout(() => {
|
||||||
}, [folderDisabled]);
|
fetchSigmaInfo();
|
||||||
|
}, 1000); // Delay by 1 second
|
||||||
|
|
||||||
|
return () => clearTimeout(fetchTimeout);
|
||||||
|
}, [globalUrl]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (ruleInfo?.length > 0) {
|
if (ruleInfo && ruleInfo.length === 0 && importAttempts < maxImportAttempts) {
|
||||||
openEditBar(ruleInfo[0]);
|
importSigmaFromUrl();
|
||||||
}
|
}
|
||||||
}, [ruleInfo]);
|
}, [ruleInfo]);
|
||||||
|
|
||||||
const openEditBar = (rule) => {
|
const openEditBar = (rule) => {
|
||||||
setSelectedRule(rule);
|
setSelectedRule(rule);
|
||||||
getFileContent(rule.file_id)
|
fetchFileContent(rule.file_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSave = (updatedContent) => {
|
const handleSave = (updatedContent) => {
|
||||||
toast("this will be saved");
|
toast("This will be saved");
|
||||||
};
|
};
|
||||||
|
|
||||||
const getFileContent = (file_id) => {
|
const fetchFileContent = (file_id) => {
|
||||||
setFileData("");
|
setFileData("");
|
||||||
fetch(globalUrl + "/api/v1/files/" + file_id + "/content", {
|
fetch(`${globalUrl}/api/v1/files/${file_id}/content`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@@ -77,38 +54,109 @@ const DetectionDashBoard = (props) => {
|
|||||||
}
|
}
|
||||||
return response.text();
|
return response.text();
|
||||||
})
|
})
|
||||||
.then((respdata) => {
|
.then((respdata) => {
|
||||||
if (respdata.length === 0) {
|
if (respdata.length === 0) {
|
||||||
toast("Failed getting file. Is it deleted?");
|
toast("Failed getting file. Is it deleted?");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return respdata
|
setFileData(respdata);
|
||||||
})
|
|
||||||
.then((responseData) => {
|
|
||||||
|
|
||||||
setFileData(responseData);
|
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
toast(error.toString());
|
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 (
|
||||||
|
<Container style={{ display: "flex", justifyContent: "center", alignItems: "center", height: "100vh" }}>
|
||||||
|
<div>
|
||||||
|
<CircularProgress />
|
||||||
|
<Typography variant="h6" style={{ marginTop: 20 }}>Downloading rules, please wait...</Typography>
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container style={{display: "flex"}}>
|
<Container style={{ display: "flex" }}>
|
||||||
{/* {selectedRule ? (
|
<Detection
|
||||||
<EditComponent
|
globalUrl={globalUrl}
|
||||||
ruleName={selectedRule.title}
|
ruleInfo={ruleInfo}
|
||||||
description={selectedRule.description}
|
folderDisabled={folderDisabled}
|
||||||
content={fileData}
|
setFolderDisabled={setFolderDisabled}
|
||||||
setContent={setFileData}
|
isTenzirActive={isTenzirActive}
|
||||||
lastEdited={selectedRule.lastEdited}
|
/>
|
||||||
editedBy={selectedRule.editedBy}
|
|
||||||
onSave={handleSave}
|
|
||||||
/>
|
|
||||||
) : null} */}
|
|
||||||
<Detection globalUrl={globalUrl} ruleInfo={ruleInfo} folderDisabled={folderDisabled} setFolderDisabled={setFolderDisabled} openEditBar={openEditBar} isTenzirActive={isTenzirActive} />
|
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DetectionDashBoard;
|
export default DetectionDashBoard;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import EditIcon from "@mui/icons-material/Edit";
|
|||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import ShuffleCodeEditor from "../components/ShuffleCodeEditor1.jsx";
|
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 [openCodeEditor, setOpenCodeEditor] = React.useState(false);
|
||||||
const [fileData, setFileData] = React.useState("");
|
const [fileData, setFileData] = React.useState("");
|
||||||
const [isEnabled, setIsEnabled] = React.useState(otherProps.is_enabled);
|
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");
|
toast("enable the directory to enable individual rules");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!isTenzirActive) {
|
||||||
|
toast("connect to the siem to enable/disable the rule");
|
||||||
|
return;
|
||||||
|
}
|
||||||
const newIsEnabled = event.target.checked;
|
const newIsEnabled = event.target.checked;
|
||||||
toggleRule(file_id, !newIsEnabled, globalUrl, () => {
|
toggleRule(file_id, !newIsEnabled, globalUrl, () => {
|
||||||
setIsEnabled(newIsEnabled);
|
setIsEnabled(newIsEnabled);
|
||||||
@@ -73,6 +77,7 @@ const RuleCard = ({ ruleName, description, file_id, globalUrl, folderDisabled, .
|
|||||||
<Switch
|
<Switch
|
||||||
checked={isEnabled && !folderDisabled}
|
checked={isEnabled && !folderDisabled}
|
||||||
onChange={handleSwitchChange}
|
onChange={handleSwitchChange}
|
||||||
|
disabled={!isTenzirActive}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -121,42 +126,43 @@ const toggleRule = (fileId, isCurrentlyEnabled, globalUrl, callback) => {
|
|||||||
toast(`An error occurred while ${action}ing the rule`);
|
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);
|
setOpenCodeEditor(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getFileContent = (file_id, setFileData, globalUrl) => {
|
const getFileContent = (file_id, setFileData, globalUrl) => {
|
||||||
setFileData("");
|
setFileData("");
|
||||||
fetch(globalUrl + "/api/v1/files/" + file_id + "/content", {
|
fetch(globalUrl + "/api/v1/files/" + file_id + "/content", {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
Accept: "application/json",
|
Accept: "application/json",
|
||||||
},
|
},
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status !== 200) {
|
||||||
|
console.log("Status not 200 for file :O!");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return response.text();
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((respdata) => {
|
||||||
if (response.status !== 200) {
|
if (respdata.length === 0) {
|
||||||
console.log("Status not 200 for file :O!");
|
toast("Failed getting file. Is it deleted?");
|
||||||
return "";
|
return;
|
||||||
}
|
}
|
||||||
return response.text();
|
return respdata
|
||||||
})
|
})
|
||||||
.then((respdata) => {
|
.then((responseData) => {
|
||||||
if (respdata.length === 0) {
|
|
||||||
toast("Failed getting file. Is it deleted?");
|
setFileData(responseData);
|
||||||
return;
|
})
|
||||||
}
|
.catch((error) => {
|
||||||
return respdata
|
toast(error.toString());
|
||||||
})
|
});
|
||||||
.then((responseData) => {
|
};
|
||||||
|
|
||||||
setFileData(responseData);
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
toast(error.toString());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export default RuleCard;
|
export default RuleCard;
|
||||||
|
|||||||
Reference in New Issue
Block a user