diff --git a/components.py b/components.py index c79011f5856c62b5efd5a4dde11717f249807729..c0bdb82686b10365573ce7cf25a9552717849bcf 100644 --- a/components.py +++ b/components.py @@ -244,4 +244,5 @@ class Diagram(): self.consequences = {} self.attacks = {} self.dynamics = {} - self.indicators = {} \ No newline at end of file + self.indicators = {} + self.erComponents = {} \ No newline at end of file diff --git a/dashBoard.py b/dashBoard.py index 41e3dabc2ed55f8253a60390e7ed926166e81ab4..866792e09e583811101bac159bd66454eb2ad50e 100644 --- a/dashBoard.py +++ b/dashBoard.py @@ -10,80 +10,101 @@ from components import Diagram import diagramParser as parse import dashboardUtils as utils + def openFile(): - fileName = filedialog.askopenfilename(initialdir= "/", - title= "Select lucidchart diagram file", - filetypes=(("CSV Diagram file", "*.csv"),) - ) - diagram = parse.parseDiagramFile(fileName) + """ + Function allows the user to select a diagram, and opens the scorecard resulting window + From here, the user can see the threats in the diagram and the associated indicators and architecture components + The user can also choose to sort by indicators + """ + #fileName = filedialog.askopenfilename(initialdir= "/",title= "Select lucidchart diagram file",filetypes=(("CSV Diagram file", "*.csv"),)) + #diagram = parse.parseDiagramFile(fileName) # Parse the diagram + s = ttk.Style() + s.theme_use('classic') + s.configure('Green.TFrame', background='Green',foreground="#1A323B", relief='raised') + s.configure('Red.TFrame', background='Red',foreground="#1A323B", relief='raised') + + + diagram = parse.parseDiagramFile("diagrams/TestIter2.csv") - top = Toplevel(guiRoot) - top.title("Result Window") - top.geometry("1600x900") - topFrame = Frame(top) - topFrame.grid() + # Defines the window for the scorecard + scorecardWindow = Toplevel(guiRoot) + scorecardWindow.title("Scorecard") + scorecardWindow.attributes("-fullscreen", True) - canvas = Canvas(topFrame, width=1450, height= 900) # Create Canvas to be able to scroll - canvas.grid() + windowHeigh = scorecardWindow.winfo_height() + windowWidth = scorecardWindow.winfo_width() - # Define scrollbar - scrollbar = Scrollbar(topFrame, orient="vertical", command=canvas.yview) - scrollbar.grid(row=0, column=1, sticky="ns") + mainFrame = ttk.Frame(scorecardWindow, height=windowHeigh, width=windowWidth) # * Defines the main frame of the window, should contain a socrecard in the top and a list of threats in the bottom + mainFrame.grid(row=0, column=0, sticky='nsew') # * Grid should sort the scorecard and the list of threats - canvas.configure(yscrollcommand=scrollbar.set) - canvas.bind( - '<Configure>', lambda e: canvas.configure(scrollregion=canvas.bbox("all")) - ) + # Inside the scorecardFrame there should be text labels with header, and three different labels with values with information + # Additionally there should be two buttons, one for threat sorting and one for indicator sorting + headerLabel = Label(mainFrame, text="Scorecard", font=("Arial", 20)) - canvasFrame = createMetrics(diagram, canvas) - canvasFrame.grid_columnconfigure(0, weight=1) + relationshipNumber = len(diagram.threats)+len(diagram.consequences)+len(diagram.erComponents) + threatNumber = len(diagram.threats) + consequenceNumber = len(diagram.consequences) + architectureNumber = len(diagram.erComponents) - canvas.create_window((0,0), window=canvasFrame, anchor="nw") + descriptionString = "The diagrams have been successfully parsed! Below is the list of found threats, and their associated architecture components. These components are linked through the security indicators found between the threats and architecture components" + descriptionString2 = "Press the sort by indicators to swap to the indicator sorted veiw. This helps identify which metrics are important and which components they relate to." + descriptionLabel = ttk.Label(mainFrame, text=descriptionString, wraplength=0.4*windowWidth, font=("Arial", 15)) + description2Label = ttk.Label(mainFrame, text=descriptionString2, wraplength=0.4*windowWidth, font=("Arial", 15)) - rowIndex = 0 + sortThreatButton = Button(mainFrame, text="Sort by threats", command=lambda: createThreatView(diagram, mainFrame), width=2, height=3) + sortIndicatorButton = Button(mainFrame, text="Sort by indicators", command=lambda: createIndicatorView(diagram, mainFrame), width=2, height=3) - for threat in diagram.threats.values(): - - metrics, components = findMetrics(diagram, threat.componentID, "bowtie") - - threatFrame = Frame(top) - threatFrame.grid(row=rowIndex) - rowIndex +=1 - - l1 = Label(threatFrame, text= f"Threat ID: {threat.id} \n Threat description: {threat.threatSource}") - l2 = Label(threatFrame, text= f"Associated vulnerability: {threat.vulnerability}") - - listofIndicators = Listbox(threatFrame, font="Helvetica") - index = 1 - for metric in metrics: - listofIndicators.insert(index,metric) - index +=1 - - linkedComponents = Listbox(threatFrame, font="Helvetica") - index = 1 - for component in components: - linkedComponents.insert(index, component) - index +=1 - - l3 = Label(threatFrame, text= f"Observable indicators: {metrics}") + analyticsLabel = Label(mainFrame, text="Features", font=("Arial", 20, "bold")) + analyticsRow3 = Label(mainFrame, text=f"Number of indicators: {len(diagram.indicators)}", font=("Arial", 15)) + analyticsrow4 = Label(mainFrame, text=f"Number of relationships: {relationshipNumber}", font=("Arial", 15)) + analyticsRow5 = Label(mainFrame, text=f"Number of threats: {threatNumber}", font=("Arial", 15)) + analyticsRow6 = Label(mainFrame, text=f"Number of consequences: {consequenceNumber}", font=("Arial", 15)) + analyticsRow7 = Label(mainFrame, text=f"Number of architecture components: {architectureNumber}", font=("Arial", 15)) + + # Create the reult text + + paddingScorecardInfo = 18 + headerLabel.grid(row=0, column=0, sticky="nw", pady=paddingScorecardInfo, padx=paddingScorecardInfo) + descriptionLabel.grid(row=1, column=0, sticky="nw", pady=paddingScorecardInfo, padx=paddingScorecardInfo, rowspan=4, columnspan=2) + description2Label.grid(row=2, column=0, sticky="nw", pady=paddingScorecardInfo, padx=paddingScorecardInfo, rowspan=4, columnspan=2) + + #* Buttons + sortIndicatorButton.grid(row=7, column=0, sticky="nsew") + sortThreatButton.grid(row=7, column=1, sticky="nsew") + - l4 = Label(threatFrame, text = f"Linked Components: {components}") - - l1.config(font=("Helvetica", 20, "bold")) - l2.config(font=("Helvetica", 15)) - l3.config(font=("Helvetica", 15)) - l4.config(font=("Helvetica", 15)) - - l1.grid(row = 4, column = 0) - l2.grid(row=6, column = 0) - listofIndicators.grid(row=4, column=10) - linkedComponents.grid(row = 4, column = 15) - -def tempTestFunction(): + # * From this point to row 6 is the analytics matrix, padding is reduced to 10 + analyticsLabel.grid(row=0, column=1, sticky="nw", pady=paddingScorecardInfo, padx=paddingScorecardInfo) + + paddingScorecardInfo= 5 + + analyticsRow3.grid(row=2, column=1, sticky="nw", pady=paddingScorecardInfo, padx=paddingScorecardInfo) + analyticsrow4.grid(row=3, column=1, sticky="nw", pady=paddingScorecardInfo, padx=paddingScorecardInfo) + analyticsRow5.grid(row=4, column=1, sticky="nw", pady=paddingScorecardInfo, padx=paddingScorecardInfo) + analyticsRow6.grid(row=5, column=1, sticky="nw", pady=paddingScorecardInfo, padx=paddingScorecardInfo) + analyticsRow7.grid(row=6, column=1, sticky="nw", pady=paddingScorecardInfo, padx=paddingScorecardInfo) + + # Create frame for the list of either threat or indicator, Framelocation mainFrame row 2 + listFrame = customtkinter.CTkScrollableFrame(mainFrame, width= 0.9*windowWidth, height=0.5*windowHeigh, bg_color="#155E53") + listFrame.grid(row=8, column=0, columnspan=2 ,sticky="nsew") + + # Create the list of threats + createThreatView(diagram, mainFrame, 0.9*windowWidth) + + + +def createThreatView(diagram: Diagram, frame, canvasWidth): + pass + + + + +def createIndicatorView(): windowWidth = 1250 windowHeight = 1200 @@ -99,7 +120,7 @@ def tempTestFunction(): mainFrame.grid_rowconfigure(0, weight=1) canvasFrame = createMetrics(diagram, mainFrame, 1550) - + def createMetrics(diagram: Diagram, frame, canvasWidth): s = ttk.Style() @@ -115,7 +136,6 @@ def createMetrics(diagram: Diagram, frame, canvasWidth): scoreFrame = ttk.Frame(frame, height=100, width=canvasWidth, padding=10, style='Test.TFrame') scoreFrame.grid(padx=10, pady=25, sticky="nsew") - scoreFrame.grid_columnconfigure(0, weight=1) headerLabel = ttk.Label(scoreFrame, text="Diagram scorecard", font=("Helvetica", 25, "bold"), style="Head.TLabel") label1 = ttk.Label(scoreFrame, text=f"Diagrams parsed! Below is the list of found metrics along with the amount of relationships. Further down you will find the list of metrics with usage and associated components", wraplength=0.5*canvasWidth ,font=("Helvetica", 20), style="Test.TLabel") @@ -194,11 +214,12 @@ label3 = ttk.Label(guiRoot, text="BowTie risk diagram, Software supply chain arc label2.grid(column=1, row=4) label3.grid(column=1, row=5) -#labelWindow = Label(guiRoot, text="Please select CSV export file containing ER diagram, BowTie diagram and dynamics matrix", font=("Arial", 20)) -#buttonGetFile = Button(guiRoot, text="Select file", command=openFile, width=20, height=2) -#labelWindow.grid(column = 1, row = 1) -#buttonGetFile.grid(column = 1, row = 1) +labelWindow = Label(guiRoot, text="Please select CSV export file containing ER diagram, BowTie diagram and dynamics matrix", font=("Arial", 20)) +buttonGetFile = Button(guiRoot, text="Select file", command=openFile, width=20, height=2) +labelWindow.grid(column = 1, row = 1) +buttonGetFile.grid(column = 1, row = 1) + +openFile() -tempTestFunction() guiRoot.mainloop() diff --git a/dashboardUtils.py b/dashboardUtils.py index 8ade295cfa3cca0f938fbb01cd756dc49ee06480..9288102012df60036ee62a5db863d1592bc6a978 100644 --- a/dashboardUtils.py +++ b/dashboardUtils.py @@ -8,13 +8,13 @@ from components import * import diagramParser as parse -def createERLabel(top, metric: Metric, diagram: Diagram): +def createERLabel(top, indicator : Indicator, diagram: Diagram): s = ttk.Style() s.configure('ListFrame.TLabel', background='white', foreground="#1A323B", font=('Helvetica', 15, 'bold')) nameList = [] labelList = [] - for i in metric.erID: + for i in indicator.erID: for j in diagram.dynamics.values(): if j.type == "ER": if i in j.associatedERComponents.keys(): @@ -29,7 +29,7 @@ def createERLabel(top, metric: Metric, diagram: Diagram): labelList.append(label) return labelList -def createBowtieLabel(top, metric: Metric, diagram: Diagram): +def createBowtieLabel(top, indicator: Indicator, diagram: Diagram): s = ttk.Style() s.configure('ListFrame.TLabel', background='white', foreground="#1A323B", font=('Helvetica', 15, 'bold')) diff --git a/diagramParser.py b/diagramParser.py index 6dc19bd863deed45cbc511166cb90c67f2d36546..7b979c9730afffd17c5ef51ec6a5b439e5fe2d8d 100644 --- a/diagramParser.py +++ b/diagramParser.py @@ -127,6 +127,7 @@ def parseRelationshipComponentER(df: pd.DataFrame, diagram: component.Diagram, r # Add indicators to the ER component erComponent.linkedIndicators.update(indicatorList) erComponents[erComponent.id]= erComponent + diagram.erComponents[erComponent.id] = erComponent for i in indicatorList.keys(): # We need to update the indicators with the ER components and the reasoning for the indicator annotation diff --git a/main.py b/main.py index bce6a625da6666f7d26044ed28f6b97838ebce45..37349861a2fa8b5cdd29c488d23fa7a7f9482c2f 100644 --- a/main.py +++ b/main.py @@ -1,11 +1,12 @@ import diagramParser as parse +import components as component -def main(): +def main(): + diagram:component.Diagram = parse.parseDiagramFile('diagrams/TestIter2.csv') # Parse the diagram + + + - dynamicMetricsBowtie = [] # List of metrics for the bowtie model - dynamicMetricsArchitecture = [] # List of metrics for the architecture - #parse.parseDiagramFile('diagrams/Thesis Bow-Tie and architecture - Meta model-2.csv') # Parse the diagram - diagram = parse.parseDiagramFile('diagrams/TestIter2.csv') # Parse the diagram if __name__=="__main__":