def save_current_status_message(component_id, component_type, message_code, data=""): """Saves or merges the status_message Args: component_id(uuid canonical string) message_code(uuid cannonical string):Message id data (str): Message data component_type(str): Component tyep """ result = True try: message = get_current_status_message(component_id, message_code) db.session.begin() if message is not None: message_data = message #message_data.creation_time = datetime.now() message_data.additional_info = data db.session.merge(message_data) else: message_data = Current_Status() message_data.id = uuid.uuid4().bytes message_data.component_id = get_bytes_from_uuid(component_id) message_data.component_type = component_type message_data.creation_time = datetime.utcnow() message_data.message_id = get_bytes_from_uuid(message_code) message_data.additional_info = data message_data.supressed = 0 message_data.viewed = 0 db.session.add(message_data) db.session.commit() except Exception as error: db.session.rollback() result = False return result
def update_asset_id(sensor_id, agent_id, asset_id): """ Update Asset ID related to agent Raises: APICannotResolveSensorID APIInvalidHIDSAgentID APICannotUpdateHIDSAgent APICannotResolveAssetID """ if sensor_id is None: api_log.error("[update_asset_id]: Sensor ID could not be empty") raise APICannotResolveSensorID(sensor_id) if agent_id is None: api_log.error("[update_asset_id]: Agent ID could not be empty") raise APIInvalidHIDSAgentID(agent_id) if asset_id is None: api_log.error("[update_asset_id]: Asset ID could not be empty") raise APICannotResolveAssetID(asset_id) try: sensor_id_bin = get_bytes_from_uuid(sensor_id) asset_id_bin = get_bytes_from_uuid(asset_id) db.session.query(Hids_Agents).filter( and_(Hids_Agents.agent_id == agent_id, Hids_Agents.sensor_id == sensor_id_bin)).update({"host_id": asset_id_bin}) except Exception as msg: api_log.error("[update_asset_id]: %s" % str(msg)) raise APICannotUpdateHIDSAgent(agent_id, sensor_id)
def given_create_or_update_current_status_entry(context, var_cid, var_mid, var_type, viewed): #Using merging http://docs.sqlalchemy.org/en/latest/orm/session.html#merging to create or update # Check if we must create or delete print (context.alienvault[var_cid]) print (context.alienvault[var_mid]) try: entry = db.session.query(Current_Status).filter(and_( Current_Status.component_id == get_bytes_from_uuid(context.alienvault[var_cid]), Current_Status.message_id == context.alienvault[var_mid])).one() entry.component_type = context.alienvault[var_type] entry.viewed = viewed except NoResultFound: # Create a new entry entry = Current_Status() entry.id = uuid.uuid4().bytes entry.message_id = get_bytes_from_uuid(context.alienvault[var_mid]) entry.component_id = get_bytes_from_uuid(context.alienvault[var_cid]) entry.component_type = context.alienvault[var_type] entry.viewed = viewed try: db.session.begin() new_obj = db.session.merge(entry) db.session.commit() except Exception,e: print ("Error: %s" %str(e)) db.session.rollback()
def get_current_status_message(component_id, message_id): """ Returns the message object from a message code and a component id Args: component_id(UUID canonical string) message id(UUID cannonical string) """ try: component_id_binary = get_bytes_from_uuid(component_id) message = ( db.session.query(Current_Status) .filter( and_( Current_Status.message_id == get_bytes_from_uuid(message_id), Current_Status.component_id == get_bytes_from_uuid(component_id), ) ) .one() ) except NoResultFound: message = None except MultipleResultsFound: message = message[0] except Exception as e: message = None return message
def get_base_path(sensor_id): """ Return the base PATH taking into account the ha configuration """ try: data = db.session.query(System).filter(or_(System.sensor_id == get_bytes_from_uuid(sensor_id), System.server_id == get_bytes_from_uuid(sensor_id))).order_by( asc(System.ha_name)).limit(1).one() result = True, os.path.join("/var/alienvault/", data.serialize['uuid']) except NoResultFound: db.session.rollback() result = False, "No sensor identified by " + sensor_id return result
def given_store_current_status_entry_id(context, comp_id_key, msg_id_key, type_key, stat_id_key): entry = None try: entry = db.session.query(Current_Status).filter( and_( Current_Status.component_id == get_bytes_from_uuid(context.alienvault[comp_id_key]), Current_Status.message_id == get_bytes_from_uuid(context.alienvault[msg_id_key]), Current_Status.component_type == context.alienvault[type_key] ) ).one() except NoResultFound: assert None, "Current_Status entry was not found" context.alienvault[stat_id_key] = entry.serialize['id'] if entry is not None else ""
def db_insert_current_status_message(message_id, component_id, component_type, additional_info, replace, created=None): """Inserts a new notification on the system. The related message id should exists. Args: message_id (str:uuid string): Message id related with the notification component_id(str:uuid string): Component id related with the notification (Could be none for external messages) component_type(str): Component type. Allowed values: ('net','host','user','sensor','server','system','external') additional_info (str:json): Additional information you want to store. Returns: success(bool): True if the operation went well, False otherwise msg(str): A message string that will contain some kind of information in case of error""" if created is None: created = datetime.utcnow() if component_type not in ['net', 'host', 'user', 'sensor', 'server', 'system', 'external']: return False, "Invalid component_type" if component_type != "external" and component_id is None: return False, "Component id cannot be none for the given component_type" msg_id_binary = get_bytes_from_uuid(message_id) success, status_message = get_status_message_from_id(message_id=msg_id_binary, is_admin=True, serialize=False) if not success: return False, "The given message_id doesn't exist" if status_message is None: return False, "The given message_id doesn't exist. Message is None" component_id_binary = get_bytes_from_uuid(component_id) if (component_id_binary is None or component_id_binary == "") and component_type != "external": return False, "Invalid component_id" if replace is True: success, msg = delete_current_status_messages([msg_id_binary]) if not success: return success, "Unable to remove previous messages for the given message ID." try: db.session.begin() current_status_message = Current_Status() current_status_message.id = uuid4().bytes current_status_message.component_type = component_type current_status_message.creation_time = created current_status_message.message_id = msg_id_binary current_status_message.additional_info = additional_info current_status_message.suppressed = 0 current_status_message.viewed = 0 current_status_message.component_id = component_id_binary db.session.add(current_status_message) db.session.commit() except Exception, e: db.session.rollback() return False, "%s" % str(e)
def update_host_plugins(data): """ Save data{device_id: [plugin_id, ...]} in alienvault.host_scan table """ result = True msg = '' try: if data: db.session.begin() for device_id, plugin_ids in data.iteritems(): host_id = get_bytes_from_uuid(device_id) db.session.query(Host_Scan).filter(Host_Scan.host_id == host_id).delete() if plugin_ids: for pid in plugin_ids: host_scan = Host_Scan(host_id=host_id, plugin_id=int(pid), plugin_sid=0) db.session.merge(host_scan) db.session.commit() except Exception as e: result = False db.session.rollback() msg = "Unable to save data into database {0}".format(str(e)) return result, msg
def get_sensor_ctx_by_sensor_id(sensor_id, output='str'): """ Returns a sensor CTX given a sensor ID """ sensor_ctx = None try: if sensor_id: sensor_id_bin = get_bytes_from_uuid(sensor_id) query = db.session.query(Acl_Sensors.entity_id).filter(Acl_Sensors.sensor_id == sensor_id_bin) sensor = query.join(Acl_Entities, Acl_Entities.id == Acl_Sensors.entity_id).filter( Acl_Entities.entity_type == 'context').one() sensor_ctx = sensor.entity_id else: return False, "Sensor ID could not be empty" except NoResultFound: return True, sensor_ctx except Exception as msg: msg = str(msg) api_log.error(msg) return False, msg if output == 'str': return True, get_uuid_string_from_bytes(sensor_ctx) else: return True, sensor_ctx
def get_control_node(self): server_id = self.__config_repository.get_config(CONFIG_SERVER_ID).value software_version = self.__config_repository.get_config(CONFIG_VERSION).value system = self.__system_repository.get_system() server = self.__server_repository.get_server(get_bytes_from_uuid(server_id)) contact_person = self.__contact_person_repository.get_contact_person() platform = self.__platform_repo.get_platform(system.admin_ip) # Public IP is configured on AMI systems only and should be used as a control node's IP for such systems. # For other systems, high availability configuration IP (if configured) has more priority than admin IP. control_node_ip = platform and platform.public_ip or system.ha_ip or system.admin_ip return self.__model_constructor( system.id, system.name, server.descr, platform and platform.name, platform and platform.appliance_type, software_version, platform and platform.threat_intelligence_version, contact_person and contact_person.email, contact_person and contact_person.name, control_node_ip, system.vpn_ip )
def given_get_system_ifaces (context,var_uuid,var_ifaces): uuid = get_bytes_from_uuid(context.alienvault[var_uuid]) tempdir= "" try: dbsensor = db.session.query(System).filter(System.id == uuid).one() ip_system = dbsensor.serialize.get("admin_ip") # Create a tempdir tempdir = tempfile.mkdtemp (suffix =".behave") # Get the private pass used in ssh to communicate with other sensors config = ConfigParser() assert config.read ("/etc/ansible/ansible.cfg")[0] == "/etc/ansible/ansible.cfg", "Can\'t load ansible.cfg file" sshkey = config.get("defaults","private_key_file") ssh = Popen( ["ssh", "-i", sshkey, "-l", "avapi", ip_system, "/sbin/ifconfig -s -a"], shell=False, stdout=PIPE, stderr=PIPE ) (stdoutdata, stderrdata) = ssh.communicate() lines = filter(None, stdoutdata.splitlines()) # The format is # Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg # eth0 1500 0 339579 0 0 0 47558 0 0 0 BMPRU # lo 16436 0 1336360692 0 0 0 1336360692 0 0 0 LRU context.alienvault[var_ifaces] = ",".join([ x.split()[0].strip() for x in lines[1:] if x.split()[0].strip() != 'lo']) except NoResultFound: assert False,"Can't find sensor with uuid %s in database " % context.alienvault[var_uuid] except MultipleResultsFound, msg: assert False,"Multiples result for query. Internal database error uuid => %s" % var_uuid
def get_sensor_properties(sensor_id): result = True try: properties = db.session.query(Sensor_Properties).filter( Sensor_Properties.sensor_id == get_bytes_from_uuid(sensor_id)).one() message = {'has_nagios': bool(properties.has_nagios), 'has_ntop': bool(properties.has_ntop), 'has_vuln_scanner': bool(properties.has_vuln_scanner), 'has_kismet': bool(properties.has_kismet), 'ids': bool(properties.ids), 'passive_inventory': bool(properties.passive_inventory), 'netflows': bool(properties.netflows)} except NoResultFound: db.session.rollback() result = False message = "No properties found for sensor %s" % str(sensor_id) except MultipleResultsFound: db.session.rollback() result = False message = "More than one set of properties found for sensor %s" % str(sensor_id) except Exception, msg: db.session.rollback() result = False message = "An error occurred while retrieving properties for sensor %s: %s" % (str(sensor_id), str(msg))
def db_get_hostname(system_id): try: system_id_bin = get_bytes_from_uuid(system_id) system = db.session.query(System).filter(System.id == system_id_bin).one() except Exception, msg: db.session.rollback() return False, "Error while querying for system with id '%s': %s" % (system_id, str(msg))
def given_gen_monitor_data(context,var_n,var_type): db.session.query(Monitor_Data).delete() # Delete all current_status entries ctypes = var_type.split(",") for x in range (0,int(var_n)): ctype = random.choice (ctypes) assert (ctype in ['net','host','user','sensor','server','system']) == True, "Unknown type '%s'" % ctype entry = Monitor_Data() # Select a entry try: c_id = { 'user': str(uuid.UUID(db.session.query(Users).order_by(func.rand()).limit(1).one().serialize['uuid'])), 'net' : str(uuid.UUID(db.session.query(Net).order_by(func.rand()).limit(1).one().serialize['id'])), 'host': str(uuid.UUID(db.session.query(Host).order_by(func.rand()).limit(1).one().serialize['id'])), 'sensor': str(uuid.UUID(db.session.query(Host).order_by(func.rand()).limit(1).one().serialize['id'])), 'system': str(uuid.UUID(db.session.query(System).order_by(func.rand()).limit(1).one().serialize['uuid'])), 'server': str(uuid.UUID(db.session.query(Server).order_by(func.rand()).limit(1).one().serialize['id'])), }.get(ctype) except NoResultFound: assert None,"Can't load a asset of type '%s'" % ctype # We have now the component_id # Select a msg_id entry.component_id = get_bytes_from_uuid (c_id) entry.monitor_id = 1 entry.component_type = "system" sleep(1) entry.data = "{\"msg\": \"Texto de prueba\"}" db.session.begin() db.session.merge(entry) db.session.commit()
def update_hids_agent_status(agent_id, sensor_id, agent_status): """ Update status of HIDS agent Raises: APICannotResolveSensorID APIInvalidHIDSAgentID APICannotUpdateHIDSAgent """ if sensor_id is None: api_log.error("[update_hids_agent_status]: Sensor ID could not be empty") raise APICannotResolveSensorID(sensor_id) if agent_id is None: api_log.error("[update_hids_agent_status]: Agent ID could not be empty") raise APIInvalidHIDSAgentID(agent_id) try: sensor_id_bin = get_bytes_from_uuid(sensor_id) status_integer = Hids_Agents.get_status_integer_from_string(agent_status) db.session.query(Hids_Agents).filter( and_(Hids_Agents.agent_id == agent_id, Hids_Agents.sensor_id == sensor_id_bin)).update({"agent_status": status_integer}) except Exception as msg: api_log.error("[update_hids_agent_status]: %s" % str(msg)) raise APICannotUpdateHIDSAgent(agent_id, sensor_id)
def get_system_info(system_id): """ Return all information related to system :param System ID """ system_info = {} try: system_id_bin = get_bytes_from_uuid(system_id) system = db.session.query(System).filter(System.id == system_id_bin).one() if system: system_info = { 'id': get_uuid_string_from_bytes(system.id), 'name': system.name, 'admin_ip': get_ip_str_from_bytes(system.admin_ip) if system.admin_ip is not None else None, 'vpn_ip': get_ip_str_from_bytes(system.vpn_ip) if system.vpn_ip is not None else None, 'profile': system.profile, 'sensor_id': get_uuid_string_from_bytes(system.sensor_id) if system.sensor_id is not None else None, 'server_id': get_uuid_string_from_bytes(system.server_id) if system.server_id is not None else None, 'database_id': get_uuid_string_from_bytes( system.database_id) if system.database_id is not None else None, 'host_id': get_uuid_string_from_bytes(system.host_id) if system.host_id is not None else None, 'ha_ip': get_ip_str_from_bytes(system.ha_ip) if system.ha_ip is not None else None, 'ha_name': system.ha_name, 'ha_role': system.ha_role } except Exception as err: db.session.rollback() return False, "Error while querying system {0}. Reason: {1}".format(system_id, err) return True, system_info
def delete_hids_agent(agent_id, sensor_id): """ Delete a HIDS agent Args: agent_id(str): HIDS agent ID sensor_id(str): Sensor ID Raises: APICannotResolveSensorID APIInvalidHIDSAgentID APICannotDeleteHIDSAgent """ if sensor_id is None: api_log.error("[delete_hids_agent]: Sensor ID could not be empty") raise APICannotResolveSensorID(sensor_id) if agent_id is None: api_log.error("[delete_hids_agent]: Agent ID could not be empty") raise APIInvalidHIDSAgentID(agent_id) try: sensor_id_bin = get_bytes_from_uuid(sensor_id) db.session.query(Hids_Agents).filter(and_(Hids_Agents.agent_id == agent_id, Hids_Agents.sensor_id == sensor_id_bin)).delete() except Exception as msg: api_log.error("[delete_hids_agent] %s" % str(msg)) raise APICannotDeleteHIDSAgent(agent_id, sensor_id)
def get_sensor_by_sensor_id(sensor_id): """Returns a Sensor object given a Sensor ID""" try: # Getting Sensor ID for local system if sensor_id.lower() == 'local': (success, system_id) = get_system_id_from_local() if not success: raise APICannotResolveLocalSystemID() (success, local_sensor_id) = get_sensor_id_from_system_id(system_id) if success and local_sensor_id: sensor_id = local_sensor_id if not is_valid_uuid(sensor_id): raise APICannotResolveSensorID(sensor_id) # Getting sensor information success = True sensor_id_bin = get_bytes_from_uuid(sensor_id.lower()) data = db.session.query(Sensor).filter(Sensor.id == sensor_id_bin).one() except NoResultFound: success = False data = "No sensor found with the given ID" except MultipleResultsFound: success = False data = "More than one sensor found with the given ID" except Exception as ex: db.session.rollback() success = False data = "Something wrong happen while retrieving the sensor {0}".format(ex) return success, data
def get_host_id_by_ip_ctx(ip, ctx, output='str'): """ Returns an Asset ID given an IP address and context """ host_id = None try: if ip and ctx: ip_bin = get_ip_bin_from_str(ip) ctx_bin = get_bytes_from_uuid(ctx) query = db.session.query(Host.id).filter(Host.ctx == ctx_bin) host = query.join(Host_Ip, Host_Ip.host_id == Host.id).filter(Host_Ip.ip == ip_bin).one() host_id = host.id else: return False, "IP address and/or context could not be empty" except NoResultFound: return True, host_id except Exception as msg: msg = str(msg) api_log.error(msg) return False, "Asset ID not found in the system" if output == 'str': return True, get_uuid_string_from_bytes(host_id) else: return True, host_id
def set_sensor_properties_value(sensor_id, property_name, value): result = True try: message = "" db.session.begin() sensor_id_binary = get_bytes_from_uuid(sensor_id) property = db.session.query(Sensor_Properties).filter(Sensor_Properties.sensor_id == sensor_id_binary).one() if property is not None: if hasattr(property, property_name): setattr(property, property_name, value) db.session.merge(property) else: result = False message = "Invalid property name <%s>" % property_name db.session.commit() except NoResultFound: db.session.rollback() result = False message = "No property found " except MultipleResultsFound: db.session.rollback() result = False message = "More than one value for the property!! " except Exception as err: db.session.rollback() result = False message = "An error occurred while setting the sensor_property value %s" % str(err) return result, message
def get_current_status_message_from_id(current_status_id): """Retrieves the Current_Status message id with the given id""" try: data = db.session.query(Current_Status).filter( Current_Status.message_id == get_bytes_from_uuid( current_status_id)).one() except NoResultFound: return (False, "No Current_Status found with id '%s'" % str(current_status_id)) except MultipleResultsFound: return (False, "More than one Current_Status found with id '%s'" % str(current_status_id)) except Exception, msg: db.session.rollback() return (False, "Unknown error while querying for status message '%s': %s" % (str(current_status_id), str(msg)))
def load_messages_to_db(msg_list): """ Load list of messages into DB Status_Message table Args: msg_list ([Message]): Message list purge (boolean): Indicates when the fucntion should purge old messages. Returns: success (bool): True if successful, False elsewhere result (str): Error message (if any) """ success = True result = "" try: if msg_list: db.session.begin() for msg in msg_list: db_msg = Status_Message( id=get_bytes_from_uuid(msg.id), level=Status_Message.get_level_integer_from_string( msg.level), type=msg.type, message_role=msg.message_role, action_role=msg.action_role, title=msg.title, description=msg.description, actions=msg.actions, alternative_actions=msg.alternative_actions, source=msg.source) db.session.merge(db_msg) # insert or update # remove those messages that have been dissapeared messsages_ids_str = ','.join( ["'%s'" % msg.id.replace('-', '').upper() for msg in msg_list]) cmd = "delete from status_message where hex(id) not in (%s) and source='monitor'" % ( messsages_ids_str) db.session.connection(mapper=Status_Message).execute(cmd) #cmd = "delete current_status from current_status left join status_message on current_status.message_id=status_message.id where status_message.id is null;" #db.session.connection(mapper=Current_Status).execute(cmd) #success, result = purge_current_status_messages() db.session.commit() except Exception, e: success = False result = "[load_messages_to_db] Error: %s" % str(e) db.session.rollback()
def get_system_ip_from_system_id(system_id, output='str', local_loopback=True): """ Return the ip of a system using its id. """ try: if is_local(system_id): success, system_ip = get_system_ip_from_local( output='bin', local_loopback=local_loopback) if not success: return success, system_ip else: system_id_bin = get_bytes_from_uuid(system_id.lower()) system = db.session.query(System).filter( System.id == system_id_bin).one() system_ip = system.vpn_ip if system.vpn_ip else system.admin_ip except NoResultFound, msg: return False, "No system found with id '%s'" % str(system_id)
def get_host_by_host_id(host_id): """ Returns a Host object given its host_id Args: host_id (uuid): Host ID Return: Tuple (boolean,data) - boolean indicates whether the operation was successful or not - data will contain the data in case the operation was successful, or the error string otherwise """ host_id_bin = get_bytes_from_uuid(host_id) try: host = db.session.query(Host).filter(Host.id == host_id_bin).one() except NoResultFound, msg: return (True, None)
def save_monitor_data(monitor_id, component_id, component_type, data): result = True try: db.session.begin() monitor_data = Monitor_Data() monitor_data.component_id = get_bytes_from_uuid(component_id) monitor_data.timestamp = datetime.now() monitor_data.monitor_id = monitor_id monitor_data.data = data monitor_data.component_type = component_type db.session.add(monitor_data) db.session.commit() except Exception: import traceback print traceback.format_exc() db.session.rollback() result = False return result
def then_very_component_id_and_levels(context, var_cid, var_info): q = db.session.query(Current_Status).filter( Current_Status.component_id == get_bytes_from_uuid( context.alienvault[var_cid])) levels = var_info.split(",") f = [Current_Status.message.has(level=x) for x in levels] q = q.filter(or_(*f)) results = q.all() #print [x.serialize for x in results] total = len(results) j = json.loads(context.result.getvalue()) resp_total = j['data']['total'] assert_equal(total, int(resp_total)) for msg in j['data']['messages']: assert msg['component_id'] == context.alienvault[ var_cid], "Bad component_id in response from API: %s" % msg[ 'component_id'] assert (msg['message_level'] in levels) == True, "Bad level %s" % msg['message_level']
def db_get_server(server_id): """ Return the Server db object with server_id """ server = None if server_id.lower() == 'local': success, server_id = get_server_id_from_local() if not success: api_log.error(str(server_id)) return False, server_id try: server_id_bin = get_bytes_from_uuid(server_id) server = db.session.query(Server).filter( Server.id == server_id_bin).one() except NoResultFound, msg: return (False, "No server entry found with server id '%s'" % str(server_id))
def get_control_node(self): server_id = self.__config_repository.get_config(CONFIG_SERVER_ID).value software_version = self.__config_repository.get_config( CONFIG_VERSION).value system = self.__system_repository.get_system() server = self.__server_repository.get_server( get_bytes_from_uuid(server_id)) contact_person = self.__contact_person_repository.get_contact_person() platform = self.__platform_repo.get_platform(system.admin_ip) # Public IP is configured on AMI systems only and should be used as a control node's IP for such systems. # For other systems, high availability configuration IP (if configured) has more priority than admin IP. control_node_ip = platform and platform.public_ip or system.ha_ip or system.admin_ip return self.__model_constructor( system.id, system.name, server.descr, platform and platform.name, platform and platform.appliance_type, software_version, platform and platform.threat_intelligence_version, contact_person and contact_person.email, contact_person and contact_person.name, control_node_ip, system.vpn_ip)
def append_monitor_object(self, component_id, component_type, data): """ Save the monitor data. :param component_id: The component id - uuid canonical string :param component_type: Component type (see Component Types) :param data: The monitor json data. :return: True is successful, False otherwise """ return_value = True try: monitor_data = Monitor_Data() monitor_data.component_id = get_bytes_from_uuid(component_id) monitor_data.timestamp = datetime.now() monitor_data.monitor_id = self.monitor_id monitor_data.data = data monitor_data.component_type = component_type #db.session.add(monitor_data) self.monitor_objects.append(monitor_data) except Exception: return_value = False return return_value
def get_system(self): _, system_id = get_system_id_from_local() system_id_bin = get_bytes_from_uuid(system_id) system_info = db.session.query( System.name, System.admin_ip, System.vpn_ip, System.ha_ip ).filter(System.id == system_id_bin).one() system_name = system_info[0] system_admin_ip = get_ip_str_from_bytes(system_info[1]) system_vpn_ip = get_ip_str_from_bytes(system_info[2]) system_ha_ip = get_ip_str_from_bytes(system_info[3]) return self._system_constructor( system_id, system_name, system_admin_ip, system_vpn_ip, system_ha_ip )
def load_external_messages_on_db(messages): """Loads the downloaded messages into the database""" message_list = [] messages_to_be_removed = [] for message in messages: msg_id_binary = get_bytes_from_uuid(str(message['msg_id'])) if message['status'] == 'delete': messages_to_be_removed.append(msg_id_binary) continue message_list.append(message) success = True data = "" if len(message_list) > 0: success, data = load_mcserver_messages(message_list) success_remove = True data_remove = "" if len(messages_to_be_removed) > 0: success_remove, data_remove = delete_messages(messages_to_be_removed) return ((success and success_remove), { 'loaded': data, 'removed': data_remove })
def when_select_random_asset (context,var_type,var_uuid): # First, select net,host,system,server,user,sensor value = None while value is None: asset = var_type try: value = { 'user': str(uuid.UUID(db.session.query(Users).order_by(func.rand()).limit(1).one().serialize['uuid'])), 'net' : str(uuid.UUID(db.session.query(Net).order_by(func.rand()).limit(1).one().serialize['id'])), 'host': str(uuid.UUID(db.session.query(Host).order_by(func.rand()).limit(1).one().serialize['id'])), 'sensor': str(uuid.UUID(db.session.query(Sensor).order_by(func.rand()).limit(1).one().serialize['id'])), 'system': str(uuid.UUID(db.session.query(System).order_by(func.rand()).limit(1).one().serialize['uuid'])), 'server': str(uuid.UUID(db.session.query(Server).order_by(func.rand()).limit(1).one().serialize['id'])), }.get(asset) except NoResultFound: assert None,"No asset of type '%s' in system" % asset # Verify if the hosts is in the current_status q = db.session.query(Current_Status).filter(Current_Status.component_id == get_bytes_from_uuid (value)).all() if len(q) == 0: value = None context.alienvault[var_uuid] = value
def get_sensor_by_sensor_id(sensor_id): """Returns a Sensor object given a Sensor ID""" try: # Getting Sensor ID for local system if sensor_id.lower() == 'local': (success, system_id) = get_system_id_from_local() if not success: raise APICannotResolveLocalSystemID() (success, local_sensor_id) = get_sensor_id_from_system_id(system_id) if success and local_sensor_id: sensor_id = local_sensor_id if not is_valid_uuid(sensor_id): raise APICannotResolveSensorID(sensor_id) # Getting sensor information success = True sensor_id_bin = get_bytes_from_uuid(sensor_id.lower()) data = db.session.query(Sensor).filter( Sensor.id == sensor_id_bin).one() except NoResultFound: success = False data = "No sensor found with the given ID" except MultipleResultsFound: success = False data = "More than one sensor found with the given ID" except Exception as ex: db.session.rollback() success = False data = "Something wrong happen while retrieving the sensor {0}".format( ex) return success, data
def has_forward_role(server_id): """Check if server_id has forward role Checks the Server_Forward_Role table and returns True/False depending on wether the server_id appears as server_src_id on that table Args: server_id (str): server_id to check for forward role Returns: bool: True if server_id has forward role, False elsewhere """ is_forwarder = False try: forwarder_id = db.session.query(Server_Forward_Role).filter( Server_Forward_Role.server_src_id == get_bytes_from_uuid( server_id)).first() if forwarder_id: is_forwarder = True except Exception, e: api_log.error( "An error occurred when checking server_forward_role: %s" % str(e))
def set_up_db_schema(self): self.cursor.execute(""" CREATE TABLE `sensor` ( `id` binary(16) NOT NULL, `name` varchar(64) NOT NULL, `ip` varbinary(16) DEFAULT NULL, `priority` smallint(6) NOT NULL, `port` int(11) NOT NULL, `connect` smallint(6) NOT NULL, `descr` varchar(255) NOT NULL, `tzone` float NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 """) self.cursor.execute( """ CREATE TABLE `sensor_properties` ( `sensor_id` binary(16) NOT NULL, `version` varchar(64) NOT NULL, `has_nagios` tinyint(1) NOT NULL DEFAULT '1', `has_ntop` tinyint(1) NOT NULL DEFAULT '1', `has_vuln_scanner` tinyint(1) NOT NULL DEFAULT '1', `has_kismet` tinyint(1) NOT NULL DEFAULT '0', `ids` tinyint(1) NOT NULL DEFAULT '0', `passive_inventory` tinyint(1) NOT NULL DEFAULT '0', `netflows` tinyint(1) NOT NULL DEFAULT '0', PRIMARY KEY (`sensor_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 """ ) self.cursor.execute( """ CREATE TABLE `config` ( `conf` varchar(255) NOT NULL, `value` text CHARACTER SET latin1 COLLATE latin1_general_ci, PRIMARY KEY (`conf`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 """ ) self.expected_sensor_id = str(uuid.uuid4()) self.expected_name = 'sensor_name' self.expected_is_connected = True self.expected_descr = 'sensor description' self.cursor.execute(""" INSERT INTO sensor (id, name, ip, priority, port, connect, descr) VALUES (%s, %s, %s, %s, %s, %s, %s)""", ( get_bytes_from_uuid(self.expected_sensor_id), self.expected_name, socket.inet_aton(self.expected_ip), 1, 8080, 0, self.expected_descr )) self.expected_software_version = '100500' self.cursor.execute(""" INSERT INTO sensor_properties (sensor_id, version) VALUES (%s, %s) """, ( get_bytes_from_uuid(self.expected_sensor_id), self.expected_software_version )) self.expected_platform_name = 'alienvault-hyperv' self.expected_platform_by_ansible = 'alienvault-hyperv' self.expected_appliance_type_by_ansible = 'alienvault-vmware-aio-6x1gb' self.expected_intelligence_version = '100501' self.db.commit()
def given_gen_status_message(context, var_n): db.session.query( Current_Status).delete() # Delete all current_status entries total = 0 total_msg = _return_total_status() assert int( var_n ) <= total_msg, "We don't have enought messages and asset to generate %d current_status entries " % int( var_n) while total < int(var_n): ctype = random.choice( ['net', 'host', 'user', 'sensor', 'server', 'system']) entry = Current_Status() try: c_id = { 'user': str( uuid.UUID( db.session.query(Users).order_by( func.rand()).limit(1).one().serialize['uuid'])), 'net': str( uuid.UUID( db.session.query(Net).order_by( func.rand()).limit(1).one().serialize['id'])), 'host': str( uuid.UUID( db.session.query(Host).order_by( func.rand()).limit(1).one().serialize['id'])), 'sensor': str( uuid.UUID( db.session.query(Sensor).order_by( func.rand()).limit(1).one().serialize['id'])), 'system': str( uuid.UUID( db.session.query(System).order_by( func.rand()).limit(1).one().serialize['uuid'])), 'server': str( uuid.UUID( db.session.query(Server).order_by( func.rand()).limit(1).one().serialize['id'])), }.get(ctype) except NoResultFound: assert None, "Can't load a asset of type '%s'" % ctype # We have now the component_id # Select a msg_id try: msg_entry = db.session.query(Status_Message).order_by( func.rand()).limit(1).one().serialize except NoResultFound: assert None, "Can't load a message entry" entry.id = get_bytes_from_uuid(str(uuid.uuid1())) entry.message_id = get_bytes_from_uuid(msg_entry['id']) entry.component_id = get_bytes_from_uuid(c_id) entry.component_type = ctype entry.viewed = random.choice([True, False]) entry.additional_info = """{"msg_id": "Random generate message"}""" # check q = db.session.query(Current_Status).filter( and_(Current_Status.message_id == entry.message_id, Current_Status.component_id == entry.component_id)).all() if len(q) > 0: continue db.session.begin() db.session.merge(entry) db.session.commit() total = total + 1
def given_gen_status_message(context, var_n, var_type): db.session.query( Current_Status).delete() # Delete all current_status entries ctypes = var_type.split(",") total = 0 while (total < 100): ctype = random.choice(ctypes) assert (ctype in ['net', 'host', 'user', 'sensor', 'server', 'system']) == True, "Unknown type '%s'" % ctype entry = Current_Status() # Select a entry try: c_id = { 'user': str( uuid.UUID( db.session.query(Users).order_by( func.rand()).limit(1).one().serialize['uuid'])), 'net': str( uuid.UUID( db.session.query(Net).order_by( func.rand()).limit(1).one().serialize['id'])), 'host': str( uuid.UUID( db.session.query(Host).order_by( func.rand()).limit(1).one().serialize['id'])), 'sensor': str( uuid.UUID( db.session.query(Sensor).order_by( func.rand()).limit(1).one().serialize['id'])), 'system': str( uuid.UUID( db.session.query(System).order_by( func.rand()).limit(1).one().serialize['uuid'])), 'server': str( uuid.UUID( db.session.query(Server).order_by( func.rand()).limit(1).one().serialize['id'])) }.get(ctype) except NoResultFound: assert None, "Can't load a asset of type '%s'" % ctype # We have now the component_id # Select a msg_id try: msg_entry = db.session.query(Status_Message).order_by( func.rand()).limit(1).one().serialize except NoResultFound: assert None, "Can't load a message entry" entry.id = get_bytes_from_uuid(str(uuid.uuid1())) entry.message_id = get_bytes_from_uuid(msg_entry['id']) entry.component_id = get_bytes_from_uuid(c_id) entry.component_type = ctype entry.viewed = False entry.suppressed = False entry.additional_info = """{"id": "Random generate message"}""" db.session.begin() db.session.merge(entry) db.session.commit() total = total + 1
def get_host_by_host_id(host_id): """ Returns a Host object given its host_id Args: host_id (uuid): Host ID Return: Tuple (boolean,data) - boolean indicates whether the operation was successful or not - data will contain the data in case the operation was successful, or the error string otherwise """ host_id_bin = get_bytes_from_uuid(host_id) try: host = db.session.query(Host).filter(Host.id == host_id_bin).one() except NoResultFound: return True, None except Exception as err_detail: return False, "Error captured while querying for host id '%s': %s" % ( str(host_id), str(err_detail)) # Build the output host_output = {} if host is not None: host_dict = host.__dict__ for key, value in host_dict.iteritems(): if key in ('_sa_instance_state', ): continue if key in ('ctx', 'id'): host_output[key] = get_uuid_string_from_bytes(value) continue if key == "permissions": host_output[key] = str(value) if key == 'asset': host_output['asset_value'] = value else: host_output[key] = value host_output['os'] = "" host_output['model'] = "" for host_property in host.host_properties: if host_property.property_ref == 3: host_output['os'] = host_property.value continue if host_property.property_ref == 14: host_output['model'] = host_property.value continue host_output['ips'] = [ get_ip_str_from_bytes(x.ip) for x in host.host_ips ] host_output['sensors'] = [ get_uuid_string_from_bytes(x.sensor_id) for x in host.host_sensor_reference ] host_output['services'] = [x.service for x in host.host_services] host_output['networks'] = [ get_uuid_string_from_bytes(x.net_id) for x in host.host_net_reference ] return True, host_output
def then_current_status_verify (context,var_uuid): q = db.session.query(Current_Status).filter ( Current_Status.component_id == get_bytes_from_uuid (context.alienvault[var_uuid])).all() assert_equal (0, len(q),"Not all current_status messages deleted")
def then_monitor_data_verify (context,var_uuid): q = db.session.query(Monitor_Data).filter (Monitor_Data.component_id == get_bytes_from_uuid (context.alienvault[var_uuid])).all() assert_equal (0, len(q),"Not all monitor_data messages deleted")
System.profile.ilike(system_type)).all() else: system_list = db.session.query(System).filter( System.profile.ilike('%' + system_type + '%')).all() except Exception, msg: db.session.rollback() return False, "Error while querying for '%s' systems: %s" % ( system_type if system_type != '' else 'all', str(msg)) if directly_connected: try: server_ip = get_ip_bin_from_str( db.session.query(Config).filter( Config.conf == 'server_address').one().value) server_id = get_bytes_from_uuid( db.session.query(Config).filter( Config.conf == 'server_id').one().value) connected_servers = [ x.child_id for x in db.session.query(Server_Hierarchy).filter( Server_Hierarchy.parent_id == server_id).all() ] connected_servers.append(server_id) except Exception, msg: db.session.rollback() return False, "Error while querying for server: '%s'" % str(msg) if not system_type or system_type.lower() == 'server': system_list = filter( lambda x: x.server_id in connected_servers or 'server' not in x .profile.lower(), system_list)
def then_verify_interfaces(context,var_uuid): j = json.loads(context.result.getvalue()) print (j['data']['interfaces']) # Verify the correct json # Obtain admin_ip from database # Log into system, obtain interfaces list # Verify interface lists (copy the file from remote system) try: if context.alienvault[var_uuid] !='local': uuid = get_bytes_from_uuid(context.alienvault[var_uuid]) admin_ip = db.session.query(System).filter(System.id == uuid).one().serialize.get("admin_ip") else: admin_ip = '127.0.0.1' r = re.compile(r'inet\s(.*?)/(.*?)\sbrd\s(.*?)\sscope') config = ConfigParser() assert config.read ("/etc/ansible/ansible.cfg")[0] == "/etc/ansible/ansible.cfg", "Can\'t load ansible.cfg file" sshkey = config.get("defaults","private_key_file") ssh = Popen( ["ssh", "-i", sshkey, "-l", "avapi", admin_ip, "/bin/cat /proc/net/dev"], shell=False, # this protects you against most of the risk associated with piping commands to the shell stdout=PIPE, stderr=PIPE ) (stdoutdata, stderrdata) = ssh.communicate() lines = filter(None, stdoutdata.splitlines()) iface_set = set ([x.split (':',2)[0].strip() for x in lines[2:]]) iface_response = set (j['data']['interfaces'].keys()) assert iface_set == iface_response, "Bad interfaces returnes from API" # Check the properties (ip etc ) # Flags # obtain the flags flags = {} for iface in iface_response: ssh = Popen( ["ssh", "-i", sshkey, "-l", "avapi", admin_ip, "/bin/cat /sys/class/net/%s/flags" % iface], shell=False, stdout=PIPE, stderr=PIPE ) (stdoutdata, stderrdata) = ssh.communicate() flaglines = filter(None, stdoutdata.splitlines()) flags[iface] = {'promisc':(int(flaglines[0].strip(),16) & IFF_PROMISC) == IFF_PROMISC} assert j['data']['interfaces'][iface]['promisc'] == flags[iface]['promisc'],"Bad interface promisc flag API CALL= %s System = %s " % (j['data']['interfaces'][iface]['promisc'], flags[iface]) ssh = Popen( ["ssh", "-i", sshkey, "-l", "avapi", admin_ip, "/bin/ip addr show dev %s" % iface], shell=False, stdout=PIPE, stderr=PIPE ) (stdoutdata, stderrdata) = ssh.communicate() ipaddr_lines = filter(None, stdoutdata.splitlines()) for line in ipaddr_lines[2:]: m = r.match(line.strip()) if m: flags[iface]['ip'] = m.group(1) v = (2**int(m.group(2)))-1 flags[iface]['mask'] = "%u.%u.%u.%u" % ((v & 0xFF), \ (v & 0xFF00) >> 8, \ (v & 0xFF0000) >> 16, \ (v & 0xFF000000) >> 24 ) #print flags[iface]['mask'] flags[iface]['bcast'] = m.group(3) assert j['data']['interfaces'][iface]['ipv4']['address'] == flags[iface]['ip'],"Bad address at iface %s" % iface assert j['data']['interfaces'][iface]['ipv4']['netmask'] == flags[iface]['mask'],"Bad mask at iface %s" % iface #print flags except NoResultFound: assert False,"Can't find sensor with uuid %s in database " % var_uuid except MultipleResultsFound, msg: assert False,"Multiples result for query. Internal database error uuid => %s" % var_uuid
def get_current_status_messages(component_id=None, message_level=None, order_by=None, page=None, page_row=None, order_desc=None, component_type=None, message_id=None, message_type=None, search=None, only_unread=None, login_user=None, is_admin=False): """Returns the list of current_status messages matching the given criteria. Args: component_id(UUID string): Component ID related with the message message_level(list<str>): Message level order_by(str): Current status field by which you want to sort the results. page(int): Page number page_row(int): Number of items per page order_desc(Boolean or None): Specify whether you want to sort the results in descendig order or not. component_type(str): Component Type related with the message message_id(UUID string): The message ID you are looking for message_type(list<str>): Kind of message you want to retrieve. search(str): It's a free text to search for message title only_unread(Boolean or None): If true, retrieve only unread messages login_user (admin): logged user on the system is_admin(bool): Whether the current user is admin or not. Returns: [Current_Status] A list of Current_Status Items """ if login_user is None or login_user == "": return True, {'messages': {}, 'total': 0} query = db.session.query(Current_Status) # message_type and message_level are fields belonging to the related table status_message # We need to deal with this situation when we set the build the order_by clause if order_by is not None: if order_by not in ['message_level', 'message_type', 'message_title']: if order_desc: query = query.order_by(desc(order_by)) else: query = query.order_by(asc(order_by)) else: order_by_field = Status_Message.type if order_by == 'message_level': order_by_field = Status_Message.level if order_by == 'message_title': order_by_field = Status_Message.title if order_desc: query = query.join(Status_Message).order_by( desc(order_by_field)) else: query = query.join(Status_Message).order_by( asc(order_by_field)) if login_user != "admin" and not is_admin: # neither user admin nor is_admin query = query.join( UserPermissions, UserPermissions.component_id == Current_Status.component_id) query = query.filter(and_(UserPermissions.login == login_user)) query = query.order_by(asc(Current_Status.viewed)) if component_id is not None: query = query.filter( and_(Current_Status.component_id == get_bytes_from_uuid( component_id))) if message_id is not None: query = query.filter( and_(Current_Status.message_id == get_bytes_from_uuid(message_id))) if message_level is not None: new_filter = [ Current_Status.message.has( Status_Message.level.like( Status_Message.get_level_integer_from_string(x))) for x in message_level ] query = query.filter(or_(*new_filter)) if message_type is not None: new_filter = [ Current_Status.message.has(Status_Message.type.like(x)) for x in message_type ] query = query.filter(or_(*new_filter)) if component_type is not None: query = query.filter( and_(Current_Status.component_type == component_type)) if search is not None: query = query.filter( or_( Current_Status.message.has( Status_Message.title.like("%" + search + "%")), Current_Status.message.has( Status_Message.description.like("%" + search + "%")))) if only_unread: query = query.filter(and_(Current_Status.viewed == 0)) query = query.filter( or_(Current_Status.suppressed == None, Current_Status.suppressed == 0)) # Always order by creationtime if order_by != "creation_time": query = query.order_by(desc(Current_Status.creation_time)) msgs = {} total = 0 try: if page is None: # return all data = query.all() msgs = [x.serialize for x in data] total = len(data) else: current_page = paginate(query, page, page_row, error_out=False) msgs = [x.serialize for x in current_page['items']] total = current_page['total'] except Exception as err: api_log.error("status: get_status_messages: %s" % format_exc()) return False, "Internal error %s" % str(err) return True, {'messages': msgs, 'total': total}
def load_mcserver_messages(message_list): """Adds or updates messages coming from the mcserver Args: message_list[Status_Message] Returns: success (bool): True if successful, False elsewhere result (str): Error message (if any) """ result = "" success = True try: db.session.begin() for msg in message_list: msg_id_str = str(msg['msg_id']) msg_id_binary = get_bytes_from_uuid(msg_id_str) additional_info_json = "" if msg['additional_info'] is not None and msg[ 'additional_info'] != "": try: additional_info_json = json.dumps(msg['additional_info']) except Exception as e: api_log.warning( "Message with an invalid additional_info %s - %s" % (msg_id_str, str(e))) additional_info_json = "" success, status_message = get_status_message_from_id( message_id=msg_id_binary, is_admin=True, serialize=False) if success: #update values: status_message.level = Status_Message.get_level_integer_from_string( str(msg['level'])) status_message.title = msg['title'] status_message.description = msg['description'] status_message.type = msg['type'] success, current_status_message = get_current_status_from_message_id( msg_id_str) if not success or len(current_status_message) != 1: api_log.error( "Invalid external message %s. Current_Status: %s, tuples(%s)" % (msg_id_str, success, len(current_status_message))) continue current_status_message[ 0].additional_info = additional_info_json db.session.merge(current_status_message[0]) db.session.merge(status_message) else: new_msg = Status_Message() new_msg.id = msg_id_binary new_msg.level = Status_Message.get_level_integer_from_string( str(msg['level'])) new_msg.title = msg['title'] new_msg.description = msg['description'] new_msg.type = msg['type'] new_msg.expire = datetime.strptime(msg['valid_to'], "%Y-%m-%dT%H:%M:%S") new_msg.actions = "" new_msg.alternative_actions = "" new_msg.source = "external" current_status_message = Current_Status() current_status_message.id = uuid4().bytes current_status_message.component_type = 'external' current_status_message.creation_time = datetime.strptime( msg['valid_from'], "%Y-%m-%dT%H:%M:%S") current_status_message.message_id = new_msg.id current_status_message.additional_info = "" current_status_message.suppressed = 0 current_status_message.viewed = 0 current_status_message.additional_info = additional_info_json db.session.add(new_msg) db.session.add(current_status_message) db.session.commit() except Exception, e: success = False result = "[load_mcserver_messages(] Error: %s" % str(e) db.session.rollback()
def create_host(ips, sensor_id, hostname='', fqdns='', asset_value=2, threshold_c=30, threshold_a=30, alert=0, persistence=0, nat=None, rrd_profile=None, descr='', lat=0, lon=0, icon=None, country=None, external_host=0, permissions=0, av_component=0, output='str', refresh=False): """ Creates a new host in the database Args: Host data Return: Tuple (boolean, msg) - boolean indicates whether the operation was successful or not - msg will be the host ID, or the error string otherwise """ if len(ips) == 0: return False, "At least one IP is required" succes, ctx = get_sensor_ctx_by_sensor_id(sensor_id) if not is_valid_uuid(ctx): return False, "ctx is not a valid canonical uuid" ctx = get_bytes_from_uuid(ctx) host_id = str(uuid.uuid4()) if hostname == '': hostname = "Host-%s" % (ips[0].replace(".", "-")) try: db.session.begin() for host_ip in ips: host_ip_object = Host_Ip(host_id=get_bytes_from_uuid(host_id), ip=get_ip_bin_from_str(host_ip), mac=None, interface=None) db.session.merge(host_ip_object) host = Host(id=get_bytes_from_uuid(host_id), ctx=ctx, hostname=hostname, fqdns=fqdns, asset=asset_value, threshold_c=threshold_c, threshold_a=threshold_a, alert=alert, persistence=persistence, nat=nat, rrd_profile=rrd_profile, descr=descr, lat=lat, lon=lon, icon=icon, country=country, external_host=external_host, permissions=permissions, av_component=av_component) db.session.merge(host) hs_reference = Host_Sensor_Reference(host_id=get_bytes_from_uuid(host_id), sensor_id=get_bytes_from_uuid(sensor_id)) db.session.merge(hs_reference) db.session.commit() except Exception, msg: db.session.rollback() message = "There was a problem adding new Host %s to the database: %s" % (hostname, str(msg)) api_log.error(message) return False, message