Question: I have an open-source matrix of data, the Mitre ATT&CK Cyberthreat Intel ( Matrix - Enterprise | MITRE ATT&CK®).
How do i make the matrix like a tree, where column headings are laid out with a tidy tree, and the rows/sub-rows are laid out with an indented tree algorithm? the aim is to be able to collapse/expand the tree, since we need to use it for knowledge exploration. The process requires users to search through techniques till they find and select the one to suit their scenario.
The original table looks like this
I have table-like structure in a tree-data-shape, where there are:
- Matrix: A matrix that holds all of the data
- Columns: Tactics that act as column headings in the table
- Rows: techniques that act as rows in the table
- Sub-Rows: Subtechniques that act as sub-rows to the rows
The aim is to create this in a tree-like structure that looks similar to table. I have a rough mock-up below.
The four key features are:
- The matrix and tactics nodes are laid out by a vertical tidy tree,
- The technique nodes are laid out by a vertical indented tree
- The subtechniques can be indented off the techniques, but inside their box
- The tree can be collapsed or expanded at will
Is this possible to achieve with D3, or do i need to shift to another library. Can anyone help me achieve this please?
I have so far made two tries at this (I am not strong at JS):
- Try1 which focuses on building the tree data, with only a simple tree (i.e. you can see there are too many categories for standard layout Mitre ATT&CK Try 1. / brettforbes | Observable (observablehq.com)
- Try 2 which uses the dataset, and has a more sophisticated, node-based layout Mitre ATT&CK Try 2. / brettforbes | Observable (observablehq.com)
the visual aim is to look something like this diagram below.
- There are a range of tactics that can be collapsed or expanded, shown/hidden
- On the left, the view shows techniques-only, laid out under the tactic using a vertical indented tree
- On the right it shows the view of when sub-techniques are on, then subtechniques are inside the technique box
- All components are collapsible/expandible
Version 2 may be a useful springboard, since the rectangles and the text appear, it is the layout that is wrong. Can this goal be achieved?
I would probably model this as an HTML nested list so that you can use CSS grids and Flexbox to arrange the items, and let the browser handle most of the layout complexities for you. If you wrap your sublists in
<details> you can probably even get away without any JS at all in the rendered markup.
hey thats a super interesting idea, thanks. I guess I’m more of a Python programmer, and hadn’t really thought it through from that angle, so thats a real insight, cheers.
I hadn’t considered this because i am guessing this is the way the current mitre navigator is done, and their current tech is really inflexible to use. Its a static table, and you cannot drill into any additional data using their current tool (i.e. select a box and drill into and expose more detail behind it). There are many layers of knowledge to this thing.
One thing i was looking for was flexible, expansion/collapse and knowledge drill-down mechanisms. Because I want to show a whole lot more data (i.e. close some boxes and open more), once any one of the blocks are clicked. This is why i was thinking of D3
Does this expanded use case change your mind back to D3? Or do you think this could also be handled using your approach? I am not sufficiently knowledgeable to tell.
I was checking out flextree ( Klortho/d3-flextree: Flexible tree layout algorithm that allows for variable node sizes (github.com)), and was wondering whether i would have to build something similar, but obviously with a different layout (i.e. different pseudo-code approach to the papers).
This 350 lines of JS does seem tricky though. Thoughts?
In my mind the only argument that would speak for an SVG layout would be that you can export it as an image, and arguably you can do the same by converting an HTML DOM to SVG.
Trees by themselves aren’t difficult. It’s the nested layouts that make things tricky (propagate layout changes when dimensions of nested nodes change, calculate offsets and orientation, deal with long lines of text, etc). The browser can already handle all of these things for you. With
<details> you also get the benefit that even collapsed nodes remain searchable through the browser’s in-page search and will automatically expand if they contain a match.
Event zooming and panning HTML elements is possible. I have a helper for that in Syntax Tree Chart / Fabian Iwand | Observable
My recommendation would be:
- Start by generating nested
<ul>s from your data
- Wrap each
<details>, using the node title as
- Add the node depth either as class or as
data- attribute so that you can target each level via CSS
- Start prototyping your CSS in a separate cell. That way you don’t have to invalidate the built DOM every time, and can even use the browser’s devtools to try different things before applying them.
Here’s a “basic” example (as in, I didn’t attempt to draw links, but I’d also argue that they might not be necessary): https://observablehq.com/d/a3fcb62fa23af22d
You’re a genius and a very cool person @mootari it is greatly appreciated. Its given me a lot to think about. Let me cogitate on it and come back to you.
But thank you so much for helping me, you have great skill and i appreciate you spending time on me, cheers