diff --git a/backend/app_sdk/app_base.py b/backend/app_sdk/app_base.py index 34105383..9d8e6592 100644 --- a/backend/app_sdk/app_base.py +++ b/backend/app_sdk/app_base.py @@ -823,7 +823,7 @@ class AppBase: returns = [] for item in value: self.logger.info("VALUE: %s" % item) - if len(item) != 36: + if len(item) != 36 and not item.startswith("file_"): self.logger.info("Bad length for file value %s" % item) continue #return { diff --git a/backend/app_sdk/build.sh b/backend/app_sdk/build.sh index 20372b62..a8be1c76 100644 --- a/backend/app_sdk/build.sh +++ b/backend/app_sdk/build.sh @@ -3,7 +3,7 @@ ### DEFAULT NAME=shuffle-app_sdk -VERSION=0.9.58 +VERSION=0.9.59 docker rmi docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION --force docker build . -f Dockerfile -t frikky/shuffle:app_sdk -t frikky/$NAME:$VERSION -t docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION -t ghcr.io/frikky/$NAME:$VERSION -t ghcr.io/frikky/$NAME:nightly diff --git a/backend/go-app/go.mod b/backend/go-app/go.mod index 86e33d11..09a4b486 100644 --- a/backend/go-app/go.mod +++ b/backend/go-app/go.mod @@ -2,7 +2,7 @@ module main go 1.16 -//replace github.com/shuffle/shuffle-shared => ../../../shuffle-shared +replace github.com/shuffle/shuffle-shared => ../../../shuffle-shared //replace github.com/frikky/kin-openapi => ../../../../git/kin-openapi //replace github.com/frikky/go-elasticsearch => ../../../../git/go-elasticsearch diff --git a/backend/go-app/main.go b/backend/go-app/main.go index 5cd17cd7..a8b52797 100644 --- a/backend/go-app/main.go +++ b/backend/go-app/main.go @@ -5875,10 +5875,13 @@ func initHandlers() { r.HandleFunc("/api/v1/apps/authentication/{appauthId}/config", shuffle.SetAuthenticationConfig).Methods("POST", "OPTIONS") r.HandleFunc("/api/v1/apps/authentication/{appauthId}", shuffle.DeleteAppAuthentication).Methods("DELETE", "OPTIONS") - // Related to + // Related to NFT things r.HandleFunc("/api/v1/workflows/collections/load", shuffle.LoadCollections).Methods("POST", "OPTIONS") r.HandleFunc("/api/v1/workflows/collections/{key}", shuffle.HandleGetCollection).Methods("GET", "OPTIONS") + // Related to use-cases that are not directly workflows. + r.HandleFunc("/api/v1/workflows/usecases", shuffle.LoadUsecases).Methods("GET", "OPTIONS") + // Legacy app things r.HandleFunc("/api/v1/workflows/apps/validate", validateAppInput).Methods("POST", "OPTIONS") r.HandleFunc("/api/v1/workflows/apps", getWorkflowApps).Methods("GET", "OPTIONS") diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index 952cb4d1..09ef01d4 100644 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -1351,7 +1351,7 @@ const AngularWorkflow = (defaultprops) => { // This can be used to only show prioritzed ones later // Right now, it can prioritize authenticated ones //"Testing", - const internalIds = ["Shuffle Tools", "http"]; + const internalIds = ["Shuffle Tools", "http", "email"]; const getAppAuthentication = (reset, updateAction) => { fetch(globalUrl + "/api/v1/apps/authentication", { diff --git a/frontend/src/views/Dashboard.jsx b/frontend/src/views/Dashboard.jsx index 8a2986d8..ee9327ec 100644 --- a/frontend/src/views/Dashboard.jsx +++ b/frontend/src/views/Dashboard.jsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import { useInterval } from "react-powerhooks"; // nodejs library that concatenates classes import classNames from "classnames"; @@ -32,18 +32,316 @@ import { RadialPointSeries, RadialArea, RadialLine, + TreeMap, + TreeMapSeries, + TreeMapLabel, + TreeMapRect, } from 'reaviz'; -const keys = [ - { key: '1. Collect & Distribute', data: 2 }, - { key: '2. Enrich', data: 11 }, - { key: '3. Detect', data: 3 }, - { key: '4. Respond', data: 4 }, - { key: '5. Report', data: 12 }, - { key: '6. Validate', data: 7, color: "red",}, +const categorydata = [ + { + "name": "1. Collect & Distribute", + "list": [ + { + "name": "2-way Ticket synchronization", + "items": {} + }, + { + "name": "Email management", + "items": { + "name": "Release a quarantined message", + "items": {} + } + }, + { + "name": "EDR to ticket", + "items": { + "name": "Get host information", + "items": {} + } + }, + { + "name": "SIEM to ticket", + "items": {} + }, + { + "name": "ChatOps", + "items": {} + }, + { + "name": "Threat Intel received", + "items": {} + }, + { + "name": "Domain investigation with LetsEncrypt", + "items": {} + }, + { + "name": "Botnet tracker", + "items": {} + }, + { + "name": "Get running containers", + "items": {} + }, + { + "name": "Assign tickets", + "items": {} + }, + { + "name": "Firewall alerts", + "items": { + "name": "URL filtering", + "items": {} + } + }, + { + "name": "IDS/IPS alerts", + "items": { + "name": "Manage policies", + "items": {} + } + }, + { + "name": "Deduplicate information", + "items": {} + }, + { + "name": "Correlate information", + "items": {} + } + ] + }, + { + "name": "3. Detect", + "list": [ + { + "name": "Search SIEM (Sigma)", + "items": { + "name": "Endpoint", + "items": {} + } + }, + { + "name": "Search EDR (OSQuery)", + "items": {} + }, + { + "name": "Search emails (Phish)", + "items": { + "name": "Check headers and IOCs", + "items": {} + } + }, + { + "name": "Search IOCs (ioc-finder)", + "items": {} + }, + { + "name": "Search files (Yara)", + "items": {} + }, + { + "name": "Correlate tickets", + "items": {} + }, + { + "name": "Honeypot access", + "items": { + "name": "...", + "items": {} + } + } + ] + }, + { + "name": "Verify", + "list": [ + { + "name": "Discover vulnerabilities", + "items": {} + }, + { + "name": "Discover assets", + "items": {} + }, + { + "name": "Ensure policies are followed", + "items": {} + }, + { + "name": "Find Inactive users", + "items": {} + }, + { + "name": "Ensure access rights match HR systems", + "items": {} + }, + { + "name": "Ensure onboarding is followed", + "items": {} + }, + { + "name": "Third party apps in SaaS", + "items": {} + }, + { + "name": "Devices used for your cloud account", + "items": {} + }, + { + "name": "Too much access in GCP/Azure/AWS/ other clouds", + "items": {} + }, + { + "name": "Certificate validation", + "items": {} + }, + { + "name": "Monitor new DNS entries for domain with passive DNS", + "items": {} + }, + { + "name": "Monitor and track password dumps", + "items": {} + }, + { + "name": "Monitor for mentions of domain on darknet sites", + "items": {} + }, + { + "name": "Reporting", + "items": { + "name": "Monthly reports", + "items": { + "name": "...", + "items": {} + } + } + } + ] + }, + { + "name": "4. Respond", + "list": [ + { + "name": "Eradicate malware", + "items": {} + }, + { + "name": "Quarantine host(s)", + "items": {} + }, + { + "name": "Trigger scans", + "items": {} + }, + { + "name": "Update indicators (FW, EDR, SIEM...)", + "items": {} + }, + { + "name": "Autoblock activity when threat intel is received", + "items": {} + }, + { + "name": "Lock/Delete/Reset account", + "items": {} + }, + { + "name": "Lock vault", + "items": {} + }, + { + "name": "Increase authentication", + "items": {} + }, + { + "name": "Trigger scans", + "items": {} + }, + { + "name": "Get policies from assets", + "items": {} + } + ] + }, + { + "name": "2. Enrich", + "list": [ + { + "name": "Internal Enrichment", + "items": { + "name": "...", + "items": {} + } + }, + { + "name": "External historical Enrichment", + "items": { + "name": "...", + "items": {} + } + }, + { + "name": "Realtime", + "items": { + "name": "Analyze screenshots", + "items": {} + } + }, + { + "name": "Ticketing webhook verification", + "items": {} + } + ] + } ] -const RadialChart = () => { +const TreeChart = ({keys}) => { + const [hovered, setHovered] = useState(""); + + return ( +
{ + console.log("Click: ", hovered) + }}> + { + return info.color + }} + label={ + + } + rect={ + { + console.log("Click: ", event) + }} + /> + } + /> + } + /> +
+ ) + //axis={} +} + + +const RadialChart = ({keys}) => { const [hovered, setHovered] = useState(""); return ( @@ -137,11 +435,70 @@ const Dashboard = (props) => { const [stats, setStats] = useState({}); const [changeme, setChangeme] = useState(""); const [statsRan, setStatsRan] = useState(false); + const [keys, setKeys] = useState([]) + const [treeKeys, setTreeKeys] = useState([]) + + //const keys = [ + // { key: '1. Collect & Distribute', data: 2 }, + // { key: '2. Enrich', data: 11 }, + // { key: '3. Detect', data: 3 }, + // { key: '4. Respond', data: 4 }, + // { key: 'Validation', data: 7, color: "red",}, + //] document.title = "Shuffle - dashboard"; var dayGraphLabels = [60, 80, 65, 130, 80, 105, 90, 130, 70, 115, 60, 130]; var dayGraphData = [60, 80, 65, 130, 80, 105, 90, 130, 70, 115, 60, 130]; + const handleKeysetting = (categorydata) => { + var allCategories = [] + var treeCategories = [] + for (key in categorydata) { + const category = categorydata[key] + console.log("cat: ", category) + allCategories.push({"key": category.name, "data": category.list.length,}) + treeCategories.push({"key": category.name, "data": 100, "color": category.color,}) + for (var subkey in category.list) { + treeCategories.push({"key": category.list[subkey].name, "data": 20, "color": category.color}) + } + } + + setKeys(allCategories) + setTreeKeys(treeCategories) + } + + const fetchUsecases = () => { + fetch(globalUrl + "/api/v1/workflows/usecases", { + method: "GET", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for usecases"); + } + + return response.json(); + }) + .then((responseJson) => { + if (responseJson.success !== false) { + console.log("Usecases: ", responseJson) + handleKeysetting(responseJson) + } + }) + .catch((error) => { + //alert.error("ERROR: " + error.toString()); + console.log("ERROR: " + error.toString()); + }); + }; + + useEffect(() => { + fetchUsecases() + }, []); + const fetchdata = (stats_id) => { fetch(globalUrl + "/api/v1/stats/" + stats_id, { method: "GET", @@ -291,8 +648,8 @@ const Dashboard = (props) => { if (firstRequest) { console.log("HELO"); setFirstRequest(false); - start(); - runUpdate(); + //start(); + //runUpdate(); } else if (!statsRan) { // FIXME: Run this under runUpdate schedule? // 1. Fix labels in dayGraphy.data @@ -391,8 +748,14 @@ const Dashboard = (props) => { ) : null; const data = ( -
- +
+ {keys.length > 0 ? + + : null} + + {treeKeys.length > 0 ? + + : null} {/* { var upload = ""; const [workflows, setWorkflows] = React.useState([]); + const [_, setUpdate] = React.useState(""); // Used for rendering, don't remove + const [selectedUsecases, setSelectedUsecases] = React.useState([]); const [filteredWorkflows, setFilteredWorkflows] = React.useState([]); const [selectedWorkflow, setSelectedWorkflow] = React.useState({}); const [workflowDone, setWorkflowDone] = React.useState(false); @@ -510,6 +520,8 @@ const Workflows = (props) => { const [actionImageList, setActionImageList] = React.useState([]); const [firstLoad, setFirstLoad] = React.useState(true); + const [showMoreClicked, setShowMoreClicked] = React.useState(false); + const [usecases, setUsecases] = React.useState([]); const isCloud = window.location.host === "localhost:3002" || @@ -869,8 +881,10 @@ const Workflows = (props) => { .then((responseJson) => { if (responseJson !== undefined) { setWorkflows(responseJson); + fetchUsecases(responseJson) if (responseJson !== undefined) { + var actionnamelist = []; var parsedactionlist = []; for (var key in responseJson) { @@ -910,6 +924,83 @@ const Workflows = (props) => { }); }; + const handleKeysetting = (categorydata, workflows) => { + console.log("Workflows: ", workflows) + //workflows[0].category = ["detect"] + //workflows[0].usecase_ids = ["Correlate tickets"] + + if (workflows !== undefined && workflows !== null) { + const newcategories = [] + for (var key in categorydata) { + var category = categorydata[key] + category.matches = [] + + for (var subcategorykey in category.list) { + var subcategory = category.list[subcategorykey] + subcategory.matches = [] + + for (var workflowkey in workflows) { + const workflow = workflows[workflowkey] + + if (workflow.usecase_ids !== undefined && workflow.usecase_ids !== null) { + for (var usecasekey in workflow.usecase_ids) { + if (workflow.usecase_ids[usecasekey].toLowerCase() === subcategory.name.toLowerCase()) { + console.log("Got match: ", workflow.usecase_ids[usecasekey]) + + category.matches.push({ + "workflow": workflow.id, + "category": subcategory.name, + }) + subcategory.matches.push(workflow.id) + break + } + } + } + + if (subcategory.matches.length > 0) { + break + } + } + } + + newcategories.push(category) + } + + console.log("Categories: ", newcategories) + setUsecases(newcategories) + } else { + setUsecases(categorydata) + } + } + + const fetchUsecases = (workflows) => { + fetch(globalUrl + "/api/v1/workflows/usecases", { + method: "GET", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for usecases"); + } + + return response.json(); + }) + .then((responseJson) => { + if (responseJson.success !== false) { + console.log("Usecases: ", responseJson) + handleKeysetting(responseJson, workflows) + } + }) + .catch((error) => { + //alert.error("ERROR: " + error.toString()); + console.log("ERROR: " + error.toString()); + }); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => { if (workflows.length <= 0) { @@ -918,7 +1009,6 @@ const Workflows = (props) => { setView(tmpView); } - //setFirstrequest(false); getAvailableWorkflows(); } }, []) @@ -1392,6 +1482,11 @@ const Workflows = (props) => { if (data.tags !== undefined && data.tags !== null) { setNewWorkflowTags(JSON.parse(JSON.stringify(data.tags))); } + + console.log("Editing: ", data) + if (data.usecase_ids !== undefined && data.usecase_ids !== null && data.usecase_ids.length > 0) { + setSelectedUsecases(data.usecase_ids) + } }} key={"change"} > @@ -1785,7 +1880,8 @@ const Workflows = (props) => { tags, defaultReturnValue, editingWorkflow, - redirect + redirect, + currentUsecases, ) => { var method = "POST"; var extraData = ""; @@ -1812,6 +1908,12 @@ const Workflows = (props) => { workflowdata["default_return_value"] = defaultReturnValue; } + if (currentUsecases !== undefined && currentUsecases !== null) { + workflowdata["usecase_ids"] = currentUsecases + //workflows[0].category = ["detect"] + //workflows[0].usecase_ids = ["Correlate tickets"] + } + return fetch(globalUrl + "/api/v1/workflows" + extraData, { method: method, headers: { @@ -2289,6 +2391,7 @@ const Workflows = (props) => { return
{workflowData}
; }; + var total_count = 0 const modalView = modalOpen ? ( { }} color="primary" placeholder="Name" + required margin="dense" defaultValue={newWorkflowName} autoFocus @@ -2346,47 +2450,115 @@ const Workflows = (props) => { color="primary" defaultValue={newWorkflowDescription} placeholder="Description" - rows="3" multiline margin="dense" fullWidth /> - { - newWorkflowTags.push(chip); - setNewWorkflowTags(newWorkflowTags); - }} - onDelete={(chip, index) => { - newWorkflowTags.splice(index, 1); - setNewWorkflowTags(newWorkflowTags); - }} - /> +
+ { + newWorkflowTags.push(chip); + setNewWorkflowTags(newWorkflowTags); + }} + onDelete={(chip, index) => { + newWorkflowTags.splice(index, 1); + setNewWorkflowTags(newWorkflowTags); + }} + /> + + Usecases + + +
+ + {showMoreClicked ? + + setDefaultReturnValue(event.target.value)} + InputProps={{ + style: { + color: "white", + }, + }} + color="primary" + defaultValue={defaultReturnValue} + placeholder="Default return value (used for Subflows if the subflow fails)" + rows="3" + multiline + margin="dense" + fullWidth + /> + + : null} + + { + setShowMoreClicked(!showMoreClicked); + }} + > + {showMoreClicked ? : } + + - setDefaultReturnValue(event.target.value)} - InputProps={{ - style: { - color: "white", - }, - }} - color="primary" - defaultValue={defaultReturnValue} - placeholder="Default return value (used for Subflows if the subflow fails)" - rows="3" - multiline - margin="dense" - fullWidth - />
diff --git a/functions/onprem/worker/worker.go b/functions/onprem/worker/worker.go index 9b634e90..e3d988ef 100644 --- a/functions/onprem/worker/worker.go +++ b/functions/onprem/worker/worker.go @@ -375,8 +375,10 @@ func deployApp(cli *dockerclient.Client, image string, identifier string, env [] DeployContainer(ctx, cli, config, hostConfig, identifier, workflowExecution, newExecId) }) } else { - log.Printf("[DEBUG] Running app %s in docker NORMALLY as there is no delay set", action.Name) - return DeployContainer(ctx, cli, config, hostConfig, identifier, workflowExecution, newExecId) + log.Printf("[DEBUG] Running app %s in docker NORMALLY as there is no delay set with identifier %s", action.Name, identifier) + returnvalue := DeployContainer(ctx, cli, config, hostConfig, identifier, workflowExecution, newExecId) + log.Printf("[DEBUG] Normal deploy ret: %s", returnvalue) + return returnvalue } return nil @@ -397,9 +399,9 @@ func DeployContainer(ctx context.Context, cli *dockerclient.Client, config *cont if !strings.Contains(err.Error(), "Conflict. The container name") { log.Printf("[ERROR] Container CREATE error (1): %s", err) - err = shuffle.DeleteCache(ctx, newExecId) - if err != nil { - log.Printf("[ERROR] FAILED Deleting cache for %s: %s", newExecId, err) + cacheErr := shuffle.DeleteCache(ctx, newExecId) + if cacheErr != nil { + log.Printf("[ERROR] FAILED Deleting cache for %s: %s", newExecId, cacheErr) } return err @@ -420,9 +422,10 @@ func DeployContainer(ctx context.Context, cli *dockerclient.Client, config *cont if err != nil { log.Printf("[ERROR] Container create error (2): %s", err) - err = shuffle.DeleteCache(ctx, newExecId) - if err != nil { - log.Printf("[ERROR] FAILED Deleting cache for %s: %s", newExecId, err) + + cacheErr := shuffle.DeleteCache(ctx, newExecId) + if cacheErr != nil { + log.Printf("[ERROR] FAILED Deleting cache for %s: %s", newExecId, cacheErr) } return err @@ -457,9 +460,9 @@ func DeployContainer(ctx context.Context, cli *dockerclient.Client, config *cont if err != nil { log.Printf("[ERROR] Container create error (3): %s", err) - err = shuffle.DeleteCache(ctx, newExecId) - if err != nil { - log.Printf("[ERROR] FAILED Deleting cache for %s: %s", newExecId, err) + cacheErr := shuffle.DeleteCache(ctx, newExecId) + if cacheErr != nil { + log.Printf("[ERROR] FAILED Deleting cache for %s: %s", newExecId, cacheErr) } return err @@ -472,9 +475,9 @@ func DeployContainer(ctx context.Context, cli *dockerclient.Client, config *cont if err != nil { log.Printf("[ERROR] Failed to start container in environment %s: %s", environment, err) - err = shuffle.DeleteCache(ctx, newExecId) - if err != nil { - log.Printf("[ERROR] FAILED Deleting cache for %s: %s", newExecId, err) + cacheErr := shuffle.DeleteCache(ctx, newExecId) + if cacheErr != nil { + log.Printf("[ERROR] FAILED Deleting cache for %s: %s", newExecId, cacheErr) } //shutdown(workflowExecution, workflowExecution.Workflow.ID, true) @@ -1352,6 +1355,7 @@ func handleExecutionResult(workflowExecution shuffle.WorkflowExecution) { } else { err = deployApp(dockercli, images[0], identifier, env, workflowExecution, action) + log.Printf("[DEBUG] Failed deploying app? %s", err) if err != nil && !strings.Contains(err.Error(), "Conflict. The container name") { if strings.Contains(err.Error(), "exited prematurely") { log.Printf("[DEBUG] Shutting down (9)") diff --git a/functions/usecases/categories.json b/functions/usecases/categories.json index f32d9700..e438a380 100644 --- a/functions/usecases/categories.json +++ b/functions/usecases/categories.json @@ -1,522 +1,260 @@ -{ - "1. Collect & Distribute": { - "2-way Ticket synchronization": { - "name": "", - "description": "", - "image": "" - }, - "Email management": { - "name": "", - "description": "", - "image": "", - "Attachments": { - "name": "", - "description": "", - "image": "" +[ + { + "name": "1. Collect & Distribute", + "color": "#c51152", + "list": [ + { + "name": "2-way Ticket synchronization", + "items": {} }, - "Manage senders": { - "name": "", - "description": "", - "image": "" + { + "name": "Email management", + "items": { + "name": "Release a quarantined message", + "items": {} + } }, - "Manage URLs": { - "name": "", - "description": "", - "image": "" + { + "name": "EDR to ticket", + "items": { + "name": "Get host information", + "items": {} + } }, - "Encode & Decode URLs": { - "name": "", - "description": "", - "image": "" + { + "name": "SIEM to ticket", + "items": {} }, - "Release a quarantined message": { - "name": "", - "description": "", - "image": "" + { + "name": "ChatOps", + "items": {} + }, + { + "name": "Threat Intel received", + "items": {} + }, + { + "name": "Domain investigation with LetsEncrypt", + "items": {} + }, + { + "name": "Botnet tracker", + "items": {} + }, + { + "name": "Get running containers", + "items": {} + }, + { + "name": "Assign tickets", + "items": {} + }, + { + "name": "Firewall alerts", + "items": { + "name": "URL filtering", + "items": {} + } + }, + { + "name": "IDS/IPS alerts", + "items": { + "name": "Manage policies", + "items": {} + } + }, + { + "name": "Deduplicate information", + "items": {} + }, + { + "name": "Correlate information", + "items": {} } - }, - "EDR to ticket": { - "name": "", - "description": "", - "image": "", - "Fetch incidents & events": { - "name": "", - "description": "", - "image": "" - }, - "Quarantine files": { - "name": "", - "description": "", - "image": "" - }, - "Quarantine host (respond)": { - "name": "", - "description": "", - "image": "" - }, - "Get host information": { - "name": "", - "description": "", - "image": "" - } - }, - "SIEM to ticket": { - "name": "", - "description": "", - "image": "" - }, - "ChatOps": { - "name": "", - "description": "", - "image": "" - }, - "Threat Intel received": { - "name": "", - "description": "", - "image": "" - }, - "Domain investigation with LetsEncrypt": { - "name": "", - "description": "", - "image": "" - }, - "Botnet tracker": { - "name": "", - "description": "", - "image": "" - }, - "Get running containers": { - "name": "", - "description": "", - "image": "" - }, - "Assign tickets": { - "name": "", - "description": "", - "image": "" - }, - "Firewall alerts": { - "name": "", - "description": "", - "image": "", - "Block/accept policies": { - "name": "", - "description": "", - "image": "" - }, - "Add addresses and ports to groups": { - "name": "", - "description": "", - "image": "" - }, - "Support custom URL categories": { - "name": "", - "description": "", - "image": "" - }, - "Fetch logs for specific address": { - "name": "", - "description": "", - "image": "" - }, - "URL filtering": { - "name": "", - "description": "", - "image": "" - } - }, - "IDS/IPS alerts": { - "name": "", - "description": "", - "image": "", - "Get/Fetch alerts": { - "name": "", - "description": "", - "image": "" - }, - "Receive alerts real-time": { - "name": "", - "description": "", - "image": "" - }, - "Get PCAP files": { - "name": "", - "description": "", - "image": "" - }, - "Get network logs": { - "name": "", - "description": "", - "image": "" - }, - "Manage policies": { - "name": "", - "description": "", - "image": "" - } - }, - "Deduplicate information": { - "name": "", - "description": "", - "image": "" - }, - "Correlate information": { - "name": "", - "description": "", - "image": "" - } + ] }, - "3. Detect": { - "Search SIEM (Sigma)": { - "name": "", - "description": "", - "image": "", - "Network": { - "name": "", - "description": "", - "image": "" + { + "name": "2. Enrich", + "color": "#f4c20d", + "list": [ + { + "name": "Internal Enrichment", + "items": { + "name": "...", + "items": {} + } }, - "Endpoint": { - "name": "", - "description": "", - "image": "" + { + "name": "External historical Enrichment", + "items": { + "name": "...", + "items": {} + } + }, + { + "name": "Realtime", + "items": { + "name": "Analyze screenshots", + "items": {} + } + }, + { + "name": "Ticketing webhook verification", + "items": {} } - }, - "Search EDR (OSQuery)": { - "name": "", - "description": "", - "image": "" - }, - "Search emails (Phish)": { - "name": "", - "description": "", - "image": "", - "Check malware": { - "name": "", - "description": "", - "image": "" - }, - "Check targeted": { - "name": "", - "description": "", - "image": "" - }, - "Check headers and IOCs": { - "name": "", - "description": "", - "image": "" - } - }, - "Search IOCs (ioc-finder)": { - "name": "", - "description": "", - "image": "" - }, - "Search files (Yara)": { - "name": "", - "description": "", - "image": "" - }, - "Correlate tickets": { - "name": "", - "description": "", - "image": "" - }, - "Honeypot access": { - "name": "", - "description": "", - "image": "", - "S3 Honeypot": { - "name": "", - "description": "", - "image": "" - }, - "SSH Honeypot": { - "name": "", - "description": "", - "image": "" - }, - "FTP honeypot": { - "name": "", - "description": "", - "image": "" - }, - "Network honeypot": { - "name": "", - "description": "", - "image": "" - }, - "...": { - "name": "", - "description": "", - "image": "" - } - } + ] }, - "Verify": { - "Discover vulnerabilities": { - "name": "", - "description": "", - "image": "" - }, - "Discover assets": { - "name": "", - "description": "", - "image": "" - }, - "Ensure policies are followed": { - "name": "", - "description": "", - "image": "" - }, - "Find Inactive users": { - "name": "", - "description": "", - "image": "" - }, - "Ensure access rights match HR systems": { - "name": "", - "description": "", - "image": "" - }, - "Ensure onboarding is followed": { - "name": "", - "description": "", - "image": "" - }, - "Third party apps in SaaS": { - "name": "", - "description": "", - "image": "" - }, - "Devices used for your cloud account": { - "name": "", - "description": "", - "image": "" - }, - "Too much access in GCP/Azure/AWS/ other clouds": { - "name": "", - "description": "", - "image": "" - }, - "Certificate validation": { - "name": "", - "description": "", - "image": "" - }, - "Monitor new DNS entries for domain with passive DNS": { - "name": "", - "description": "", - "image": "" - }, - "Monitor and track password dumps": { - "name": "", - "description": "", - "image": "" - }, - "Monitor for mentions of domain on darknet sites": { - "name": "", - "description": "", - "image": "" - }, - "Reporting": { - "name": "", - "description": "", - "image": "", - "Automation time saved": { - "name": "", - "description": "", - "image": "" + { + "name": "3. Detect", + "color": "#3cba54", + "list": [ + { + "name": "Search SIEM (Sigma)", + "items": { + "name": "Endpoint", + "items": {} + } }, - "Automation money saved": { - "name": "", - "description": "", - "image": "" + { + "name": "Search EDR (OSQuery)", + "items": {} }, - "Incident response report": { - "name": "", - "description": "", - "image": "" + { + "name": "Search emails (Phish)", + "items": { + "name": "Check headers and IOCs", + "items": {} + } }, - "Department cost": { - "name": "", - "description": "", - "image": "" + { + "name": "Search IOCs (ioc-finder)", + "items": {} }, - "Monthly reports": { - "name": "", - "description": "", - "image": "", - "EDR alerts": { - "name": "", - "description": "", - "image": "" - }, - "SIEM alerts": { - "name": "", - "description": "", - "image": "" - }, - "Emails quarantined": { - "name": "", - "description": "", - "image": "" - }, - "...": { - "name": "", - "description": "", - "image": "" + { + "name": "Search files (Yara)", + "items": {} + }, + { + "name": "Correlate tickets", + "items": {} + }, + { + "name": "Honeypot access", + "items": { + "name": "...", + "items": {} } } - } + ] }, - "4. Respond": { - "Eradicate malware": { - "name": "", - "description": "", - "image": "" - }, - "Quarantine host(s)": { - "name": "", - "description": "", - "image": "" - }, - "Trigger scans": { - "name": "", - "description": "", - "image": "" - }, - "Update indicators (FW, EDR, SIEM...)": { - "name": "", - "description": "", - "image": "" - }, - "Autoblock activity when threat intel is received": { - "name": "", - "description": "", - "image": "" - }, - "Lock/Delete/Reset account": { - "name": "", - "description": "", - "image": "" - }, - "Lock vault": { - "name": "", - "description": "", - "image": "" - }, - "Increase authentication": { - "name": "", - "description": "", - "image": "" - }, - "Get policies from assets": { - "name": "", - "description": "", - "image": "" - } + { + "name": "4. Respond", + "color": "#4a148c", + "list": [ + { + "name": "Eradicate malware", + "items": {} + }, + { + "name": "Quarantine host(s)", + "items": {} + }, + { + "name": "Trigger scans", + "items": {} + }, + { + "name": "Update indicators (FW, EDR, SIEM...)", + "items": {} + }, + { + "name": "Autoblock activity when threat intel is received", + "items": {} + }, + { + "name": "Lock/Delete/Reset account", + "items": {} + }, + { + "name": "Lock vault", + "items": {} + }, + { + "name": "Increase authentication", + "items": {} + }, + { + "name": "Get policies from assets", + "items": {} + } + ] }, - "2. Enrich": { - "Internal Enrichment": { - "name": "", - "description": "", - "image": "", - "Users": { - "name": "", - "description": "", - "image": "" + { + "name": "5. Verify", + "color": "#4885ed", + "list": [ + { + "name": "Discover vulnerabilities", + "items": {} }, - "Hostnames": { - "name": "", - "description": "", - "image": "" + { + "name": "Discover assets", + "items": {} }, - "IPs": { - "name": "", - "description": "", - "image": "" + { + "name": "Ensure policies are followed", + "items": {} }, - "Departments": { - "name": "", - "description": "", - "image": "" + { + "name": "Find Inactive users", + "items": {} }, - "Role": { - "name": "", - "description": "", - "image": "" + { + "name": "Ensure access rights match HR systems", + "items": {} }, - "Software": { - "name": "", - "description": "", - "image": "" + { + "name": "Ensure onboarding is followed", + "items": {} }, - "...": { - "name": "", - "description": "", - "image": "" + { + "name": "Third party apps in SaaS", + "items": {} + }, + { + "name": "Devices used for your cloud account", + "items": {} + }, + { + "name": "Too much access in GCP/Azure/AWS/ other clouds", + "items": {} + }, + { + "name": "Certificate validation", + "items": {} + }, + { + "name": "Monitor new DNS entries for domain with passive DNS", + "items": {} + }, + { + "name": "Monitor and track password dumps", + "items": {} + }, + { + "name": "Monitor for mentions of domain on darknet sites", + "items": {} + }, + { + "name": "Reporting", + "items": { + "name": "Monthly reports", + "items": { + "name": "...", + "items": {} + } + } } - }, - "External historical Enrichment": { - "name": "", - "description": "", - "image": "", - "IPs": { - "name": "", - "description": "", - "image": "" - }, - "URLs": { - "name": "", - "description": "", - "image": "" - }, - "Hashes": { - "name": "", - "description": "", - "image": "" - }, - "Files": { - "name": "", - "description": "", - "image": "" - }, - "...": { - "name": "", - "description": "", - "image": "" - } - }, - "Realtime": { - "name": "", - "description": "", - "image": "", - "File detonation": { - "name": "", - "description": "", - "image": "" - }, - "URL detonation": { - "name": "", - "description": "", - "image": "" - }, - "PCAP analysis": { - "name": "", - "description": "", - "image": "" - }, - "Analyze screenshots": { - "name": "", - "description": "", - "image": "" - } - }, - "Ticketing webhook verification": { - "name": "", - "description": "", - "image": "" - } + ] } -} \ No newline at end of file +] \ No newline at end of file diff --git a/functions/usecases/categories.rtf b/functions/usecases/categories.rtf index e66d5fbf..e19cf26a 100644 --- a/functions/usecases/categories.rtf +++ b/functions/usecases/categories.rtf @@ -3,7 +3,7 @@ {\f0\froman Arial;} } {\info -{\createim\yr2022\mo2\dy18\hr17\min49} +{\createim\yr2022\mo2\dy20\hr1\min15} } \paperw11907\paperh16840\margl1800\margr1800\margt1440\margb1440 @@ -279,7 +279,7 @@ rich \par\pard\plain \slmult0\ltrpar\li200 {\fs24 -Verify +5. Verify } \par\pard\plain \slmult0\ltrpar\li400 @@ -444,11 +444,6 @@ Increase authentication \par\pard\plain \slmult0\ltrpar\li400 {\fs24 -Trigger scans -} -\par\pard\plain -\slmult0\ltrpar\li400 -{\fs24 Get policies from assets } \par\pard\plain diff --git a/functions/usecases/read_categories.py b/functions/usecases/read_categories.py index c99c4f01..65df43c9 100644 --- a/functions/usecases/read_categories.py +++ b/functions/usecases/read_categories.py @@ -2,11 +2,16 @@ data = "" with open("categories.rtf", "r") as tmp: data = tmp.read() -fixed_json = {} +fixed_json = [] linearity = 0 heading = "" subheading = "" subsubheading = "" + +cnt = -1 +subcnt = -1 + +colors = ["#c51152", "#3cba54", "#4885ed", "#4a148c", "#f4c20d"] for line in data.split("\n"): if line == "rich": continue @@ -30,16 +35,23 @@ for line in data.split("\n"): continue if linearity == 2: - fixed_json[line] = {} + #if cnt >= 0: + # for key, value in fixed_json[cnt].items(): + # print(key, value) + + + cnt += 1 + subcnt = -1 + fixed_json.append({"name": line, "color": colors[cnt], "list": []}) heading = line elif linearity == 4: - fixed_json[heading][line] = {"name": "", "description": "", "image": ""} subheading = line + fixed_json[cnt]["list"].append({"name": line, "items": {}}) + subcnt += 1 elif linearity == 6: - fixed_json[heading][subheading][line] = {"name": "", "description": "", "image": ""} - subsubheading = line + fixed_json[cnt]["list"][subcnt]["items"] = {"name": line, "items": {}} elif linearity == 8: - fixed_json[heading][subheading][subsubheading][line] = {"name": "", "description": "", "image": ""} + fixed_json[cnt]["list"][subcnt]["items"]["items"] = {"name": line, "items": {}} else: print("No handler for %s" % line) @@ -47,6 +59,7 @@ for line in data.split("\n"): #print(data) import json filename = "categories.json" +fixed_json.sort(key=lambda x: x["name"]) with open(filename, "w+") as tmp: tmp.write(json.dumps(fixed_json, indent=4))