def remove(self, _key): """Remove an API. Parameters ---------- obj : dict The API to be removed. """ try: self.logger.debug("bin.db: Removing API.") if not _key: raise Exception('Missing ID in remove DB module') kvstoreUri = self.kvstoreUri + '/' + str( _key) + '?output_mode=json' result = self.session.delete(kvstoreUri, headers={ "Authorization": "Splunk %s" % splunk.getSessionKey(), "Content-Type": "application/json" }, verify=False) if result.status_code == 200: parsed_result = jsonbak.dumps({'data': 'API removed.'}) else: msg = jsonbak.loads(result.text) text = msg['messages'][0]['text'] raise Exception(text) return parsed_result except Exception as e: self.logger.error("Error removing an API in DB module: %s" % (e)) raise e
def remove_job(self, _key, session_key=False): """Remove an API. Parameters ---------- obj : dict The API to be removed. """ try: self.logger.debug("bin.jobs_queue: Removing job.") if not _key: raise Exception('Missing ID in remove JobQueue module') kvstoreUri = self.kvstoreUri+'/'+str(_key)+'?output_mode=json' auth_key = session_key if session_key else splunk.getSessionKey() result = self.session.delete(kvstoreUri, headers={ "Authorization": "Splunk %s" % auth_key, "Content-Type": "application/json"}, verify=False) if result.status_code == 200: return 'Job removed.' else: msg = jsonbak.loads(result.text) text = msg['messages'][0]['text'] raise Exception(text) except Exception as e: self.logger.error("bin.jobs_queu: Error removing a Job in JobsQueue module: %s" % (e)) raise e
def update_api(self, **kwargs): """Update Wazuh API. Parameters ---------- kwargs : dict The request's parameters """ try: self.logger.debug("manager: Updating API information.") entry = kwargs if '_user' in kwargs: del kwargs['_user'] if not "passapi" in entry: opt_id = entry["_key"] data_temp = self.db.get(opt_id) current_api = jsonbak.loads(data_temp) current_api = current_api["data"] entry["passapi"] = current_api["passapi"] keys_list = ['_key', 'url', 'portapi', 'userapi', 'passapi', 'filterName', 'filterType', 'managerName'] if set(entry.keys()) == set(keys_list): self.db.update(entry) parsed_data = jsonbak.dumps({'data': 'success'}) else: missing_params = diff_keys_dic_update_api(entry) raise Exception( "Invalid arguments, missing params : %s" % str(missing_params)) except Exception as e: self.logger.error("manager: Error in update_api endpoint: %s" % (e)) return jsonbak.dumps({"error": str(e)}) return parsed_data
def get_api_credentials(self, api_id): """Get API credentials. Parameters ---------- str: api_id The API id """ try: self.logger.debug("bin.check_queue: Getting API credentials.") api = self.db.get(api_id, self.auth_key) api = jsonbak.loads(api) if "data" in api and "messages" in api["data"] and api["data"][ "messages"][0] and "type" in api["data"]["messages"][ 0] and api["data"]["messages"][0]["type"] == "ERROR": raise Exception('API does not exist') elif api: opt_username = api['data']["userapi"] opt_password = api['data']["passapi"] opt_base_url = api['data']["url"] opt_base_port = api['data']["portapi"] url = str(opt_base_url) + ":" + str(opt_base_port) auth = requestsbak.auth.HTTPBasicAuth(opt_username, opt_password) verify = False return url, auth, verify else: raise Exception('API not found') except Exception as e: raise e
def check_connection_by_id(self, **kwargs): """Given an API id we check the connection. Parameters ---------- kwargs : dict The request's parameters """ try: self.logger.debug("manager: Checking API connection by id.") opt_id = kwargs["apiId"] current_api = self.get_api(apiId=opt_id) current_api_json = jsonbak.loads(jsonbak.loads(current_api)) if not "data" in current_api_json: return jsonbak.dumps({"status": "400", "error": "Error when checking API connection."}) opt_username = str(current_api_json["data"]["userapi"]) opt_password = str(current_api_json["data"]["passapi"]) opt_base_url = str(current_api_json["data"]["url"]) opt_base_port = str(current_api_json["data"]["portapi"]) opt_cluster = False if "cluster" in current_api_json["data"]: opt_cluster = current_api_json["data"]["cluster"] == "true" url = opt_base_url + ":" + opt_base_port auth = requestsbak.auth.HTTPBasicAuth(opt_username, opt_password) verify = False try: manager_info = self.session.get( url + '/manager/info', auth=auth, timeout=20, verify=verify) manager_info = manager_info.json() except ConnectionError as e: self.logger.error("manager: Cannot connect to API : %s" % (e)) return jsonbak.dumps({"status": "400", "error": "Unreachable API, please check the URL and port."}) output = {} if "error" in manager_info and manager_info["error"] != 0: #Checks if daemons are up and running return jsonbak.dumps({"status": "400", "error": manager_info["message"]}) output['managerName'] = { 'name' : manager_info['data']['name'] } output['clusterMode'] = { "enabled" : manager_info['data']['cluster']['enabled'], "running" : manager_info['data']['cluster']['running'] } output['clusterName'] = { "type" : manager_info['data']['cluster']['node_type'], "cluster" : manager_info['data']['cluster']['name'], "node" : manager_info['data']['cluster']['node_name'] } del current_api_json["data"]["passapi"] output['api'] = current_api_json result = jsonbak.dumps(output) except Exception as e: self.logger.error("Error when checking API connection: %s" % (e)) raise e return result
def get_config_on_memory(self): try: self.logger.debug("manager: Getting configuration on memory.") config_str = getSelfConfStanza("config", "configuration") config = jsonbak.loads(config_str) return config except Exception as e: self.logger.error("manager: Error getting the configuration on memory: %s" % (e)) raise e
def check_connection_by_id(self, **kwargs): """Given an API id we check the connection. Parameters ---------- kwargs : dict The request's parameters """ try: self.logger.debug("manager: Checking API connection by id.") opt_id = kwargs["apiId"] current_api = self.get_api(apiId=opt_id) current_api_json = jsonbak.loads(jsonbak.loads(current_api)) if not "data" in current_api_json: return jsonbak.dumps({ "status": "400", "error": "Error when checking API connection." }) opt_username = str(current_api_json["data"]["userapi"]) opt_password = str(current_api_json["data"]["passapi"]) opt_base_url = str(current_api_json["data"]["url"]) opt_base_port = str(current_api_json["data"]["portapi"]) opt_cluster = False if "cluster" in current_api_json["data"]: opt_cluster = current_api_json["data"]["cluster"] == "true" output = self.get_cluster_info(opt_username, opt_password, opt_base_url, opt_base_port, opt_cluster) del current_api_json["data"]["passapi"] output['api'] = current_api_json result = jsonbak.dumps(output) except Exception as e: self.logger.error("Error when checking API connection: %s" % (e)) raise e return result
def init(self): """Inits the jobs """ try: self.logger.debug("bin.check_queue: Checking jobs queue.") jobs = self.q.get_jobs(self.auth_key) todo_jobs = self.get_todo_jobs(jobs) self.check_todo_jobs(todo_jobs) jobs = jsonbak.loads(jobs) self.check_todo_jobs(jobs) except Exception as e: self.logger.error( 'bin.check_queue: Error at init in the CheckQueue module: {}'. format(e))
def get_todo_jobs(self, jobs): """Gets the to do jobs Parameters ---------- str: jobs A dictionary in string format with the jobs """ try: self.logger.debug("bin.check_queue: Gettings todo jobs.") jobs = jsonbak.loads(jobs) todo_jobs = filter(lambda j: j['done'] == False, jobs) except TypeError as e: todo_jobs = [] self.logger.error( 'bin.check_queue: Error filtering the fields in the CheckQueue module: {}' .format(e)) return todo_jobs
def get_credentials(self, the_id): try: self.logger.debug("api: Getting API credentials.") api = self.db.get(the_id) api = jsonbak.loads(api) if api: opt_username = api['data']["userapi"] opt_password = api['data']["passapi"] opt_base_url = api['data']["url"] opt_base_port = api['data']["portapi"] url = str(opt_base_url) + ":" + str(opt_base_port) auth = requestsbak.auth.HTTPBasicAuth(opt_username, opt_password) verify = False cluster_enabled = True if api['data']['filterType'] == "cluster.name" else False return url, auth, verify, cluster_enabled else: raise Exception('API not found') except Exception as e: raise e
def get_apis(self, **kwargs): """Obtain all Wazuh APIs from DB. Parameters ---------- kwargs : dict The request's parameters """ try: self.logger.debug("manager: Getting API list.") apis = self.db.all() parsed_apis = jsonbak.loads(apis) # Remove the password from the list of apis for api in parsed_apis: if "passapi" in api: del api["passapi"] result = jsonbak.dumps(parsed_apis) except Exception as e: self.logger.error(jsonbak.dumps({"error": str(e)})) return jsonbak.dumps({"error": str(e)}) return result
def check_status(): """Check status of agents.""" try: logger.debug("bin.get_agents_status: Checking agents status.") apis = get_apis() apis = jsonbak.loads( apis ) #get_apis() returns a JSON string, it needs to be converted as a dictionary date = str(datetime.datetime.utcnow())[:-7] # obtains for api in apis: opt_password = api["passapi"] opt_username = api["userapi"] opt_base_url = api["url"] opt_base_port = api["portapi"] agent_list = {} url = str(opt_base_url) + ":" + str(opt_base_port) auth = requestsbak.auth.HTTPBasicAuth(opt_username, opt_password) verify = False agents_url_total_items = url + '/agents?limit=1&q=id!=000' try: request_agents = requestsbak.get(agents_url_total_items, auth=auth, timeout=1, verify=verify).json() total_items = request_agents["data"]["totalItems"] limit = 500 offset = 0 params = {} params['q'] = 'id!=000' while offset < total_items: agents_url = url + \ '/agents?select=id,ip,manager,status&offset='+str(offset)+'&limit='+str(limit) request_agents = requestsbak.get(agents_url, auth=auth, timeout=1, verify=verify).json() agent_list = request_agents["data"]["items"] final_url_cluster = url + '/cluster/status' request_cluster_status = requestsbak.get( final_url_cluster, auth=auth, timeout=1, verify=verify).json() cluster_status = request_cluster_status["data"]["enabled"] final_url_cluster_name = url + '/cluster/node' request_cluster_name = requestsbak.get( final_url_cluster_name, timeout=1, auth=auth, verify=verify).json() offset = offset + limit for item in agent_list: if cluster_status == "yes": item["cluster"] = {} item["cluster"]["name"] = request_cluster_name[ "data"]["cluster"] if 'manager' in item: manager_name = item["manager"] item["manager"] = {} item["manager"]["name"] = manager_name item["timestamp"] = date print(jsonbak.dumps(item)) except Exception as e: logger.error("Error requesting agents status: %s" % str(e)) pass except Exception as e: logger.error("Error requesting agents status: %s" % str(e)) pass
def csv(self, **kwargs): """Generate an exportable CSV from request data. Parameters ---------- kwargs : dict Request parameters """ try: self.logger.debug("api: Generating CSV file.") if 'id' not in kwargs or 'path' not in kwargs: raise Exception("Invalid arguments or missing params.") filters = {} filters['limit'] = 500 filters['offset'] = 0 if 'filters' in kwargs and kwargs['filters'] != '': parsed_filters = jsonbak.loads(kwargs['filters']) keys_to_delete = [] for key, value in parsed_filters.items(): if parsed_filters[key] == "": keys_to_delete.append(key) if len(keys_to_delete) > 0: for key in keys_to_delete: parsed_filters.pop(key, None) filters.update(parsed_filters) the_id = kwargs['id'] api = self.db.get(the_id) api = jsonbak.loads(api) opt_username = api["data"]["userapi"] opt_password = api["data"]["passapi"] opt_base_url = api["data"]["url"] opt_base_port = api["data"]["portapi"] opt_endpoint = kwargs['path'] url = str(opt_base_url) + ":" + str(opt_base_port) auth = requestsbak.auth.HTTPBasicAuth(opt_username, opt_password) verify = False wazuh_token = self.wztoken.get_auth_token(url, auth) is_list_export_keys_values = "lists/files" in opt_endpoint # init csv writer output_file = StringIO() # get total items and keys request = self.session.get( url + opt_endpoint, params=None if is_list_export_keys_values else filters, headers={ 'Authorization': f'Bearer {wazuh_token}' }, verify=verify).json() self.logger.debug("api: Data obtained for generate CSV file.") if ('affected_items' in request['data'] and len(request['data']['affected_items']) > 0): # Export CSV the CDB List keys and values if is_list_export_keys_values: items_list = [{ "Key": k, "Value": v } for k, v in request["data"]["affected_items"][0].items()] dict_writer = csv.DictWriter( output_file, delimiter=',', fieldnames=items_list[0].keys(), extrasaction='ignore', lineterminator='\n', quotechar='"') # write CSV header dict_writer.writeheader() dict_writer.writerows(items_list) csv_result = output_file.getvalue() output_file.close() self.logger.debug("api: CSV file generated.") return csv_result else: final_obj = request["data"]["affected_items"] if isinstance(final_obj, list): keys = final_obj[0].keys() self.format_output(keys) final_obj_dict = self.format_output(final_obj) total_items = request["data"]["total_affected_items"] # initializes CSV buffer if total_items > 0: dict_writer = csv.DictWriter(output_file, delimiter=',', fieldnames=keys, extrasaction='ignore', lineterminator='\n', quotechar='"') # write CSV header dict_writer.writeheader() dict_writer.writerows(final_obj_dict) offset = 0 # get the rest of results while offset <= total_items: offset += filters['limit'] filters['offset'] = offset req = self.session.get(url + opt_endpoint, params=filters, headers={ 'Authorization': f'Bearer {wazuh_token}' }, verify=verify).json() paginated_result = req['data']['affected_items'] format_paginated_results = self.format_output( paginated_result) dict_writer.writerows(format_paginated_results) csv_result = output_file.getvalue() self.logger.info("api: CSV generated successfully.") else: csv_result = '[]' else: csv_result = '[]' output_file.close() self.logger.debug("api: CSV file generated.") except Exception as e: self.logger.error("api: Error in CSV generation!: %s" % (str(e))) return jsonbak.dumps({"error": str(e)}) return csv_result
def upload_file(self, **kwargs): # Only rules files are uploaded currently self.logger.debug("manager: Uploading file(s)") try: # Get file name and file content split_file = str(kwargs["file"]).split('\', \'') file_name = split_file[1] file_content = split_file[2] file_content = file_content[:len(file_content) - 2] file_content2 = file_content # Get path dest_path = kwargs["path"] # Get current API data opt_id = kwargs["apiId"] current_api_json = self.db.get(opt_id) current_api_json = jsonbak.loads(current_api_json) opt_username = str(current_api_json["data"]["userapi"]) opt_password = str(current_api_json["data"]["passapi"]) opt_base_url = str(current_api_json["data"]["url"]) opt_base_port = str(current_api_json["data"]["portapi"]) opt_cluster = False if "filterType" in current_api_json["data"] and current_api_json[ "data"]["filterType"] == 'cluster.name': opt_cluster = True # API requests auth auth = requestsbak.auth.HTTPBasicAuth(opt_username, opt_password) verify = False url = opt_base_url + ":" + opt_base_port if dest_path and dest_path == 'etc/lists/': file_content = file_content.replace('\\n', "\n") result = self.session.post( url + '/manager/files?path=' + dest_path + file_name, data=file_content, headers={"Content-type": "application/octet-stream"}, auth=auth, timeout=20, verify=verify) else: file_content = file_content.replace('\\n', '') result = self.session.post( url + '/manager/files?path=' + dest_path + file_name, data=file_content, headers={"Content-type": "application/xml"}, auth=auth, timeout=20, verify=verify) result = jsonbak.loads(result.text) if 'error' in result and result['error'] != 0: return jsonbak.dumps({ "status": "400", "text": "Error adding file: %s. Cause: %s" % (file_name, result["message"]) }) return jsonbak.dumps({ "status": "200", "text": "File %s was updated successfully. " % file_name }) except Exception as e: self.logger.error("manager: Error trying to upload a file(s): %s" % (e))
def upload_file(self, **kwargs): # Only rules files are uploaded currently self.logger.debug("manager: Uploading file(s)") try: # Get file name and file content file_info = kwargs["file"].__dict__ file_name = file_info['filename'] file_content = kwargs['file'].file # Get path dest_resource = kwargs["resource"] # Get current API data opt_id = kwargs["apiId"] current_api_json = self.db.get(opt_id) current_api_json = jsonbak.loads(current_api_json) opt_username = str(current_api_json["data"]["userapi"]) opt_password = str(current_api_json["data"]["passapi"]) opt_base_url = str(current_api_json["data"]["url"]) opt_base_port = str(current_api_json["data"]["portapi"]) opt_cluster = False if "filterType" in current_api_json["data"] and current_api_json[ "data"]["filterType"] == 'cluster.name': opt_cluster = True # API requests auth auth = requestsbak.auth.HTTPBasicAuth(opt_username, opt_password) verify = False url = opt_base_url + ":" + opt_base_port wazuh_token = self.wztoken.get_auth_token(url, auth) response = self.session.put(url + '/' + dest_resource + '/files/' + file_name, data=file_content, headers={ "Content-type": "application/octet-stream", 'Authorization': f'Bearer {wazuh_token}' }, timeout=20, verify=verify) result = jsonbak.loads(response.text) if 'error' in result and result['error'] != 0: self.logger.error( "manager: Error trying to upload a file(s): %s" % (result)) return jsonbak.dumps({ "status": "400", "text": "Error adding file: %s. Cause: %s" % (file_name, result["detail"]) }) return jsonbak.dumps({ "status": "200", "text": "File %s was updated successfully. " % file_name }) except Exception as e: self.logger.error("manager: Error trying to upload a file(s): %s" % (e)) return jsonbak.dumps({ "status": "400", "text": "Error adding file: %s. Cause: %s" % (file_name, e) })