From 8d0602f41e3520cf94108b7079a5ee85575ec053 Mon Sep 17 00:00:00 2001 From: Rob C Date: Mon, 19 Jul 2021 11:18:13 -0700 Subject: [PATCH 1/5] Refactored aggregated dfds into one dfd function --- fluentm.py | 133 ++++++++++++++--------------------------------- requirements.txt | 1 + 2 files changed, 41 insertions(+), 93 deletions(-) diff --git a/fluentm.py b/fluentm.py index eb7e87b..4a3b860 100644 --- a/fluentm.py +++ b/fluentm.py @@ -484,7 +484,6 @@ def get(name): # DataFlow is _NOT_ an Asset class DataFlow(object): - def __init__( self, pitcher: Union[Actor, Process], @@ -541,86 +540,7 @@ def renderDfd(graph: Digraph, title: str, outputDir: str): print(graph) return f"{title}-dfd.png" -def aggregatedDfd(scenes: dict): - print("### Starting Aggregated DFD ###") - graph = Digraph("Aggregated DFD") - graph.attr(rankdir="LR", color="blue") - graph.attr("node", fontname="Arial", fontsize="14") - - clusterAttr = { - "fontname": "Arial", - "fontsize": "12", - "color": "red", - "line": "dotted", - } - - boundaryClusters = {} - - # Track which nodes should be placed in which clusters but place neither until we've built the subgraph structure. - placements = {} - edges = {} - - # Gather the boundaries and understand how they're nested (but don't nest the graphviz objects ,yet) - # Graphviz subgraphs can't have nodes added, so you need to populate a graph with nodes first, then subgraph it under another graph - for scene in scenes: - # print(f"scene: {scene}") - for flow in scenes[scene]: - # print(flow) - for e in (flow.pitcher, flow.catcher): - if e.name in placements: - continue # skip to next loop - - ptr = e - while hasattr(ptr, "boundary"): - if ptr.boundary not in boundaryClusters: - boundaryClusters[ptr.boundary] = Digraph( - name=f"cluster_{ptr.boundary.name}", - graph_attr=clusterAttr | {"label": ptr.boundary.name}, - ) - ptr = ptr.boundary - - if hasattr(e, "boundary"): - placements[e.name] = boundaryClusters[e.boundary] - else: - placements[e.name] = graph - - # Figure out which edges we need to draw (We want double ended lines) - for flow in scenes[scene]: - # Look to see if the reverse flow is already there in reverse - # If it is, update the line description to say it should go both ways - f = (flow.pitcher.name, flow.catcher.name) # Directional flow - revf = (f[1],f[0]) # Reverse that directional flow - - # First, check if the flow is already in there but the other way around - if revf in edges: - edges[revf] = "BOTH" - elif f not in edges: - edges[f] = "LR" - - # Place nodes in Graphs, ready for subgraphing - print(placements) - for n in placements: - placements[n].node(n) - - # Subgraph the nodes - for c in boundaryClusters: - if hasattr(c, "boundary"): - boundaryClusters[c.boundary].subgraph(boundaryClusters[c]) - else: - graph.subgraph(boundaryClusters[c]) - - for edge in edges: - print(edge) - if edges[edge] == "LR": - graph.edge_attr.update(dir='forward') - graph.edge(edge[0],edge[1]) - elif edges[edge] == "BOTH": - graph.edge_attr.update(dir='both') - graph.edge(edge[0], edge[1]) - - return graph - -def dfd(scenes: dict, title: str, dfdLabels=True, render=False): +def dfd(scenes: dict, title: str, dfdLabels=True, render=False, simplified=False): graph = Digraph(title) graph.attr(rankdir="LR", color="blue") graph.attr("node", fontname="Arial", fontsize="14") @@ -671,15 +591,31 @@ def dfd(scenes: dict, title: str, dfdLabels=True, render=False): graph.subgraph(boundaryClusters[c]) # Add the edges - flowCounter = 1 - for flow in scenes[title]: - if dfdLabels is True: - graph.edge( - flow.pitcher.name, flow.catcher.name, f"({flowCounter}) {flow.name}" - ) - else: - graph.edge(flow.pitcher.name, flow.catcher.name, f"({flowCounter})") - flowCounter += 1 + + if simplified is True: + edges = {} # Map the edges and figure out if we need to be double or single ended + for flow in scenes[title]: + # This edge is flow.pitcher.name -> flow.catcher.name + # If we don't have this edge, first check to see if we have it the other way + if (flow.pitcher.name, flow.catcher.name) not in edges and (flow.catcher.name, flow.pitcher.name) not in edges: + edges[(flow.pitcher.name, flow.catcher.name)] = "forward" + elif (flow.pitcher.name, flow.catcher.name) not in edges and (flow.catcher.name, flow.pitcher.name) in edges: + edges[(flow.catcher.name, flow.pitcher.name)] = "both" + + for edge in edges: + print(edge) + graph.edge(edge[0], edge[1], dir=edges[edge]) + + else: #simplified is False + flowCounter = 1 + for flow in scenes[title]: + if dfdLabels is True: + graph.edge( + flow.pitcher.name, flow.catcher.name, f"({flowCounter}) {flow.name}" + ) + else: + graph.edge(flow.pitcher.name, flow.catcher.name, f"({flowCounter})") + flowCounter += 1 return graph @@ -727,18 +663,29 @@ def report(scenes: dict, outputDir: str, select=None, dfdLabels=True): "dfdImage": renderDfd(graph, key, outputDir=outputDir), "dataFlowTable": dataFlowTable(scenes, key), } - - agg = aggregatedDfd(scenes) + + compoundFlows = [] + for flow in scenes.values(): + compoundFlows = compoundFlows + flow + + agg = dfd({'all':compoundFlows}, 'all', simplified=True) aggDfd = { "graph": agg, "dfdImage": renderDfd(agg, "AggregatedDfd", outputDir=outputDir), } + templateLoader = FileSystemLoader(searchpath="./") templateEnv = Environment(loader=templateLoader) template = templateEnv.get_template("reportTemplate.html") with open(f"{outputDir}/ThreatModel.html", "w") as f: f.write( - template.render({"title": "Threat Models", "sceneReports": sceneReports, "aggregatedDfd":aggDfd}) + template.render( + { + "title": "Threat Models", + "sceneReports": sceneReports, + "aggregatedDfd": aggDfd, + } + ) ) diff --git a/requirements.txt b/requirements.txt index 63b5d50..d10eb08 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ graphviz==0.16 Jinja2==3.0.1 +black==21.7b0 \ No newline at end of file From 6586f06e7c38b9fbda09c69af57cc5c8e4a4a032 Mon Sep 17 00:00:00 2001 From: Rob C Date: Mon, 19 Jul 2021 11:22:53 -0700 Subject: [PATCH 2/5] Adding nest example --- example_nest.py | 23 ++++++ examples/nest/AggregatedDfd-dfd | 30 ++++++++ examples/nest/AggregatedDfd-dfd.png | Bin 0 -> 20349 bytes examples/nest/ThreatModel.html | 106 ++++++++++++++++++++++++++++ examples/nest/Towers-dfd | 31 ++++++++ examples/nest/Towers-dfd.png | Bin 0 -> 26544 bytes 6 files changed, 190 insertions(+) create mode 100644 example_nest.py create mode 100644 examples/nest/AggregatedDfd-dfd create mode 100644 examples/nest/AggregatedDfd-dfd.png create mode 100644 examples/nest/ThreatModel.html create mode 100644 examples/nest/Towers-dfd create mode 100644 examples/nest/Towers-dfd.png diff --git a/example_nest.py b/example_nest.py new file mode 100644 index 0000000..6fdaac3 --- /dev/null +++ b/example_nest.py @@ -0,0 +1,23 @@ +from fluentm import Actor, Boundary, Process, Data, DataFlow, HTTP, TLS, SQL +from fluentm import report + + +scenes = { + # Example using variables, which is fine for small things but gets hard with longer flows + "Towers":[ + DataFlow( + Process("Alice").inBoundary(Boundary("A Inner").inBoundary(Boundary("A Mid").inBoundary(Boundary("A Outer")))), + Process("Bob").inBoundary(Boundary("B Inner").inBoundary(Boundary("B Mid").inBoundary(Boundary("B Outer")))), + TLS("Helo"), + response=TLS("Hai") + ), + DataFlow( + Process("Charlie").inBoundary(Boundary("B Outer")), + Process("Alice"), + TLS("Yo") + ) + ] +} + +if __name__ == "__main__": + report(scenes, outputDir="examples/nest") diff --git a/examples/nest/AggregatedDfd-dfd b/examples/nest/AggregatedDfd-dfd new file mode 100644 index 0000000..8a77f12 --- /dev/null +++ b/examples/nest/AggregatedDfd-dfd @@ -0,0 +1,30 @@ +digraph all { + color=blue rankdir=LR + node [fontname=Arial fontsize=14] + subgraph "cluster_A Outer" { + graph [color=red fontname=Arial fontsize=12 label="A Outer" line=dotted] + subgraph "cluster_A Mid" { + graph [color=red fontname=Arial fontsize=12 label="A Mid" line=dotted] + subgraph "cluster_A Inner" { + graph [color=red fontname=Arial fontsize=12 label="A Inner" line=dotted] + Alice + } + } + } + subgraph "cluster_B Outer" { + graph [color=red fontname=Arial fontsize=12 label="B Outer" line=dotted] + subgraph "cluster_B Mid" { + graph [color=red fontname=Arial fontsize=12 label="B Mid" line=dotted] + subgraph "cluster_B Inner" { + graph [color=red fontname=Arial fontsize=12 label="B Inner" line=dotted] + Bob + } + } + } + subgraph "cluster_B Outer" { + graph [color=red fontname=Arial fontsize=12 label="B Outer" line=dotted] + Charlie + } + Alice -> Bob [dir=both] + Charlie -> Alice [dir=forward] +} diff --git a/examples/nest/AggregatedDfd-dfd.png b/examples/nest/AggregatedDfd-dfd.png new file mode 100644 index 0000000000000000000000000000000000000000..87d16a80d450f4e90788408bddbfad9e098a116d GIT binary patch literal 20349 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
P-F>@AO_yc@p$q@hORTGM;`#=k7tPZWJy46UsL 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 + + + Threat Models + + + + +

Aggregated Model

+

This high level diagram gathers all flows in this model to show how components interact at a high level.

+ +
+ +

Towers

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Flow IDPitcherCatcherData Flow
1AliceBobTLS( Helo )
2BobAliceTLS( Hai )
3CharlieAliceTLS( Yo )
+ + +
+ + + \ No newline at end of file diff --git a/examples/nest/Towers-dfd b/examples/nest/Towers-dfd new file mode 100644 index 0000000..027044f --- /dev/null +++ b/examples/nest/Towers-dfd @@ -0,0 +1,31 @@ +digraph Towers { + color=blue rankdir=LR + node [fontname=Arial fontsize=14] + subgraph "cluster_A Outer" { + graph [color=red fontname=Arial fontsize=12 label="A Outer" line=dotted] + subgraph "cluster_A Mid" { + graph [color=red fontname=Arial fontsize=12 label="A Mid" line=dotted] + subgraph "cluster_A Inner" { + graph [color=red fontname=Arial fontsize=12 label="A Inner" line=dotted] + Alice + } + } + } + subgraph "cluster_B Outer" { + graph [color=red fontname=Arial fontsize=12 label="B Outer" line=dotted] + subgraph "cluster_B Mid" { + graph [color=red fontname=Arial fontsize=12 label="B Mid" line=dotted] + subgraph "cluster_B Inner" { + graph [color=red fontname=Arial fontsize=12 label="B Inner" line=dotted] + Bob + } + } + } + subgraph "cluster_B Outer" { + graph [color=red fontname=Arial fontsize=12 label="B Outer" line=dotted] + Charlie + } + Alice -> Bob [label="(1) Helo"] + Bob -> Alice [label="(2) Hai"] + Charlie -> Alice [label="(3) Yo"] +} diff --git a/examples/nest/Towers-dfd.png b/examples/nest/Towers-dfd.png new file mode 100644 index 0000000000000000000000000000000000000000..427c51e3b744a0d6150b308b63b93cca35146ad5 GIT binary patch literal 26544 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 E15!7XUH||9 literal 0 HcmV?d00001 From ce3aa16c3b0da4176d77eb3da19889caaec86b19 Mon Sep 17 00:00:00 2001 From: Rob C Date: Mon, 19 Jul 2021 11:25:53 -0700 Subject: [PATCH 3/5] Added separate scene for Charlie --- example_nest.py | 4 +++- examples/nest/Enter Charlie-dfd | 19 +++++++++++++++++++ examples/nest/Enter Charlie-dfd.png | Bin 0 -> 13870 bytes examples/nest/ThreatModel.html | 22 +++++++++++++++++++++- examples/nest/Towers-dfd | 5 ----- examples/nest/Towers-dfd.png | Bin 26544 -> 16104 bytes 6 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 examples/nest/Enter Charlie-dfd create mode 100644 examples/nest/Enter Charlie-dfd.png diff --git a/example_nest.py b/example_nest.py index 6fdaac3..22c029f 100644 --- a/example_nest.py +++ b/example_nest.py @@ -10,7 +10,9 @@ Process("Bob").inBoundary(Boundary("B Inner").inBoundary(Boundary("B Mid").inBoundary(Boundary("B Outer")))), TLS("Helo"), response=TLS("Hai") - ), + ) + ], + "Enter Charlie":[ DataFlow( Process("Charlie").inBoundary(Boundary("B Outer")), Process("Alice"), diff --git a/examples/nest/Enter Charlie-dfd b/examples/nest/Enter Charlie-dfd new file mode 100644 index 0000000..c54b12b --- /dev/null +++ b/examples/nest/Enter Charlie-dfd @@ -0,0 +1,19 @@ +digraph "Enter Charlie" { + color=blue rankdir=LR + node [fontname=Arial fontsize=14] + subgraph "cluster_B Outer" { + graph [color=red fontname=Arial fontsize=12 label="B Outer" line=dotted] + Charlie + } + subgraph "cluster_A Outer" { + graph [color=red fontname=Arial fontsize=12 label="A Outer" line=dotted] + subgraph "cluster_A Mid" { + graph [color=red fontname=Arial fontsize=12 label="A Mid" line=dotted] + subgraph "cluster_A Inner" { + graph [color=red fontname=Arial fontsize=12 label="A Inner" line=dotted] + Alice + } + } + } + Charlie -> Alice [label="(1) Yo"] +} diff --git a/examples/nest/Enter Charlie-dfd.png b/examples/nest/Enter Charlie-dfd.png new file mode 100644 index 0000000000000000000000000000000000000000..f956256c50c4d79751948d2e513269d0a9835f80 GIT binary patch literal 13870 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 Q03)3`aaK7?(e(De0U1k5MgRZ+ literal 0 HcmV?d00001 diff --git a/examples/nest/ThreatModel.html b/examples/nest/ThreatModel.html index d620e70..89a0e93 100644 --- a/examples/nest/ThreatModel.html +++ b/examples/nest/ThreatModel.html @@ -84,9 +84,29 @@

Towers

+ + + +
+ +

Enter Charlie

+ + + + + + + + + + + + + + - + diff --git a/examples/nest/Towers-dfd b/examples/nest/Towers-dfd index 027044f..591e180 100644 --- a/examples/nest/Towers-dfd +++ b/examples/nest/Towers-dfd @@ -21,11 +21,6 @@ digraph Towers { } } } - subgraph "cluster_B Outer" { - graph [color=red fontname=Arial fontsize=12 label="B Outer" line=dotted] - Charlie - } Alice -> Bob [label="(1) Helo"] Bob -> Alice [label="(2) Hai"] - Charlie -> Alice [label="(3) Yo"] } diff --git a/examples/nest/Towers-dfd.png b/examples/nest/Towers-dfd.png index 427c51e3b744a0d6150b308b63b93cca35146ad5..5e05c97555c68402fd32d2ad670945ba9627e428 100644 GIT binary patch literal 16104 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 E15!7XUH||9 From 9a2ef2b52d58c72648fee127de57855250c9c735 Mon Sep 17 00:00:00 2001 From: Rob C Date: Mon, 19 Jul 2021 11:28:47 -0700 Subject: [PATCH 4/5] Updated with black formatting --- fluentm.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/fluentm.py b/fluentm.py index 4a3b860..0c0c321 100644 --- a/fluentm.py +++ b/fluentm.py @@ -540,6 +540,7 @@ def renderDfd(graph: Digraph, title: str, outputDir: str): print(graph) return f"{title}-dfd.png" + def dfd(scenes: dict, title: str, dfdLabels=True, render=False, simplified=False): graph = Digraph(title) graph.attr(rankdir="LR", color="blue") @@ -593,20 +594,28 @@ def dfd(scenes: dict, title: str, dfdLabels=True, render=False, simplified=False # Add the edges if simplified is True: - edges = {} # Map the edges and figure out if we need to be double or single ended + edges = ( + {} + ) # Map the edges and figure out if we need to be double or single ended for flow in scenes[title]: # This edge is flow.pitcher.name -> flow.catcher.name # If we don't have this edge, first check to see if we have it the other way - if (flow.pitcher.name, flow.catcher.name) not in edges and (flow.catcher.name, flow.pitcher.name) not in edges: + if (flow.pitcher.name, flow.catcher.name) not in edges and ( + flow.catcher.name, + flow.pitcher.name, + ) not in edges: edges[(flow.pitcher.name, flow.catcher.name)] = "forward" - elif (flow.pitcher.name, flow.catcher.name) not in edges and (flow.catcher.name, flow.pitcher.name) in edges: + elif (flow.pitcher.name, flow.catcher.name) not in edges and ( + flow.catcher.name, + flow.pitcher.name, + ) in edges: edges[(flow.catcher.name, flow.pitcher.name)] = "both" for edge in edges: print(edge) graph.edge(edge[0], edge[1], dir=edges[edge]) - else: #simplified is False + else: # simplified is False flowCounter = 1 for flow in scenes[title]: if dfdLabels is True: @@ -668,13 +677,12 @@ def report(scenes: dict, outputDir: str, select=None, dfdLabels=True): for flow in scenes.values(): compoundFlows = compoundFlows + flow - agg = dfd({'all':compoundFlows}, 'all', simplified=True) + agg = dfd({"all": compoundFlows}, "all", simplified=True) aggDfd = { "graph": agg, "dfdImage": renderDfd(agg, "AggregatedDfd", outputDir=outputDir), } - templateLoader = FileSystemLoader(searchpath="./") templateEnv = Environment(loader=templateLoader) template = templateEnv.get_template("reportTemplate.html") From 6ebeed2fd5a4c59b9166430b35e3c812d8331b51 Mon Sep 17 00:00:00 2001 From: Rob C Date: Mon, 19 Jul 2021 11:43:13 -0700 Subject: [PATCH 5/5] Black formatting post merge --- fluentm.py | 1 + 1 file changed, 1 insertion(+) diff --git a/fluentm.py b/fluentm.py index fd4c3e8..cdd1b63 100644 --- a/fluentm.py +++ b/fluentm.py @@ -558,6 +558,7 @@ def renderDfd(graph: Digraph, title: str, outputDir: str): print(graph) return f"{title}-dfd.png" + def dfd(scenes: dict, title: str, dfdLabels=True, render=False, simplified=False): graph = Digraph(title) graph.attr(rankdir="LR", color="blue")

Flow IDPitcherCatcherData Flow
31 Charlie