import React, { useState, useEffect } from 'react';
import { securityFramework} from "./LandingpageUsecases.jsx";
import CytoscapeComponent from 'react-cytoscapejs';
import frameworkStyle from '../frameworkStyle.jsx';
import AppSearch from './Appsearch.jsx';
import { v4 as uuidv4 } from "uuid";
import theme from '../theme';
import { useAlert } from "react-alert";
import { usecaseTypes } from "../components/UsecaseSearch.jsx"
import PaperComponent from "../components/PaperComponent.jsx"
import SuggestedWorkflows from "../components/SuggestedWorkflows.jsx"
import {
Paper,
Typography,
Divider,
IconButton,
Badge,
CircularProgress,
Tooltip,
Dialog,
} from "@material-ui/core";
import {
Button
} from '@material-ui/core';
import {
Close as CloseIcon,
Delete as DeleteIcon,
} from "@material-ui/icons";
import * as edgehandles from "cytoscape-edgehandles";
import * as cytoscape from "cytoscape";
cytoscape.use(edgehandles);
const svgSize = 23
const parsedDatatypeImages = {
"Cases": encodeURI(`data:image/svg+xml;utf-8,`),
"EDR & AV": encodeURI(`data:image/svg+xml;utf-8,`),
}
export const usecases = {
"None": {
"manual": [],
"automated": [],
},
"Phishing": {
"manual": [],
"automated": [
{
"source": "BOTTOM_LEFT",
"target": "COMMS",
"description": "Email received",
"human": false,
},
{
"source": "COMMS",
"target": "SHUFFLE",
"human": false,
},
{
"source": "SHUFFLE",
"target": "CASES",
"human": false,
},
{
"source": "INTEL",
"target": "SHUFFLE",
"human": false,
},
{
"source": "ASSETS",
"target": "SHUFFLE",
"human": false,
},
{
"source": "SIEM",
"target": "SHUFFLE",
"human": false,
},
{
"source": "SHUFFLE",
"target": "INTEL",
"human": false,
},
{
"source": "SHUFFLE",
"target": "COMMS",
"human": false,
},
{
"source": "CASES",
"target": "EDR & AV",
"human": true,
},
]},
"Ransomware": {
"manual": [],
"automated": [
{
"source": "BOTTOM_LEFT",
"target": "EDR & AV",
"description": "EDR & AV alert",
"human": false,
},
{
"source": "EDR & AV",
"target": "SHUFFLE",
"description": "",
"human": false,
},
{
"source": "SHUFFLE",
"target": "EDR & AV",
"human": false,
"description": "isolate",
},
{
"source": "SHUFFLE",
"target": "IAM",
"human": false,
"description": "Block access",
},
{
"source": "SHUFFLE",
"target": "COMMS",
"description": "Notify oncall and affected user",
"human": false,
},
{
"source": "SHUFFLE",
"target": "CASES",
"description": "Create enriched alert",
"human": false,
},
{
"source": "SHUFFLE",
"target": "CASES",
"human": false,
},
{
"source": "CASES",
"target": "EDR & AV",
"description": "Validate alert",
"human": true,
},
]
},
"Exploits": {
"manual": [],
"automated": [
{
"source": "TOP_LEFT",
"target": "NETWORK",
"description": "Exploit",
"human": false,
},
{
"source": "NETWORK",
"target": "SIEM",
"description": "WAF alert",
"human": false,
},
{
"source": "SIEM",
"target": "SHUFFLE",
"human": false,
},
{
"source": "SHUFFLE",
"target": "CASES",
"human": false,
},
{
"source": "SHUFFLE",
"target": "COMMS",
"human": false,
},
{
"source": "INTEL",
"target": "SHUFFLE",
"human": false,
},
{
"source": "ASSETS",
"target": "SHUFFLE",
"human": false,
},
{
"source": "IAM",
"target": "SHUFFLE",
"human": false,
},
{
"source": "CASES",
"target": "EDR & AV",
"human": true,
},
]
},
"AWS S3 honeypots": {
"manual": [],
"automated": [
{
"source": "TOP_LEFT",
"target": "SIEM",
"description": "S3 logs",
"human": false,
},
{
"source": "SIEM",
"target": "SHUFFLE",
"human": false,
},
{
"source": "SHUFFLE",
"target": "INTEL",
"description": "Add sighting",
"human": false,
},
{
"source": "INTEL",
"target": "SHUFFLE",
"human": false,
},
{
"source": "SHUFFLE",
"target": "CASES",
"description": "Create case",
"human": false,
},
{
"source": "SHUFFLE",
"target": "NETWORK",
"description": "Block IP",
"human": false,
},
]
},
"SIEM alerts": {
"manual": [],
"automated": [
{
"source": "TOP_LEFT",
"target": "SIEM",
"description": "Syslog",
"human": false,
},
{
"source": "SIEM",
"target": "SHUFFLE",
"description": "Alerts",
"human": false,
},
{
"source": "SHUFFLE",
"target": "INTEL",
"description": "Enrich",
"human": false,
},
{
"source": "INTEL",
"target": "SHUFFLE",
"human": false,
},
{
"source": "IAM",
"target": "SHUFFLE",
"human": false,
"description": "enrich",
},
{
"source": "SHUFFLE",
"target": "IAM",
"human": false,
},
{
"source": "SHUFFLE",
"target": "CASES",
"human": false,
},
{
"source": "SHUFFLE",
"target": "COMMS",
"human": false,
},
{
"source": "SHUFFLE",
"target": "EDR & AV",
"human": false,
},
{
"source": "SHUFFLE",
"target": "EDR & AV",
"human": true,
},
]
},
"New Detections": {
"manual": [],
"automated": [
{
"source": "TOP_LEFT",
"target": "SIEM",
"description": "Hypothesis",
"human": true,
},
{
"source": "SIEM",
"target": "SIEM",
"description": "Create rule",
"human": true,
},
{
"source": "SIEM",
"target": "NETWORK",
"description": "Create rule",
"human": true,
},
{
"source": "NETWORK",
"target": "EDR & AV",
"description": "Create rule",
"human": true,
},
{
"source": "SIEM",
"target": "SHUFFLE",
"description": "Send alert",
"human": false,
},
{
"source": "NETWORK",
"target": "SHUFFLE",
"description": "Send alert",
"human": false,
},
{
"source": "EDR & AV",
"target": "SHUFFLE",
"description": "Send alert",
"human": false,
},
{
"source": "INTEL",
"target": "SHUFFLE",
"description": "Enrich IOCs",
"human": false,
},
{
"source": "ASSETS",
"target": "SHUFFLE",
"description": "Enrich hostnames etc.",
"human": false,
},
{
"source": "SHUFFLE",
"target": "CASES",
"description": "Create enriched alert",
"human": false,
},
]
},
"Vulnerabilities": {
"manual": [],
"automated": [
{
"source": "TOP_RIGHT",
"target": "ASSETS",
"description": "New vuln",
"human": false,
},
{
"source": "ASSETS",
"target": "SHUFFLE",
"description": "Get vuln",
"human": false,
},
{
"source": "SHUFFLE",
"target": "CASES",
"description": "Raise ticket",
"human": false,
},
{
"source": "SHUFFLE",
"target": "COMMS",
"description": "Notify owner",
"human": false,
},
{
"source": "COMMS",
"target": "SHUFFLE",
"description": "",
"human": true,
},
{
"source": "SHUFFLE",
"target": "ASSETS",
"description": "Auto-patch",
"human": false,
},
]
},
"Approvals": {
"manual": [],
"automated": [
{
"source": "TOP_LEFT",
"target": "CASES",
"description": "New inquiry",
"human": false,
},
{
"source": "CASES",
"target": "SHUFFLE",
"description": "Get tickets",
"human": false,
},
{
"source": "SHUFFLE",
"target": "COMMS",
"description": "Ask for approval",
"human": false,
},
{
"source": "COMMS",
"target": "SHUFFLE",
"human": true,
},
{
"source": "SHUFFLE",
"target": "ASSETS",
"description": "Add to user",
"human": false,
},
{
"source": "SHUFFLE",
"target": "IAM",
"description": "Approve access",
"human": false,
},
{
"source": "SHUFFLE",
"target": "CASES",
"human": false,
},
]
},
"Enrichment": {
"manual": [],
"automated": [
{
"source": "TOP_LEFT",
"target": "CASES",
"description": "Case updated",
"human": false,
},
{
"source": "SHUFFLE",
"target": "CASES",
"description": "Get and enrich ticket",
"human": false,
},
{
"source": "IAM",
"target": "SHUFFLE",
"description": "Get access rights",
"human": false,
},
{
"source": "ASSETS",
"target": "SHUFFLE",
"description": "Get relevant assets",
"human": false,
},
{
"source": "INTEL",
"target": "SHUFFLE",
"description": "Get relevant IPs",
"human": false,
},
{
"source": "COMMS",
"target": "SHUFFLE",
"description": "Find relevant mails & chats",
"human": false,
},
{
"source": "EDR & AV",
"target": "SHUFFLE",
"description": "Find incidents for host",
"human": false,
},
{
"source": "SIEM",
"target": "SHUFFLE",
"description": "Find info about hostname and user",
"human": false,
},
{
"source": "SHUFFLE",
"target": "SHUFFLE",
"description": "Format info",
"human": false,
},
{
"source": "SHUFFLE",
"target": "CASES",
"description": "",
"human": false,
},
]
},
"Draw": {
}
}
const Framework = (props) => {
const { globalUrl, isLoaded, showOptions, selectedOption, rolling, frameworkData, setFrameworkData, size, inputUsecase, isLoggedIn, color, discoveryWrapper, setDiscoveryWrapper, userdata, apps, } = props;
const [cy, setCy] = React.useState()
const [edgesStarted, setEdgesStarted] = React.useState(false)
const [graphDone, setGraphDone] = React.useState(false)
const [cyDone, setCyDone] = React.useState(false)
const [discoveryData, setDiscoveryData] = React.useState({})
const [selectionOpen, setSelectionOpen] = React.useState(true)
const [frameworkSuggestions, setFrameworkSuggestions] = React.useState([])
const [newSelectedApp, setNewSelectedApp] = React.useState({})
const [defaultSearch, setDefaultSearch] = React.useState("")
const [animationStarted, setAnimationStarted] = React.useState(false)
const [paperTitle, setPaperTitle] = React.useState("")
const [changedApp, setChangedApp] = React.useState("")
const [usecaseType, setUsecaseType] = React.useState(0)
const [selectedUsecase, setSelectedUsecase] = React.useState(selectedOption !== undefined ? selectedOption : "Phishing")
const scale = size === undefined ? 1 : size > 5 ? 3 : size
const alert = useAlert()
const showRecommendations = (changed, frameworkData) => {
console.log("Inside recommendation loader")
setChangedApp(changed)
// FIX:
// 0. Get workflows loaded in from usecasesearch
// 1. Search through workflow templates for matching app types
// 2. Validate if template is already in use~ (workflows with same tools)
// 3. Generate the workflow(s) - PS: Fix new workflow templates
// 4. Moving on!
// How can we load templates? UsecaseSearch?
var showusecases = []
//const foundusecase = usecaseTypes.find(data => data.name.toLowerCase() === defaultSearch.toLowerCase())
for (var key in usecaseTypes) {
for (var subkey in usecaseTypes[key].value) {
const usecase = usecaseTypes[key].value[subkey]
if (usecase.active === false) {
continue
}
var potential = false
var matches = []
for (var itemtype in usecase.items) {
const apptype = usecase.items[itemtype].app_type.toLowerCase()
//console.log("OLD: ", changed, "USECASE: ", apptype)
if (changed.toLowerCase() === apptype || changed.toLowerCase().includes(apptype)) {
potential = true
if (frameworkData[apptype].name !== undefined && frameworkData[apptype].name !== null && frameworkData[apptype].name.length > 0) {
usecase.items[itemtype].app = frameworkData[apptype]
}
matches.push(usecase.items[itemtype])
} else {
// Check if the type is done in frameworkData
if (frameworkData[apptype] !== undefined) {
//console.log("NOT UNDEFINED: ", frameworkData[apptype])
if (frameworkData[apptype].name !== undefined && frameworkData[apptype].name !== null && frameworkData[apptype].name.length > 0) {
console.log("FOUND: ", frameworkData[apptype])
usecase.items[itemtype].app = frameworkData[apptype]
//console.log("Real app!")
matches.push(usecase.items[itemtype])
}
//if (frameworkData[apptype] !== undefined) {
} else {
console.log("UNDEFINED APP (bad name?): ", apptype)
}
}
}
if (potential) {
if (matches.length === usecase.items.length) {
usecase.color = "#c51152"
usecase.type = usecaseTypes[key].name
showusecases.push(usecase)
}
}
}
}
// FIXME: Check if a usecase has already been handled
console.log("")
console.log("GOT USECASES: ", showusecases)
// FIXME: Just showing one usecase at a time for now
if (showusecases.length > 0) {
setFrameworkSuggestions(showusecases.slice(0,1))
}
}
useEffect(() => {
console.log("DISCWRAP CHANG: ", discoveryWrapper)
if (discoveryWrapper === undefined || discoveryWrapper.id === "SHUFFLE" || discoveryWrapper.id === undefined || cy === undefined) {
setDiscoveryData({})
if (cy !== undefined) {
cy.nodes().unselect()
}
return
}
// Find the node and click it?
//setTimeout(() => {
const nodes = cy.nodes().jsons()
for (var key in nodes) {
const node = nodes[key]
var newSearchName = discoveryWrapper.id.valueOf()
if (newSearchName === "EMAIL") {
newSearchName = "COMMS"
}
if (newSearchName === "ERADICATION" || newSearchName === "ENDPOINT") {
newSearchName = "EDR & AV"
}
if (node.data.id === newSearchName) {
const tmpnode = cy.getElementById(node.data.id)
if (tmpnode !== undefined) {
tmpnode.select()
}
setDefaultSearch(discoveryWrapper.id)
setPaperTitle(discoveryWrapper.id)
}
}
//}, 50,)
//setDiscoveryData(discoveryWrapper)
}, [discoveryWrapper])
const setUsecaseItem = (inputUsecase) => {
var parsedUsecase = inputUsecase
const edges = cy.edges().jsons()
parsedUsecase.process = []
for (var key in edges) {
const edge = edges[key]
console.log("Edge: ", edge)
parsedUsecase.process.push(edge.data)
}
fetch(globalUrl + "/api/v1/workflows/usecases", {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify(parsedUsecase),
credentials: "include",
})
.then((response) => {
if (response.status !== 200) {
console.log("Status not 200 for framework!");
}
return response.json();
})
.then((responseJson) => {
if (responseJson.success === false) {
if (responseJson.reason !== undefined) {
alert.error("Failed updating: " + responseJson.reason)
} else {
alert.error("Failed to update framework for your org.")
}
} else {
alert.info("Updated usecase.")
}
})
.catch((error) => {
alert.error(error.toString());
//setFrameworkLoaded(true)
})
}
const setFrameworkItem = (data) => {
fetch(globalUrl + "/api/v1/apps/frameworkConfiguration", {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify(data),
credentials: "include",
})
.then((response) => {
if (response.status !== 200) {
console.log("Status not 200 for framework!");
}
return response.json();
})
.then((responseJson) => {
if (responseJson.success === false) {
if (responseJson.reason !== undefined) {
alert.error("Failed updating: " + responseJson.reason)
} else {
alert.error("Failed to update framework for your org.")
}
}
//setFrameworkLoaded(true)
//setFrameworkData(responseJson)
})
.catch((error) => {
alert.error(error.toString());
//setFrameworkLoaded(true)
})
}
useEffect(() => {
console.log(newSelectedApp, discoveryData)
if (newSelectedApp.objectID === undefined || newSelectedApp.objectID === undefined || newSelectedApp.objectID.length === 0) {
return
}
//if (paperTitle.length > 0) {
// console.log("No papertitle (parent button)")
// cy.elements().unselect()
// return
//}
if (discoveryData.id === undefined) {
console.log("No discoverydata (parent button)")
cy.elements().unselect()
return
}
const submitValue = {
"type": discoveryData.id,
"name": newSelectedApp.name,
"id": newSelectedApp.objectID,
"large_image": newSelectedApp.image_url,
"description": newSelectedApp.description,
}
const foundelement = cy.getElementById(discoveryData.id)
if (foundelement !== undefined && foundelement !== null) {
foundelement.data("large_image", newSelectedApp.image_url)
foundelement.data("margin_x", "0px")
foundelement.data("margin_y", "0px")
foundelement.data("text_margin_y", `${60*scale}px`)
foundelement.data("width", `${85*scale}px`)
foundelement.data("height", `${85*scale}px`)
}
if (setFrameworkData !== undefined) {
// Find discoveryData.id
var keys = []
for (const [key, value] of Object.entries(frameworkData)) {
if (key.toLowerCase() === discoveryData.id.toLowerCase()) {
keys.push(key)
}
}
if (keys.length === 0) {
console.log("Failed to find: ", discoveryData.id, " IN ", frameworkData)
} else {
for (var key in keys) {
frameworkData[keys[key]] = submitValue
}
setFrameworkData(frameworkData)
showRecommendations(discoveryData.id, frameworkData)
}
}
setFrameworkItem(submitValue)
cy.elements().unselect()
}, [newSelectedApp])
const isCloud =
window.location.host === "localhost:3002" ||
window.location.host === "shuffler.io";
const imgSize = 50;
var parsedFrameworkData = frameworkData === undefined ? {} : frameworkData
// Awful mapping to make sure all access is always there
if (frameworkData !== undefined) {
if (frameworkData.cases !== undefined) {
if (frameworkData.cases.large_image === undefined && frameworkData.cases.large_image === null || frameworkData.cases.large_image === "") {
frameworkData.cases = {}
}
parsedFrameworkData.Cases = frameworkData.cases
} else {
parsedFrameworkData.Cases = {}
}
if (frameworkData.siem !== undefined) {
if (frameworkData.siem.large_image === undefined && frameworkData.siem.large_image === null || frameworkData.siem.large_image === "") {
frameworkData.siem = {}
}
parsedFrameworkData.SIEM = frameworkData.siem
} else {
parsedFrameworkData.SIEM = {}
}
if (frameworkData.assets !== undefined) {
if (frameworkData.assets.large_image === undefined && frameworkData.assets.large_image === null || frameworkData.assets.large_image === "") {
frameworkData.assets = {}
}
parsedFrameworkData.Assets = frameworkData.assets
} else {
parsedFrameworkData.Assets = {}
}
if (frameworkData.intel !== undefined) {
if (frameworkData.intel.large_image === undefined && frameworkData.intel.large_image === null || frameworkData.intel.large_image === "") {
frameworkData.intel = {}
}
parsedFrameworkData.Intel = frameworkData.intel
} else {
parsedFrameworkData.Intel= {}
}
if (frameworkData.communication !== undefined) {
if (frameworkData.communication.large_image === undefined && frameworkData.communication.large_image === null || frameworkData.communication.large_image === "") {
frameworkData.communication = {}
}
parsedFrameworkData.Comms = frameworkData.communication
} else {
parsedFrameworkData.Comms = {}
}
if (frameworkData.network !== undefined) {
if (frameworkData.network.large_image === undefined && frameworkData.network.large_image === null || frameworkData.network.large_image === "") {
frameworkData.network = {}
}
parsedFrameworkData.Network = frameworkData.network
} else {
parsedFrameworkData.Network = {}
}
if (frameworkData.iam !== undefined) {
if (frameworkData.iam.large_image === undefined && frameworkData.iam.large_image === null || frameworkData.iam.large_image === "") {
frameworkData.iam = {}
}
parsedFrameworkData.IAM = frameworkData.iam
} else {
parsedFrameworkData.IAM = {}
}
if (frameworkData.edr !== undefined) {
if (frameworkData.edr.large_image === undefined && frameworkData.edr.large_image === null || frameworkData.edr.large_image === "") {
frameworkData.edr = {}
}
parsedFrameworkData["EDR & AV"] = frameworkData.edr
} else {
parsedFrameworkData["EDR & AV"] = {}
}
} else {
//console.log("No frameworkdata for org! Setting default")
parsedFrameworkData["Cases"] = {}
parsedFrameworkData["SIEM"] = {}
parsedFrameworkData["Assets"] = {}
parsedFrameworkData["IAM"] = {}
parsedFrameworkData["Intel"] = {}
parsedFrameworkData["Comms"] = {}
parsedFrameworkData["Network"] = {}
parsedFrameworkData["EDR & AV"] = {}
}
//console.log("Framework - update? ", parsedFrameworkData)
// 0 = automated, 1 = manual
const elements = []
const surfaceColor = "#27292D"
const changeUsecase = (value, type) => {
//console.log("Value: ", value)
if (value === "Draw" && !edgesStarted) {
setEdgesStarted(true)
cy.edgehandles({
handleNodes: (el) => {
if (el.isNode() &&
!el.data("isButton") &&
!el.data("isDescriptor") &&
el.data("type") !== "COMMENT") {
return true
}
return false
},
preview: true,
toggleOffOnLeave: true,
loopAllowed: function (node) {
return false;
},
})
}
setSelectedUsecase(value)
const edges = cy.edges()
if (edges !== undefined) {
const allEdges = edges.jsons()
for (var key in allEdges) {
const newedge = allEdges[key]
const foundelement = cy.getElementById(newedge.data.id)
if (foundelement !== undefined && foundelement !== null) {
foundelement.remove()
}
}
}
var found = false
var parsedType = type === 1 ? "manual" : "automated"
if (usecases === undefined || usecases === null) {
return
}
const newedges = usecases[value][parsedType]
for (var key in newedges) {
newedges[key].label = parseInt(key)+1
if (newedges[key].description !== undefined && newedges[key].description !== null && newedges[key].description.length > 0) {
newedges[key].label = (parseInt(key)+1)+" "+newedges[key].description
}
cy.add({
group: "edges",
data: newedges[key],
})
}
setGraphDone(true)
}
const animationDuration = 150;
const nodeAddDuration = 2500;
if (cy !== undefined && cyDone && !animationStarted) {
const foundelement = cy.getElementById("CASES")
if (foundelement !== undefined && foundelement !== null) {
setAnimationStarted(true)
var parsedStyle = {
"ghost": "yes",
"border-color": "#f86a3e",
"border-width": "10px",
"border-opacity": ".7",
}
var parsedStyle2 = {
"ghost": "yes",
"border-width": "7px",
}
/*
// Animation
for (var i = 0; i < 10; i++) {
foundelement.animate(
{
style: parsedStyle,
},
{
duration: nodeAddDuration,
}
).delay(1000)
foundelement.animate(
{
style: parsedStyle2,
},
{
duration: nodeAddDuration,
}
)
}
*/
}
}
const onNodeAdded = (event) => {
//if (event.target.data("animate") === true) {
//}
}
const onNodeHover = (event) => {
const nodedata = event.target.data();
const cytoscapeElement = document.getElementById("cytoscape_view")
if (cytoscapeElement !== undefined && cytoscapeElement !== null) {
cytoscapeElement.style.cursor = "pointer"
}
var parsedStyle = {
"border-width": "7px",
"border-opacity": ".7",
}
//if (nodedata.type !== "COMMENT") {
// parsedStyle.color = "white";
//}
if (event.target !== undefined && event.target !== null) {
event.target.animate(
{
style: parsedStyle,
},
{
duration: animationDuration,
}
);
}
}
const onNodeHoverOut = (event) => {
const nodedata = event.target.data();
//console.log("Node OUT: ", nodedata)
const cytoscapeElement = document.getElementById("cytoscape_view")
if (cytoscapeElement !== undefined && cytoscapeElement !== null) {
cytoscapeElement.style.cursor = "default"
}
var parsedStyle = {
"border-width": "3px",
//"cursor": "default",
}
event.target.animate(
{
style: parsedStyle,
},
{
duration: animationDuration,
}
)
}
const onNodeUnselect = (event) => {
var data = event.target.data();
console.log("UNSELECT: ", data)
var parsedStyle = {
"border-width": "10px",
"border-opacity": ".7",
"border-color": "#7fe57f",
}
if (event.target !== undefined && event.target !== null) {
event.target.animate(
{
style: parsedStyle,
},
{
duration: animationDuration,
}
)
setTimeout(() => {
event.target.animate(
{
style: {
"border-width": "3px",
},
},
{
duration: animationDuration,
}
)
}, 2500)
}
//setDiscoveryData({})
setDiscoveryWrapper({})
setSelectionOpen(false)
setDefaultSearch("")
setPaperTitle("")
//setDiscoveryData({})
}
const onNodeSelect = (event) => {
var data = event.target.data();
console.log("Node: ", data)
if (data.id === "SHUFFLE") {
event.target.unselect()
return
}
if (data.label === "EDR & AV") {
data.label = "ERADICATION"
}
setDiscoveryData(data)
setSelectionOpen(true)
setNewSelectedApp({})
setDefaultSearch(data.label.charAt(0).toUpperCase()+(data.label.substring(1)).toLowerCase())
}
const onEdgeAdded = (event) => {
//event.target.data("human", false)
}
const onEdgeSelect = (event) => {
console.log(event)
if (event.target.data("human") === undefined || event.target.data("human") === false) {
event.target.data("human", true)
} else if (event.target.data("human") === true) {
event.target.remove()
return
//event.target.data("human", false)
}
console.log("Edge selected!", event.target.data())
event.target.unselect()
}
if (graphDone && cyDone === false) {
cy.fit(null, 200);
cy.on("select", "edge", (e) => onEdgeSelect(e));
cy.on("add", "edge", (e) => onEdgeAdded(e));
cy.on("select", "node", (e) => {
onNodeSelect(e)
})
cy.on("unselect", "node", (e) => {
onNodeUnselect(e)
})
cy.on("mouseover", "node", (e) => {onNodeHover(e)})
cy.on("mouseout", "node", (e) => onNodeHoverOut(e));
cy.on("add", "node", (e) => onNodeAdded(e));
setCyDone(true)
}
if (cy !== undefined && cy.elements().length === 0 && parsedFrameworkData !== undefined) {
//'background-image': 'data(small_image)',
const shiftradius = 115*scale
const baselocationX = 285*scale
const baselocationY = 50*scale
const shiftmodifier = 3*scale
//const svgSize = `${40*scale}px`
const svgSize = `${40}px`
const fontSize = `${12*scale}px`
const defaultSize = `${85*scale}px`
const iconSize = `${45*scale}px`
const textMarginDefault = `${14*scale}px`
const textMarginImage = `${60*scale}px`
const nodes = [
{
group: "nodes",
data: {
boxwidth: defaultSize,
boxheight: defaultSize,
font_size: fontSize,
is_valid: true,
isValid: true,
errors: [],
name: parsedFrameworkData.Cases.name === undefined ? "" : parsedFrameworkData.Cases.name,
description: parsedFrameworkData.Cases.description === undefined ? "" : parsedFrameworkData.Cases.description,
app_id: parsedFrameworkData.Cases.id === undefined ? "" : parsedFrameworkData.Cases.id,
text_margin_y: parsedFrameworkData.Cases.large_image === undefined ? textMarginDefault : textMarginImage,
margin_x: parsedFrameworkData.Cases.large_image === undefined ? `${32*scale}px` : "0px",
margin_y: parsedFrameworkData.Cases.large_image === undefined ? `${19*scale}px` : `0px`,
width: parsedFrameworkData.Cases.large_image === undefined ? iconSize : defaultSize,
height: parsedFrameworkData.Cases.large_image === undefined ? iconSize : defaultSize,
large_image: parsedFrameworkData.Cases.large_image === undefined ? encodeURI(`data:image/svg+xml;utf-8,`) : parsedFrameworkData.Cases.large_image,
label: securityFramework[0].text.toUpperCase(),
id: securityFramework[0].text.toUpperCase(),
animate: true,
},
renderedPosition: {
x: baselocationX,
y: baselocationY,
}
},
{
group: "nodes",
data: {
font_size: fontSize,
boxwidth: defaultSize,
boxheight: defaultSize,
is_valid: true,
isValid: true,
errors: [],
name: parsedFrameworkData.IAM.name === undefined ? "" : parsedFrameworkData.IAM.name,
description: parsedFrameworkData.IAM.description === undefined ? "" : parsedFrameworkData.IAM.description,
app_id: parsedFrameworkData.IAM.id === undefined ? "" : parsedFrameworkData.IAM.id,
text_margin_y: parsedFrameworkData.IAM.large_image === undefined ? textMarginDefault : textMarginImage,
margin_x: parsedFrameworkData.IAM.large_image === undefined ? `${32*scale}px` : "0px",
margin_y: parsedFrameworkData.IAM.large_image === undefined ? `${19*scale}px` : `0px`,
width: parsedFrameworkData.IAM.large_image === undefined ? iconSize : defaultSize,
height: parsedFrameworkData.IAM.large_image === undefined ? iconSize : defaultSize,
large_image: parsedFrameworkData.IAM.large_image === undefined ? encodeURI(`data:image/svg+xml;utf-8,`) : parsedFrameworkData.IAM.large_image,
label: securityFramework[3].text.toUpperCase(),
id: securityFramework[3].text.toUpperCase(),
animate: false,
},
renderedPosition: {
x: baselocationX+shiftradius+(shiftradius/shiftmodifier),
y: baselocationY+shiftradius-(shiftradius/shiftmodifier),
}
},
{
group: "nodes",
data: {
font_size: fontSize,
boxwidth: defaultSize,
boxheight: defaultSize,
is_valid: true,
isValid: true,
errors: [],
name: parsedFrameworkData.Assets.name === undefined ? "" : parsedFrameworkData.Assets.name,
description: parsedFrameworkData.Assets.description === undefined ? "" : parsedFrameworkData.Assets.description,
app_id: parsedFrameworkData.Assets.id === undefined ? "" : parsedFrameworkData.Assets.id,
text_margin_y: parsedFrameworkData.Assets.large_image === undefined ? textMarginDefault : textMarginImage,
margin_x: parsedFrameworkData.Assets.large_image === undefined ? `${32*scale}px` : "0px",
margin_y: parsedFrameworkData.Assets.large_image === undefined ? `${19*scale}px` : `0px`,
width: parsedFrameworkData.Assets.large_image === undefined ? iconSize : defaultSize,
height: parsedFrameworkData.Assets.large_image === undefined ? iconSize : defaultSize,
large_image: parsedFrameworkData.Assets.large_image === undefined ? encodeURI(`data:image/svg+xml;utf-8,`) : parsedFrameworkData.Assets.large_image,
label: securityFramework[2].text.toUpperCase(),
id: securityFramework[2].text.toUpperCase(),
animate: false,
},
renderedPosition: {
x: baselocationX+shiftradius*2,
y: baselocationY+shiftradius*2,
}
},
{
group: "nodes",
data: {
font_size: fontSize,
boxwidth: defaultSize,
boxheight: defaultSize,
is_valid: true,
isValid: true,
errors: [],
name: parsedFrameworkData.Intel.name === undefined ? "" : parsedFrameworkData.Intel.name,
description: parsedFrameworkData.Intel.description === undefined ? "" : parsedFrameworkData.Intel.description,
app_id: parsedFrameworkData.Intel.id === undefined ? "" : parsedFrameworkData.Intel.id,
text_margin_y: parsedFrameworkData.Intel.large_image === undefined ? textMarginDefault : textMarginImage,
margin_x: parsedFrameworkData.Intel.large_image === undefined ? `${32*scale}px` : "0px",
margin_y: parsedFrameworkData.Intel.large_image === undefined ? `${19*scale}px` : `0px`,
width: parsedFrameworkData.Intel.large_image === undefined ? iconSize : defaultSize,
height: parsedFrameworkData.Intel.large_image === undefined ? iconSize : defaultSize,
large_image: parsedFrameworkData.Intel.large_image === undefined ? encodeURI(`data:image/svg+xml;utf-8,`): parsedFrameworkData.Intel.large_image,
label: securityFramework[4].text.toUpperCase(),
id: securityFramework[4].text.toUpperCase(),
animate: false,
},
renderedPosition: {
x: baselocationX+shiftradius+(shiftradius/shiftmodifier),
y: baselocationY+shiftradius*3+(shiftradius/shiftmodifier),
}
},
{
group: "nodes",
data: {
font_size: fontSize,
boxwidth: defaultSize,
boxheight: defaultSize,
is_valid: true,
isValid: true,
errors: [],
name: parsedFrameworkData.Comms.name === undefined ? "" : parsedFrameworkData.Comms.name,
description: parsedFrameworkData.Comms.description === undefined ? "" : parsedFrameworkData.Comms.description,
app_id: parsedFrameworkData.Comms.id === undefined ? "" : parsedFrameworkData.Comms.id,
text_margin_y: parsedFrameworkData.Comms.large_image === undefined ? textMarginDefault : textMarginImage,
margin_x: parsedFrameworkData.Comms.large_image === undefined ? `${32*scale}px` : "0px",
margin_y: parsedFrameworkData.Comms.large_image === undefined ? `${19*scale}px` : `0px`,
width: parsedFrameworkData.Comms.large_image === undefined ? iconSize : defaultSize,
height: parsedFrameworkData.Comms.large_image === undefined ? iconSize : defaultSize,
large_image: parsedFrameworkData.Comms.large_image === undefined ? encodeURI(`data:image/svg+xml;utf-8,`) : parsedFrameworkData.Comms.large_image,
label: securityFramework[5].text.toUpperCase(),
id: securityFramework[5].text.toUpperCase(),
animate: false,
},
renderedPosition: {
x: baselocationX,
y: baselocationY+shiftradius*4,
}
},
{
group: "nodes",
data: {
font_size: fontSize,
boxwidth: defaultSize,
boxheight: defaultSize,
is_valid: true,
isValid: true,
errors: [],
name: parsedFrameworkData["EDR & AV"].name === undefined ? "" : parsedFrameworkData["EDR & AV"].name,
description: parsedFrameworkData["EDR & AV"].description === undefined ? "" : parsedFrameworkData["EDR & AV"].description,
app_id: parsedFrameworkData["EDR & AV"].id === undefined ? "" : parsedFrameworkData["EDR & AV"].id,
text_margin_y: parsedFrameworkData["EDR & AV"].large_image === undefined ? textMarginDefault : textMarginImage,
margin_x: parsedFrameworkData["EDR & AV"].large_image === undefined ? `${32*scale}px` : "0px",
margin_y: parsedFrameworkData["EDR & AV"].large_image === undefined ? `${19*scale}px` : `0px`,
width: parsedFrameworkData["EDR & AV"].large_image === undefined ? iconSize : defaultSize,
height: parsedFrameworkData["EDR & AV"].large_image === undefined ? iconSize : defaultSize,
large_image: parsedFrameworkData["EDR & AV"].large_image === undefined ? encodeURI(`data:image/svg+xml;utf-8,`) : parsedFrameworkData["EDR & AV"].large_image,
label: securityFramework[7].text.toUpperCase(),
id: securityFramework[7].text.toUpperCase(),
animate: false,
},
renderedPosition: {
x: baselocationX-shiftradius-(shiftradius/shiftmodifier),
y: baselocationY+shiftradius*3+(shiftradius/shiftmodifier),
}
},
{
group: "nodes",
data: {
font_size: fontSize,
boxwidth: defaultSize,
boxheight: defaultSize,
is_valid: true,
isValid: true,
errors: [],
name: parsedFrameworkData.Network.name === undefined ? "" : parsedFrameworkData.Network.name,
description: parsedFrameworkData.Network.description === undefined ? "" : parsedFrameworkData.Network.description,
app_id: parsedFrameworkData.Network.id === undefined ? "" : parsedFrameworkData.Network.id,
text_margin_y: parsedFrameworkData.Network.large_image === undefined ? textMarginDefault : textMarginImage,
margin_x: parsedFrameworkData.Network.large_image === undefined ? `${32*scale}px` : "0px",
margin_y: parsedFrameworkData.Network.large_image === undefined ? `${19*scale}px` : `0px`,
width: parsedFrameworkData.Network.large_image === undefined ? iconSize : defaultSize,
height: parsedFrameworkData.Network.large_image === undefined ? iconSize : defaultSize,
large_image: parsedFrameworkData.Network.large_image === undefined ? encodeURI(`data:image/svg+xml;utf-8,`) : parsedFrameworkData.Network.large_image,
label: securityFramework[6].text.toUpperCase(),
id: securityFramework[6].text.toUpperCase(),
animate: false,
},
renderedPosition: {
x: baselocationX-shiftradius*2,
y: baselocationY+shiftradius*2,
}
},
{
group: "nodes",
data: {
font_size: fontSize,
boxwidth: defaultSize,
boxheight: defaultSize,
is_valid: true,
isValid: true,
errors: [],
name: parsedFrameworkData.SIEM.name === undefined ? "" : parsedFrameworkData.SIEM.name,
description: parsedFrameworkData.SIEM.description === undefined ? "" : parsedFrameworkData.SIEM.description,
app_id: parsedFrameworkData.SIEM.id === undefined ? "" : parsedFrameworkData.SIEM.id,
text_margin_y: parsedFrameworkData.SIEM.large_image === undefined ? textMarginDefault : textMarginImage,
margin_x: parsedFrameworkData.SIEM.large_image === undefined ? `${32*scale}px` : "0px",
margin_y: parsedFrameworkData.SIEM.large_image === undefined ? `${19*scale}px` : `0px`,
width: parsedFrameworkData.SIEM.large_image === undefined ? iconSize : defaultSize,
height: parsedFrameworkData.SIEM.large_image === undefined ? iconSize : defaultSize,
large_image: parsedFrameworkData.SIEM.large_image === undefined ? encodeURI(`data:image/svg+xml;utf-8,`) : parsedFrameworkData.SIEM.large_image,
label: securityFramework[1].text.toUpperCase(),
id: securityFramework[1].text.toUpperCase(),
animate: false,
},
renderedPosition: {
x: baselocationX-shiftradius-(shiftradius/shiftmodifier),
y: baselocationY+shiftradius-(shiftradius/shiftmodifier),
}
},
]
// Middlenode
nodes.push({
group: "nodes",
data: {
font_size: fontSize,
width: defaultSize,
height: defaultSize,
id: "SHUFFLE",
is_valid: true,
isValid: true,
errors: [],
middle_node: true,
},
renderedPosition: {
x: baselocationX,
y: baselocationY+shiftradius*2,
}
})
// Extra nodes
nodes.push({
group: "nodes",
data: {
is_valid: true,
isValid: true,
errors: [],
large_image: encodeURI(`data:image/svg+xml;utf-8,`),
id: "TOP_LEFT",
invisible: true,
},
renderedPosition: {
x: baselocationX-shiftradius*2.5,
y: baselocationY-50,
}
})
nodes.push({
group: "nodes",
data: {
is_valid: true,
isValid: true,
errors: [],
large_image: encodeURI(`data:image/svg+xml;utf-8,`),
id: "BOTTOM_LEFT",
invisible: true,
},
renderedPosition: {
x: baselocationX-shiftradius*2.5-10,
y: baselocationY+shiftradius*4-10,
}
})
nodes.push({
group: "nodes",
data: {
is_valid: true,
isValid: true,
errors: [],
large_image: encodeURI(`data:image/svg+xml;utf-8,`),
id: "BOTTOM_RIGHT",
invisible: true,
},
renderedPosition: {
x: baselocationX+shiftradius*2+50,
y: baselocationY+shiftradius*4+50,
}
})
nodes.push({
group: "nodes",
data: {
is_valid: true,
isValid: true,
errors: [],
large_image: encodeURI(`data:image/svg+xml;utf-8,`),
id: "TOP_RIGHT",
invisible: true,
},
renderedPosition: {
x: baselocationX+shiftradius*2,
y: baselocationY-150,
}
})
//console.log("NODES: " , nodes)
for (var key in nodes) {
cy.add(nodes[key]).lock()
}
changeUsecase(selectedUsecase, usecaseType)
if (inputUsecase !== undefined && inputUsecase !== null) {
for (var key in inputUsecase.process) {
if (inputUsecase.process[key].source === "" || inputUsecase.process[key].target === "") {
continue
}
inputUsecase.process[key].label = parseInt(key)+1
inputUsecase.process[key].id = uuidv4();
cy.add({
group: "edges",
data: inputUsecase.process[key],
})
}
//changeUsecase(inputUsecase, 0)
//setSelectedUsecase(value)
}
}
if (selectedOption !== undefined && selectedUsecase !== selectedOption) {
setSelectedUsecase(selectedOption)
changeUsecase(selectedOption, usecaseType)
}
const UsecaseHandler = (props) => {
const { data, index, diff } = props
const leftImage = data.left_image !== undefined ? parsedDatatypeImages[data.left_image] : undefined
const rightImage = data.right_image !== undefined ? parsedDatatypeImages[data.right_image] : undefined
if (leftImage === undefined) {
console.log("LEFT MISSING: ", leftImage)
}
if (rightImage === undefined) {
console.log("Right MISSING: ", rightImage)
}
const parsedRightImage =
const parsedRightText =