Sigma.JS custom rendering

23 views Asked by At

I'm trying to visualize the data coming through the API with Sigma.JS, but I can't always get results. When I tried to visualize the dynamic incoming data without mock data by writing a simple API with Flask, it worked, but this data is slightly different from the real JSON data of the project, I can't integrate the new incoming data, although I took custom rendering as an example, I couldn't solve it. I will be leaving the JSON data I will be using below. In the nodes section, the JSON data is divided into two groups according to the y index in the form of attacker and destination, think of them as SIEM logs. ip is available in the id section, attackType in the label section

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Sigma.js Example</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/2.4.0/sigma.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/graphology/0.25.4/graphology.umd.min.js"></script>
  <style>
    #container {
      width: 100%;
      height: 100vh;
      background: white;
    }
  </style>
</head>
<body>
  <div id="container"></div>
  <script>
    const graph = new graphology.Graph();

    function shuffleArray(array) {
      for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
      }
    }

    async function fetchAttackTypes() {
      try {
        const response = await fetch('http://127.0.0.1:5000/data');
        const data = await response.json();
        return data.attackTypes;
      } catch (error) {
        console.error('Error:', error);
        return [];
      }
    }

    async function renderGraph() {
      const attackTypes = await fetchAttackTypes();

      shuffleArray(attackTypes);

      attackTypes.forEach((type, index) => {
        const angle = index * (2 * Math.PI / attackTypes.length);
        const x = 200 * Math.cos(angle);
        const y = 200 * Math.sin(angle);
        graph.addNode(type, { label: type, x, y, size: 10, color: '#00f' });
      });

      attackTypes.forEach(type => {
        const otherNodes = attackTypes.filter(otherType => otherType !== type);
        const hasConnections = graph.neighbors(type).length > 0;
        if (!hasConnections) {
          const randomIndex = Math.floor(Math.random() * otherNodes.length);
          const randomType = otherNodes[randomIndex];
          graph.addEdge(type, randomType, { color: '#f00' });
        }
      });

      const sigmaInstance = new Sigma(graph, document.getElementById("container"));

      sigmaInstance.on('overNode', function(e) {
        e.data.node.color = '#f00';
        e.data.node.size *= 2;
        sigmaInstance.refresh();
      });

      sigmaInstance.on('outNode', function(e) {
        e.data.node.color = '#00f';
        e.data.node.size /= 2;
        sigmaInstance.refresh();
      });
    }

    renderGraph();
  </script>
</body>
</html>

nodes.json

"nodes": [
    {
      "color": "blue",
      "id": "59.166.0.9",
      "label": Exploit,
      "size": 10,
      "x": 0,
      "y": 0
    },
    {
      "color": "blue",
      "id": "149.171.126.1",
      "label": Fuzzing,
      "size": 10,
      "x": 0,
      "y": 0
    },
    {
      "color": "blue",
      "id": "59.166.0.2",
      "label": NaN,
      "size": 10,
      "x": 0,
      "y": 1
    },
    {
      "color": "blue",
      "id": "149.171.126.7",
      "label": NaN,
      "size": 10,
      "x": 0,
      "y": 1
    },
    {
      "color": "blue",
      "id": "59.166.0.9",
      "label": NaN,
      "size": 10,
      "x": 0,
      "y": 2
    },
    {
      "color": "blue",
      "id": "149.171.126.4",
      "label": NaN,
      "size": 10,
      "x": 0,
      "y": 2
    },
    {
      "color": "blue",
      "id": "59.166.0.0",
      "label": NaN,
      "size": 10,
      "x": 0,
      "y": 3
    },
    {
      "color": "blue",
      "id": "149.171.126.3",
      "label": NaN,
      "size": 10,
      "x": 0,
      "y": 3
    }
]

edges.json

"edges": [
    {
      "color": "purple",
      "id": "e1_1000",
      "size": 5,
      "source": "175.45.176.1",
      "target": "149.171.126.10"
    },
    {
      "color": "purple",
      "id": "e1_1001",
      "size": 5,
      "source": "175.45.176.1",
      "target": "149.171.126.10"
    },
    {
      "color": "purple",
      "id": "e1_1002",
      "size": 5,
      "source": "175.45.176.0",
      "target": "149.171.126.14"
    },
    {
      "color": "purple",
      "id": "e1_1003",
      "size": 5,
      "source": "149.171.126.18",
      "target": "175.45.176.3"
    },
    {
      "color": "purple",
      "id": "e1_1004",
      "size": 5,
      "source": "149.171.126.18",
      "target": "175.45.176.3"
    },
]

Image of the code I wrote while it is running: Image of the code I wrote while it is running

I need to show the incoming data: I need to show the incoming data

Processing the data sent as JSON in the backend

graph_data = {"nodes": [], "edges": []}

def update_graph_data():
    global graph_data
    data_iterator = load_data()
    for i, data in enumerate(data_iterator):
        for index, row in data.iterrows():
            if row['attack_cat'] != "nan":
                graph_data["nodes"].append({"id": row['srcip'], "label": row['attack_cat'], "x": i, "y": index, "size": 10, "color": "blue"})
                graph_data["nodes"].append({"id": row['dstip'], "label": row['attack_cat'], "x": i, "y": index, "size": 10, "color": "blue"})
                if i > 0:
                    graph_data["edges"].append({"id": f"e{i}_{index}", "source": row['srcip'], "target": row['dstip'], "size": 5, "color": "purple"})
        time.sleep(1)
0

There are 0 answers