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 { Paper, Typography, Divider, IconButton, Badge, CircularProgress, Tooltip, } 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, size, inputUsecase, isLoggedIn, color, discoveryWrapper, setDiscoveryWrapper} = 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 [newSelectedApp, setNewSelectedApp] = React.useState({}) const [defaultSearch, setDefaultSearch] = React.useState("") const [animationStarted, setAnimationStarted] = React.useState(false) const [paperTitle, setPaperTitle] = React.useState("") const scale = size === undefined ? 1 : size > 5 ? 3 : size const alert = useAlert() 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 (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(() => { if (discoveryData.id === undefined) { return } if (newSelectedApp.objectID === undefined || newSelectedApp.objectID === undefined || newSelectedApp.objectID.length === 0) { return } if (paperTitle.length > 0) { setDiscoveryWrapper({}) setSelectionOpen(false) } 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`) } setFrameworkItem(submitValue) }, [newSelectedApp]) const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"; const imgSize = 50; var parsedFrameworkData = 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 [usecaseType, setUsecaseType] = React.useState(0) const [selectedUsecase, setSelectedUsecase] = React.useState(selectedOption !== undefined ? selectedOption : "Phishing") 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 onNodeSelect = (event) => { const data = event.target.data(); console.log("Node: ", data) if (data.id === "SHUFFLE") { event.target.unselect() return } 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("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 =
{data.right_text}
const parsedLeftImage = const parsedLeftText =
{data.left_text}
const svgSize = 20 var svgIcon = if (data.direction === "right") { svgIcon = } else if (data.direction === "left") { svgIcon = } //{"usecase_directional_arrow_"+index} // const handleHover = () => { //console.log("Hover IN: ", data.automated) const allEdges = cy.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() } } //const newedges = usecases[value][parsedType] for (var key in data.automated) { data.automated[key].label = parseInt(key)+1 if (data.automated[key].description !== undefined && data.automated[key].description !== null && data.automated[key].description.length > 0) { data.automated[key].label = (parseInt(key)+1)+" "+data.automated[key].description } cy.add({ group: "edges", data: data.automated[key], }) } } const handleHoverOut = () => { //console.log("Hover out: ", data.automated) //const allEdges = cy.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() // } //} } const bgColor = color === undefined || color === null || color.length === 0 ? theme.palette.surfaceColor : color console.log("BGCOLOR: ", bgColor) return ( {data.name}
{parsedLeftImage} {parsedLeftText}
{svgIcon}
{parsedRightImage} {parsedRightText}
) } const selectedUsecases = [ { "name": "Sync tickets", "description": "Do cool shit weeeee - this just ensure they are syncing", "left_text": "Cases", "right_text": "Cases", "left_image": "Cases", "right_image": "Cases", "direction": "both", "manual": [], "automated": [ { "source": "CASES", "target": "SHUFFLE", "description": "Get cases", "human": false, }, { "source": "SHUFFLE", "target": "CASES", "description": "Update cases", "human": false, }, ] }, { "name": "Forward alerts with enrichment", "description": "Do cool shit weeeee - this just ensure they are syncing", "left_text": "EDR & AV", "right_text": "Cases", "left_image": "EDR & AV", "right_image": "Cases", "direction": "right", "manual": [], "automated": [ { "source": "BOTTOM_LEFT", "target": "COMMS", "description": "Email received", "human": false, }, ] } ] //autounselectify={true} var usecasediff = -100 const bgColor = color === undefined || color === null || color.length === 0 ? theme.palette.surfaceColor : color return (
{showOptions === false ? null :
{Object.keys(usecases).map((data, index) => { return( ) })}
} {/* Object.getOwnPropertyNames(discoveryData).length > 0 ?
Use-cases {selectedUsecases.map((data, index) => { usecasediff += 175 return ( ) })}
: null*/} { Object.getOwnPropertyNames(discoveryData).length > 0 ? {paperTitle.length > 0 ? {paperTitle} : null} { //cy.elements().unselectify(); cy.elements().unselect() e.preventDefault(); setDiscoveryData({}) setDefaultSearch("") setPaperTitle("") }} > {/* {/*Causes errors in Cytoscape. Removing for now.} { e.preventDefault(); setDiscoveryData({ "id": discoveryData.id, "label": discoveryData.label, "name": "" }) setNewSelectedApp({ "image_url": "", "name": "", "id": "", "objectID": "remove", }) setSelectionOpen(true) setDefaultSearch("") const foundelement = cy.getElementById(discoveryData.id) if (foundelement !== undefined && foundelement !== null) { console.log("element: ", foundelement) foundelement.data("large_image", discoveryData.large_image) foundelement.data("text_margin_y", "14px") foundelement.data("margin_x", "32px") foundelement.data("margin_y", "19x") foundelement.data("width", "45px") foundelement.data("height", "45px") } setTimeout(() => { setDiscoveryData({}) setNewSelectedApp({}) }, 1000) }} > */}
{discoveryData.name !== undefined && discoveryData.name !== null && discoveryData.name.length > 0 ?
{discoveryData.id} 0 ? newSelectedApp.image_url : discoveryData.large_image} style={{height: 40, width: 40, margin: "auto",}}/>
: {discoveryData.id} } {discoveryData.name !== undefined && discoveryData.name !== null && discoveryData.name.length > 0 ? discoveryData.name : newSelectedApp.name !== undefined && newSelectedApp.name !== null && newSelectedApp.name.length > 0 ? newSelectedApp.name : `No ${discoveryData.label} app chosen` }
{discoveryData !== undefined && discoveryData.name !== undefined && discoveryData.name !== null && discoveryData.name.length > 0 ? {discoveryData.description} {/*isCloud && defaultSearch !== undefined && defaultSearch.length > 0 ? {< newSelectedApp={newSelectedApp} setNewSelectedApp={setNewSelectedApp} defaultSearch={defaultSearch} />} : null */} : selectionOpen ? Click an app below to select it : }
{selectionOpen ? : null}
: null } { // FIXME: There's something specific loading when // you do the first hover of a node. Why is this different? //console.log("CY: ", incy) setCy(incy) }} /> {isCloud && inputUsecase !== undefined && inputUsecase !== null && isLoggedIn === true && Object.keys(inputUsecase).length > 0 ? : null}
) } export default Framework;