From f8c08c0c881d31aa7e1fdfb876196cb4d75fa065 Mon Sep 17 00:00:00 2001 From: "Mark E. Haase" Date: Wed, 13 Mar 2024 11:51:17 -0400 Subject: [PATCH 1/2] Remove unused sankey diagram files --- docs/_static/html/datasources-1.html | 14 ---- docs/_static/html/mitigations-1.html | 14 ---- docs/scripts/sankey_func.py | 112 --------------------------- 3 files changed, 140 deletions(-) delete mode 100644 docs/_static/html/datasources-1.html delete mode 100644 docs/_static/html/mitigations-1.html delete mode 100644 docs/scripts/sankey_func.py diff --git a/docs/_static/html/datasources-1.html b/docs/_static/html/datasources-1.html deleted file mode 100644 index 681b636..0000000 --- a/docs/_static/html/datasources-1.html +++ /dev/null @@ -1,14 +0,0 @@ - - - -
-
- - \ No newline at end of file diff --git a/docs/_static/html/mitigations-1.html b/docs/_static/html/mitigations-1.html deleted file mode 100644 index 37c7e9e..0000000 --- a/docs/_static/html/mitigations-1.html +++ /dev/null @@ -1,14 +0,0 @@ - - - -
-
- - \ No newline at end of file diff --git a/docs/scripts/sankey_func.py b/docs/scripts/sankey_func.py deleted file mode 100644 index 4fcd747..0000000 --- a/docs/scripts/sankey_func.py +++ /dev/null @@ -1,112 +0,0 @@ -import plotly.graph_objects as go -from mitreattack.stix20 import MitreAttackData -import pandas as pd -from textwrap import wrap - -def construct_dataframes(df, mitre_attack_data, insider_threat_ttps): - - #Given a list of InT Techniques: - #Get their associated tactics, mitigations, and data sources - tactics = [tactic for tactic in mitre_attack_data.get_tactics(remove_revoked_deprecated=True) - if mitre_attack_data.get_attack_id(tactic.id) - in insider_threat_ttps['Tactic ID'].values] - - for tactic in tactics: - tactic_shortname = tactic.x_mitre_shortname - - techniques_by_tactic = [technique for technique in mitre_attack_data.get_techniques_by_tactic(tactic_shortname, domain='enterprise-attack') - if mitre_attack_data.get_attack_id(technique.id) - in insider_threat_ttps['Technique ID'].values] - - for technique_obj in techniques_by_tactic: - - #Mitigations - if 'Mitigation' in df.columns: - mitigations_mitigating_technique = mitre_attack_data.get_mitigations_mitigating_technique(technique_obj.id) - - for mitigation in mitigations_mitigating_technique: - obj_to_add = [#tactic.name, mitre_attack_data.get_attack_id(tactic.id), - technique_obj.name, mitre_attack_data.get_attack_id(technique_obj.id), - mitigation["object"].name, mitre_attack_data.get_attack_id(mitigation["object"].id), - ] - df.loc[len(df)] = obj_to_add - - #Datasources - else: - datacomponents_detecting_technique = mitre_attack_data.get_datacomponents_detecting_technique(technique_obj.id) - datasources_detecting_technique = [] - for datacomponent in datacomponents_detecting_technique: - if mitre_attack_data.get_object_by_stix_id(datacomponent["object"].x_mitre_data_source_ref) not in datasources_detecting_technique: - datasources_detecting_technique.append(mitre_attack_data.get_object_by_stix_id(datacomponent["object"].x_mitre_data_source_ref)) - - for datasource in datasources_detecting_technique: - obj_to_add = [#tactic.name, mitre_attack_data.get_attack_id(tactic.id), - technique_obj.name, mitre_attack_data.get_attack_id(technique_obj.id), - mitre_attack_data.get_attack_id(datasource.id), datasource.name - ] - df.loc[len(df)] = obj_to_add - return df - -#Orders the techniques by number of linked mitigations or datasources, most to least -def order_graph_by_frequency(df): - column_name = df.columns[2] - df['count'] = df.groupby(column_name)[column_name].transform('count') - df = df.sort_values('count', ascending=False) - return df.drop('count', axis=1) - -# Wraps labels at width limit -def wrap_labels(labels): - wrapped_labels = [] - for label in labels: - wrapped_label = "
".join(wrap(label, width=50)) - wrapped_labels.append(wrapped_label) - return wrapped_labels - -def parallel_categories(df, filepath): - #Get only techniques + mitigations, or techniques + datasources - df = order_graph_by_frequency(df[['Technique', 'Technique ID', df.columns[2], df.columns[3]]].drop_duplicates()) - dimensions=[ - # {'label':'Tactics','values':[f'{a} {b}' for a, b in zip(df['Tactic'], df['Tactic ID'])]}, - {'label':'Techniques','values':wrap_labels([f'{a} {b}' for a, b in zip(df['Technique'], df['Technique ID'])])}, - {'label': df.columns[2] + 's','values':wrap_labels([f'{a} {b}' for a, b in zip(df.iloc[:, 2], df.iloc[:, 3])])} - ] - #indexes were 4, 4, 5 - fig = go.Figure(data = go.Parcats(dimensions=dimensions)) - fig.update_layout( - hovermode="closest", - showlegend=False, - xaxis={'automargin': True}, - yaxis={'automargin': True}, - margin=dict(l=215, r=200, b=20, t=20, pad=None), - ) - if df.columns[2] == 'Datasource': - fig.update_layout( - margin=dict(l=215, r=100, b=20, t=20, pad=None), - ) - config = {'displayModeBar': True} - # fig.show() - fig.write_html(filepath, config=config) - #just generate the div and then use the cdn link as a script tag in mds.rst - #don't generate the html at all??? Just what I need for the graph and them style *-1.html myself? - -def main(): - mitre_attack_data = MitreAttackData("enterprise-attack-14.1.json") - insider_threat_ttps = pd.read_csv('insider-threat-ttp-kb.csv') - mitigations_filepath = 'docs/_static/html/mitigations-1.html' - datasources_filepath = 'docs/_static/html/datasources-1.html' - - mitigation_columns = [#'Tactic', 'Tactic ID', - 'Technique', 'Technique ID', - 'Mitigation', 'Mitigation ID'] - datasource_columns = [#'Tactic', 'Tactic ID', - 'Technique', 'Technique ID', - 'Datasource', 'Datasource ID'] - - tactics_techniques_mitigations_df = construct_dataframes(pd.DataFrame(columns= mitigation_columns), mitre_attack_data, insider_threat_ttps) - parallel_categories(tactics_techniques_mitigations_df, mitigations_filepath) - - tactics_techniques_datasources_df = construct_dataframes(pd.DataFrame(columns= datasource_columns), mitre_attack_data, insider_threat_ttps) - parallel_categories(tactics_techniques_datasources_df, datasources_filepath) - -if __name__ == "__main__": - main() \ No newline at end of file From b141be797f5700dcb9f13433e6e509eeda246c04 Mon Sep 17 00:00:00 2001 From: "Mark E. Haase" Date: Wed, 13 Mar 2024 12:23:05 -0400 Subject: [PATCH 2/2] Fix navigator layers that have minValue==maxValue (fixes #4) As noted by @IanDavila, this violates the navigator layer specification. We have several layers where min==1 and max==1. I updated all of those to have min==0 and max==1. --- docs/extra/extradocs/insider-threat-ttp.json | 4 ++-- docs/extra/green_seen_v1_v2.json | 4 ++-- docs/extra/insider_threat_matrix_combined.json | 4 ++-- docs/extra/insider_threat_matrix_v1.json | 4 ++-- docs/extra/navigatorlayers/insider-threat-ttp.json | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/extra/extradocs/insider-threat-ttp.json b/docs/extra/extradocs/insider-threat-ttp.json index 0f89a91..f82f610 100644 --- a/docs/extra/extradocs/insider-threat-ttp.json +++ b/docs/extra/extradocs/insider-threat-ttp.json @@ -3342,7 +3342,7 @@ "#31a354ff", "#31a354ff" ], - "minValue": 1, + "minValue": 0, "maxValue": 1 }, "legendItems": [ @@ -3358,4 +3358,4 @@ "selectTechniquesAcrossTactics": false, "selectSubtechniquesWithParent": false, "selectVisibleTechniques": false -} \ No newline at end of file +} diff --git a/docs/extra/green_seen_v1_v2.json b/docs/extra/green_seen_v1_v2.json index 69c54f8..7592c90 100644 --- a/docs/extra/green_seen_v1_v2.json +++ b/docs/extra/green_seen_v1_v2.json @@ -8172,7 +8172,7 @@ "#31a354ff", "#31a354ff" ], - "minValue": 1, + "minValue": 0, "maxValue": 1 }, "legendItems": [ @@ -8188,4 +8188,4 @@ "selectTechniquesAcrossTactics": false, "selectSubtechniquesWithParent": false, "selectVisibleTechniques": false -} \ No newline at end of file +} diff --git a/docs/extra/insider_threat_matrix_combined.json b/docs/extra/insider_threat_matrix_combined.json index 9ee0a3f..6280064 100644 --- a/docs/extra/insider_threat_matrix_combined.json +++ b/docs/extra/insider_threat_matrix_combined.json @@ -7405,7 +7405,7 @@ "#31a354ff", "#31a354ff" ], - "minValue": 1, + "minValue": 0, "maxValue": 1 }, "legendItems": [ @@ -7420,4 +7420,4 @@ "tacticRowBackground": "#dddddd", "selectTechniquesAcrossTactics": false, "selectSubtechniquesWithParent": false -} \ No newline at end of file +} diff --git a/docs/extra/insider_threat_matrix_v1.json b/docs/extra/insider_threat_matrix_v1.json index ed1f694..9f71515 100644 --- a/docs/extra/insider_threat_matrix_v1.json +++ b/docs/extra/insider_threat_matrix_v1.json @@ -3082,7 +3082,7 @@ "#31a354ff", "#31a354ff" ], - "minValue": 1, + "minValue": 0, "maxValue": 1 }, "legendItems": [ @@ -3098,4 +3098,4 @@ "selectTechniquesAcrossTactics": false, "selectSubtechniquesWithParent": false, "selectVisibleTechniques": false -} \ No newline at end of file +} diff --git a/docs/extra/navigatorlayers/insider-threat-ttp.json b/docs/extra/navigatorlayers/insider-threat-ttp.json index 0f89a91..f82f610 100644 --- a/docs/extra/navigatorlayers/insider-threat-ttp.json +++ b/docs/extra/navigatorlayers/insider-threat-ttp.json @@ -3342,7 +3342,7 @@ "#31a354ff", "#31a354ff" ], - "minValue": 1, + "minValue": 0, "maxValue": 1 }, "legendItems": [ @@ -3358,4 +3358,4 @@ "selectTechniquesAcrossTactics": false, "selectSubtechniquesWithParent": false, "selectVisibleTechniques": false -} \ No newline at end of file +}