def create_folder(example_folder_path): """Creates folder for storing the intermediate results of the examples.""" config = reader.read_config_file() directory_path = os.path.join(config["examples-results-path"], example_folder_path) if not os.path.exists(directory_path): os.makedirs(directory_path, mode=0o777)
def write_attack_graph(example_folder_path, graph): """Writes the attack graph onto a dot file.""" config = reader.read_config_file() folder_name = os.path.basename(example_folder_path) attack_graph_path = os.path.join(config["examples-results-path"], folder_name, "attack_graph.dot") graph.render(attack_graph_path)
def write_topology_graph(graph, example_folder_path, example_result_path=""): """Writes the topology graph onto a dot file.""" folder_name = os.path.basename(example_folder_path) if example_result_path == "": config = reader.read_config_file() example_result_path = config["examples-results-path"] topology_graph_path = os.path.join(example_result_path, folder_name, "topology_graph.dot") graph.render(topology_graph_path)
def copy_vulnerability_file(clairctl_home, image_name, old_root_path, parent_folder): """Copies the vulnerability file from clairctl to the local location.""" config = reader.read_config_file(old_root_path) parent_folder = os.path.basename(parent_folder) os.rename( os.path.join(clairctl_home, "docker-compose-data", "clairctl-reports", "json", "analysis-" + image_name + "-latest.json"), os.path.join(old_root_path, config["examples-results-path"], parent_folder, image_name + "-vulnerabilities.json"))
def write_topology_file(list_services, example_folder_path="", example_result_path=""): """Writes list of services into a file.""" folder_name = os.path.basename(example_folder_path) if example_result_path == "": config = reader.read_config_file() example_result_path = config["examples-results-path"] topology_writing_path = os.path.join(example_result_path, folder_name, "topology.json") with open(topology_writing_path, "w") as topology: json.dump(list_services, topology)
def test_big_real_example(self): """Testing the example from atsea shop app. It has 4 containers in total. However only two of them have vulnerabilities.""" print("Test: Testing a real example...") # Preparing the data for testing example_folder = os.path.join(os.getcwd(), "atsea") parent_path = os.path.dirname(os.getcwd()) # Opening the configuration file. config = reader.read_config_file(old_root_path=parent_path) topology_path = os.path.join(os.getcwd(), "atsea", "topology.json") with open(topology_path) as topology_file: topology = json.load(topology_file) vulnerabilities = reader.read_vulnerabilities(example_folder, topology.keys()) # Running the attack graph generator att_vec_path = os.path.join(parent_path, config["attack-vector-folder-path"]) nodes, edges, _, _ = generate_attack_graph(att_vec_path, config["preconditions-rules"], config["postconditions-rules"], topology, vulnerabilities, example_folder) # Checking the nodes self.assertEqual(len(nodes), 5) self.assertTrue('outside(ADMIN)' in nodes) self.assertTrue('atsea_app(ADMIN)' in nodes) self.assertTrue('atsea_app(USER)' in nodes) self.assertTrue('atsea_db(ADMIN)' in nodes) self.assertTrue('atsea_db(USER)' in nodes) # Checking the edges self.assertEqual(len(edges), 4) self.assertTrue('outside(ADMIN)|atsea_app(ADMIN)' in edges) self.assertTrue('outside(ADMIN)|atsea_app(USER)' in edges) self.assertTrue('outside(ADMIN)|atsea_db(ADMIN)' in edges) self.assertTrue('outside(ADMIN)|atsea_db(USER)' in edges)
def scalability_test_helper(example_folder): """Main function that tests the scalability for different examples.""" number_runs_per_test = 5 duration_topology = 0 duration_bdf = 0 duration_vuls_preprocessing = 0 duration_total_time = 0 for i in range(1, number_runs_per_test+1): print("\n\nIteration: "+str(i)) total_time_start = time.time() # Preparing the data for testing parent_path = os.path.dirname(os.getcwd()) # Opening the configuration file. config = reader.read_config_file(old_root_path=parent_path) topology, duration_topology_new = top_par.parse_topology(example_folder, os.getcwd()) duration_topology += duration_topology_new vuls_orig = reader.read_vulnerabilities(example_folder, ["example_samba", "example_phpmailer"]) vulnerabilities = {} for container_orig in vuls_orig.keys(): for container_topology in topology.keys(): if container_orig in container_topology: vulnerabilities[container_topology] = vuls_orig[container_orig] att_vec_path = os.path.join(parent_path, config["attack-vector-folder-path"]) # Returns a tuple of the form: # (attack_graph_nodes, attack_graph_edges, duration_bdf, duration_vul_preprocessing) attack_graph_tuple = generate_attack_graph(att_vec_path, config["preconditions-rules"], config["postconditions-rules"], topology, vulnerabilities, example_folder) # Unpacking the variables duration_bdf += attack_graph_tuple[2] duration_vuls_preprocessing += attack_graph_tuple[3] no_topology_nodes = len(topology.keys()) no_topology_edges = 0 for container in topology.keys(): no_topology_edges += len(topology[container]) # We divide them by two because each edge is counted twice. no_topology_edges = int(no_topology_edges / 2) no_attack_graph_nodes = len(attack_graph_tuple[0]) no_attack_graph_edges = len(attack_graph_tuple[1]) duration_total_time += (time.time() - total_time_start) # Calculate the averages of the times duration_topology = duration_topology/5 duration_vuls_preprocessing = duration_vuls_preprocessing/5 duration_bdf = duration_bdf/5 duration_total_time = duration_topology + duration_vuls_preprocessing + duration_bdf # Printing time summary of the attack graph generation. writer.print_summary(config["mode"], config["generate_graphs"], no_topology_nodes=no_topology_nodes, no_topology_edges=no_topology_edges, no_attack_graph_nodes=no_attack_graph_nodes, no_attack_graph_edges=no_attack_graph_edges, duration_topology=duration_topology, duration_vuls_preprocessing=duration_vuls_preprocessing, duration_bdf=duration_bdf, duration_total_time=duration_total_time) print("Total time elapsed: "+str(duration_total_time)+"\n\n\n")
def main(example_folder): """Main function responsible for running the attack graph generation pipeline.""" # Opening the configuration file. config = reader.read_config_file() # Create folder where the result files will be stored. writer.create_folder(os.path.basename(example_folder)) # Parsing the topology of the docker containers. time_start = time.time() topology, duration_topology = top_par.parse_topology(example_folder) duration_topology = time.time() - time_start print("Time elapsed: "+str(duration_topology)+" seconds.\n") # Visualizing the topology graph. duration_visualization = 0 if config['generate_graphs']: time_start = time.time() top_par.create_topology_graph(topology, example_folder) duration_visualization = time.time() - time_start print("Time elapsed: "+str(duration_visualization)+" seconds.\n") # Parsing the vulnerabilities for each docker container. vulnerabilities = {} duration_vulnerabilities = 0 if config["mode"] == "online": time_start = time.time() vul_par.parse_vulnerabilities(example_folder) duration_vulnerabilities = time.time() - time_start print("Time elapsed: "+str(duration_vulnerabilities)+" seconds.\n") vulnerabilities_folder_path = os.path.join(config['examples-results-path'], os.path.basename(example_folder)) vulnerabilities = reader.read_vulnerabilities(vulnerabilities_folder_path, topology.keys()) if not vulnerabilities.keys(): print("There is a mistake with the vulnerabilities. Terminating the function...") return # Getting the attack graph nodes and edges from the attack paths. # Returns a tuple of the form: # (attack_graph_nodes, attack_graph_edges, duration_bdf, duration_vul_preprocessing) att_graph_tuple = att_gr_par.generate_attack_graph(config["attack-vector-folder-path"], config["preconditions-rules"], config["postconditions-rules"], topology, vulnerabilities, example_folder) print("Time elapsed: "+str(att_graph_tuple[2]+att_graph_tuple[3])+" seconds.\n") # Printing the graph properties. duration_graph_properties = att_gr_par.print_graph_properties(config["labels_edges"], nodes=att_graph_tuple[0], edges=att_graph_tuple[1]) #print(att_graph_tuple[0]) #print(len(att_graph_tuple[1].keys())) if config["show_one_vul_per_edge"]: for element in att_graph_tuple[1].keys(): att_graph_tuple[1][element] = [att_graph_tuple[1][element][0]] # Visualizing the attack graph. if config['generate_graphs']: time_start = time.time() visualize_attack_graph(config["labels_edges"], example_folder, nodes=att_graph_tuple[0], edges=att_graph_tuple[1]) duration_visualization = time.time() - time_start print("Time elapsed: "+str(duration_visualization)+" seconds.\n") # Printing time summary of the attack graph generation. writer.print_summary(config["mode"], config['generate_graphs'], duration_topology=duration_topology, duration_vulnerabilities=duration_vulnerabilities, duration_bdf=att_graph_tuple[2], duration_vuls_preprocessing=att_graph_tuple[3], duration_graph_properties=duration_graph_properties, duration_visualization=duration_visualization)