class ScenarioManager(): def __init__(self, db_manager=DatabaseManager()): self.file_manager = FileManager() self.db_manager = db_manager self.scenarios_dict = self._initializeFromDatabase() def _initializeFromDirectory(self): """ Initializes the scenario's runtime objects using data from the host folders. :return: Dictionary containing scenario's data """ # Variables scenarios_dict = dict() scenarios = os.listdir(self.file_manager.getScenariosPath()) for scenario_name in scenarios: json_name = ''.join([scenario_name, ".json"]) with open( self.file_manager.getScenarioJSONPath(scenario_name) / json_name) as outfile: scenario_dict = json.load(outfile) scenario = Scenario(scenario_name).objectFromDictionary( scenario_dict) scenarios_dict[scenario_name] = scenario return scenarios_dict def _initializeFromDatabase(self): """ Pre-populates the database with scenarios. :return: Dictionary containing scenario's data """ # Variables scenarios_dict = dict() scenarios = self.db_manager.getScenarios() for raw_scenario in scenarios: del raw_scenario["_id"] scenario_name = raw_scenario["scenario_name"] scenario = Scenario(scenario_name).objectFromDictionary( raw_scenario) scenarios_dict[scenario_name] = scenario return scenarios_dict def newEmpty(self, scenario_name): """ Creates a new scenario which includes the folders and the scenario JSON file :param scenario_name: String with the scenario name :return: Response object containing the status of the request """ #Folder creation moved to FileManager response = Response() if scenario_name not in self.scenarios_dict: #self.file_manager.createScenarioFolders(scenario_name) scenario = Scenario(scenario_name) self.scenarios_dict[scenario_name] = scenario #self._saveScenarioAsJSON(scenario) self.db_manager.insertScenario(scenario.dictionary().copy()) response.setResponse(True) response.setBody(scenario.dictionary()) else: response.setResponse(False) response.setReason('Scenario already exist') response.setBody(dict()) return response.dictionary() def getAll(self): """ Gets the available scenarios :return: Response object containing the status of the request """ # Variables scenarios_dict = { "scenarios": [ self.scenarios_dict[s].scenario_name for s in self.scenarios_dict ] } response = Response() response.setResponse(True) response.setBody(scenarios_dict) return response.dictionary() def getOne(self, scenario_name): """ Gets the scenario as a JSON file :param scenario_name: String with the scenario name :return: Response object containing the status of the request """ response = Response() if scenario_name in self.scenarios_dict: response.setResponse(True) response.setBody(self.scenarios_dict[scenario_name].dictionary()) else: response.setResponse(False) response.setReason('Scenario doesn\'t exist') response.setBody(dict()) return response.dictionary() def editOne(self, scenario_json): """ Edits a current scenario with a JSON file :param scenario_json: JSON file with the new scenario :return: Response object containing the status of the request """ response = Response() print(scenario_json) scenario_name = scenario_json["scenario_name"] if scenario_name in self.scenarios_dict: if "machines" in scenario_json: for machine in scenario_json["machines"]: if scenario_json["machines"][machine]["uuid"] == "": new_uuid = uuid.uuid4() new_uuid = str(new_uuid).replace('-', '') print("Unique id: ", new_uuid) scenario_json['machines'][machine]['uuid'] = new_uuid scenario_json = Scenario(scenario_name).objectFromDictionary( scenario_json) self.scenarios_dict[scenario_name] = scenario_json #self._saveScenarioAsJSON(new_scenario) self.db_manager.editScenario(scenario_json.dictionary().copy()) response.setResponse(True) response.setBody(self.scenarios_dict[scenario_name].dictionary()) else: response.setReason('Scenario doesn\'t exist') response.setResponse(False) response.setBody(dict()) return response.dictionary() def deleteOne(self, scenario_name): """ Deletes one scenario from the database. :param scenario_name: Scenario's name string :return: Response object containing the status of the request """ response = Response() if scenario_name in self.scenarios_dict: deleted_scenario = self.scenarios_dict.pop(scenario_name) #self.file_manager.deleteScenariosFolder(scenario_name) self.db_manager.deleteScenario(scenario_name) response.setResponse(True) response.setBody(deleted_scenario.dictionary()) else: response.setResponse(False) response.setReason('Scenario doesn\'t exist') response.setBody(dict()) return response.dictionary() def scenarioExists(self, scenario_name): """ Check if a scenario exists. :param scenario_name: String with the scenario name :return: False if the scenario JSON file does not exist and the path to the JSON file if it exist """ scenario_dir_path = self.file_manager.getScenariosPath( ) / scenario_name / "JSON" if not os.path.isdir(scenario_dir_path): print("Scenario %s directory not found" % scenario_name) return False else: scenario_json_path = scenario_dir_path / ''.join( [scenario_name, ".json"]) if not os.path.exists(scenario_json_path): print("Scenario %s json not found" % scenario_name) return None else: return scenario_json_path def _saveScenarioAsJSON(self, scenario): """ Saves a scenario as a JSON file :param scenario: Scenario's name string :return: None """ scenario_json_path = self.file_manager.getScenarioJSONPath( scenario.scenario_name) / ''.join( [scenario.scenario_name, ".json"]) if scenario_json_path: with open(scenario_json_path, 'w+') as outfile: outfile.write(json.dumps(scenario.dictionary(), indent=2)) outfile.close() return
class DatabaseManager(): def __init__(self): self.file_manager = FileManager() self.url = ConfigManager().mongoURL() self.db_name = "soft_prac" self.scenarios_col_name = 'scenarios' self.exploits_col_name = 'exploits' self.vulnerabilities_col_name = 'vulnerabilities' self.client = pymongo.MongoClient(self.url) self.db = self.client[self.db_name] self.scenarios_col = self.db[self.scenarios_col_name] self.exploits_col = self.db[self.exploits_col_name] self.vulnerabilities_col = self.db[self.vulnerabilities_col_name] self.addScenariosToDB() self.addExploitsToDB() self.addVulnerabilitiesToDB() def _initializeScenariosFromDirectory(self): """ Initializes the scenario's runtime objects using data from the host folders. :return: Dictionary containing scenario's data """ # Variables scenarios_dict = dict() scenarios = os.listdir(self.file_manager.getScenariosPath()) for scenario_name in scenarios: json_name = ''.join([scenario_name, ".json"]) with open( self.file_manager.getScenarioJSONPath(scenario_name) / json_name) as outfile: scenario_dict = json.load(outfile) scenario = Scenario(scenario_name).objectFromDictionary( scenario_dict) scenarios_dict[scenario_name] = scenario return scenarios_dict def addScenariosToDB(self): """ Pre-populates the database with scenarios. :return: None """ scenarios_to_add = ['Scenario_1', 'Scenario_3'] currentScenarios = self.getScenarios() scenarios_list = [ scenario['scenario_name'] for scenario in currentScenarios ] scenarios_set = set(scenarios_list) for scenario_name in scenarios_to_add: if scenario_name not in scenarios_set: json_name = ''.join([scenario_name, ".json"]) with open( self.file_manager.getScenarioJSONPath(scenario_name) / json_name) as outfile: scenario_dict = json.load(outfile) scenario = Scenario(scenario_name).objectFromDictionary( scenario_dict) self.insertScenario(scenario.dictionary().copy()) return def addExploitsToDB(self): """ Pre-populates the database with exploits. :return: None """ exploits_to_add = [ 'Django_3_0_Cross-Site_Request_Forgery_Token_Bypass' ] currentExploits = self.getExploits() exploits_list = [exploit['name'] for exploit in currentExploits] exploits_set = set(exploits_list) for exploit_name in exploits_to_add: if exploit_name not in exploits_set: json_name = ''.join([exploit_name, ".json"]) with open( self.file_manager.getExploitJSONPath(exploit_name) / json_name) as outfile: exploit_dict = json.load(outfile) exploit = Exploit().objectFromDictionary(exploit_dict) self.insertExploit(exploit.dictionary().copy()) return def addVulnerabilitiesToDB(self): """ Pre-populates the database with vulnerabilities. :return: None """ vulnerabilities_to_add = ['rConfig_3_9_searchColumn_SQL_Injection'] currentVulnerabilities = self.getVulnerabilities() vulnerabilities_list = [ vulnerability['name'] for vulnerability in currentVulnerabilities ] vulnerabilities_set = set(vulnerabilities_list) for vulnerability_name in vulnerabilities_to_add: if vulnerability_name not in vulnerabilities_set: json_name = ''.join([vulnerability_name, ".json"]) with open( self.file_manager.getVulnerabilityJSONPath( vulnerability_name) / json_name) as outfile: vulnerability_dict = json.load(outfile) vulnerability = Vulnerability().objectFromDictionary( vulnerability_dict) self.insertVulnerability(vulnerability.dictionary().copy()) return #CRUD: CREATE, READ, UPDATE and DELETE #Scenarios def insertScenario(self, scenario_json): """ Inserts a scenario into the database. :param scenario_json: Scenario's JSON file to be inserted :return: Inserted document's id """ doc = self.scenarios_col.insert_one(scenario_json) return doc.inserted_id def getScenarioNames(self): """ Gets the scenario's names. :return: A list containing the scenarios names """ return [doc['scenario_name'] for doc in self.scenarios_col.find()] def getScenarios(self): """ Gets the scenarios from the databases. :return: A list containing scenarios in the database """ return [doc for doc in self.scenarios_col.find()] def getScenario(self, scenario_name): """ Gets a specific scenario from the database. :param scenario_name: Scenario's name string :return: A list containing the scenario retrieved from the database """ query = {'scenario_name': scenario_name} return [doc for doc in self.scenarios_col.find(query)] def editScenario(self, scenario_json): """ Edits a scenario in the database. :param scenario_json: JSON file containing scenario's data :return: Modified document's id """ query = {'scenario_name': scenario_json['scenario_name']} new_doc = {"$set": scenario_json} doc = self.scenarios_col.update_one(query, new_doc) return doc.modified_count def deleteScenario(self, scenario_name): """ Deletes a scenario from the database. :param scenario_name: Scenario's name string :return: Deleted document's id """ query = {'scenario_name': scenario_name} doc = self.scenarios_col.delete_one(query) return doc.deleted_count #Exploits def insertExploit(self, exploit_json): """ Inserts a scenario in the database. :param exploit_json: JSON file containing the exploit's data :return: Inserted document's id """ doc = self.exploits_col.insert_one(exploit_json) return doc.inserted_id def getExploitNames(self): """ Gets the exploits names from the database. :return: A list containing the exploits' names """ return [doc['name'] for doc in self.exploits_col.find()] def getExploits(self): """ Gets the exploits stored in the database. :return: A list containing the stored exploits' data """ return [doc for doc in self.exploits_col.find()] def getExploit(self, exploit_name): """ Gets an exploit from the database. :param exploit_name: Exploit's name string :return: A list containing the exploit data """ query = {'name': exploit_name} return [doc for doc in self.exploits_col.find(query)] def editExploit(self, exploit_json): """ Edits an exploit in the database. :param exploit_json: JSON file containing the exploit's data :return: Modified document's id """ query = {'name': exploit_json['name']} new_doc = {"$set": exploit_json} doc = self.exploits_col.update_one(query, new_doc) return doc.modified_count def deleteExploit(self, exploit_name): """ Deletes a exploit from the database. :param exploit_name: Exploit's name string :return: Deleted document's id """ query = {'name': exploit_name} doc = self.exploits_col.delete_one(query) return doc.deleted_count #Vulnerabilities def insertVulnerability(self, vulnerability_json): """ Inserts a vulnerability in the database. :param vulnerability_json: JSON file containing the vulnerability's data :return: Inserted document's id """ doc = self.vulnerabilities_col.insert_one(vulnerability_json) return doc.inserted_id def getVulnerabilityNames(self): """ Gets the vulnerabilities names from the database. :return: A list containing the vulnerability's names """ return [doc['name'] for doc in self.vulnerabilities_col.find()] def getVulnerabilities(self): """ Gets the vulnerabilities stored in the database. :return: A list containing the stored vulnerabilities' data """ return [doc for doc in self.vulnerabilities_col.find()] def getVulnerability(self, vulnerability_name): """ Gets a vulnerability from the database. :param vulnerability_name: Vulnerability's name string :return: A list containing the vulnerability's data """ query = {'name': vulnerability_name} return [doc for doc in self.vulnerabilities_col.find(query)] def editVulnerability(self, vulnerability_json): """ Edits a vulnerability in the database. :param vulnerability_json: JSON file containing the vulnerability's data :return: Modified document's id """ query = {'name': vulnerability_json['name']} new_doc = {"$set": vulnerability_json} doc = self.vulnerabilities_col.update_one(query, new_doc) return doc.modified_count def deleteVulnerability(self, vulnerability_name): """ Deletes a vulnerability from the database. :param vulnerability_name: Vulnerability's name string :return: Deleted document's id """ query = {'name': vulnerability_name} doc = self.vulnerabilities_col.delete_one(query) return doc.deleted_count