diff --git a/_modules/get_eventlog.py b/_modules/get_eventlog.py deleted file mode 100644 index f60c1f35..00000000 --- a/_modules/get_eventlog.py +++ /dev/null @@ -1,91 +0,0 @@ -from __future__ import absolute_import -import win32evtlog -import win32con -import win32evtlogutil -import winerror -import datetime -import zlib -import json -import base64 - - -def _compress_json(j): - return { - "wineventlog": base64.b64encode( - zlib.compress(json.dumps(j).encode("utf-8", errors="ignore")) - ).decode("ascii", errors="ignore") - } - - -def get_eventlog(logtype, last_n_days): - - start_time = datetime.datetime.now() - datetime.timedelta(days=last_n_days) - flags = win32evtlog.EVENTLOG_BACKWARDS_READ | win32evtlog.EVENTLOG_SEQUENTIAL_READ - - status_dict = { - win32con.EVENTLOG_AUDIT_FAILURE: "AUDIT_FAILURE", - win32con.EVENTLOG_AUDIT_SUCCESS: "AUDIT_SUCCESS", - win32con.EVENTLOG_INFORMATION_TYPE: "INFO", - win32con.EVENTLOG_WARNING_TYPE: "WARNING", - win32con.EVENTLOG_ERROR_TYPE: "ERROR", - 0: "INFO", - } - - computer = "localhost" - hand = win32evtlog.OpenEventLog(computer, logtype) - total = win32evtlog.GetNumberOfEventLogRecords(hand) - log = [] - uid = 0 - done = False - - try: - while 1: - events = win32evtlog.ReadEventLog(hand, flags, 0) - for ev_obj in events: - - uid += 1 - # return once total number of events reach or we'll be stuck in an infinite loop - if uid >= total: - done = True - break - - the_time = ev_obj.TimeGenerated.Format() - time_obj = datetime.datetime.strptime(the_time, "%c") - if time_obj < start_time: - done = True - break - - computer = str(ev_obj.ComputerName) - src = str(ev_obj.SourceName) - evt_type = str(status_dict[ev_obj.EventType]) - evt_id = str(winerror.HRESULT_CODE(ev_obj.EventID)) - evt_category = str(ev_obj.EventCategory) - record = str(ev_obj.RecordNumber) - msg = ( - str(win32evtlogutil.SafeFormatMessage(ev_obj, logtype)) - .replace("<", "") - .replace(">", "") - ) - - event_dict = { - "computer": computer, - "source": src, - "eventType": evt_type, - "eventID": evt_id, - "eventCategory": evt_category, - "message": msg, - "time": the_time, - "record": record, - "uid": uid, - } - - log.append(event_dict) - - if done: - break - - except Exception: - pass - - win32evtlog.CloseEventLog(hand) - return _compress_json(log) diff --git a/_modules/process_manager.py b/_modules/process_manager.py deleted file mode 100644 index dc17435e..00000000 --- a/_modules/process_manager.py +++ /dev/null @@ -1,33 +0,0 @@ -from __future__ import absolute_import -import psutil -from time import sleep -import random -import string - -def get_procs(): - ret = [] - - # setup - for proc in psutil.process_iter(): - with proc.oneshot(): - proc.cpu_percent(interval=None) - - # need time for psutil to record cpu percent - sleep(1) - - for proc in psutil.process_iter(): - x = {} - with proc.oneshot(): - x['name'] = proc.name() - x['cpu_percent'] = proc.cpu_percent(interval=None) / psutil.cpu_count() - x['memory_percent'] = proc.memory_percent() - x['pid'] = proc.pid - x['ppid'] = proc.ppid() - x['status'] = proc.status() - x['username'] = proc.username() - x['id'] = ''.join([random.choice(string.ascii_letters + string.digits) for n in range(10)]) - - if proc.pid != 0: - ret.append(x) - - return ret \ No newline at end of file diff --git a/_modules/system_info.py b/_modules/system_info.py deleted file mode 100644 index efb81bbc..00000000 --- a/_modules/system_info.py +++ /dev/null @@ -1,49 +0,0 @@ -from __future__ import absolute_import -import wmi - - -class SystemDetail: - def __init__(self): - self.c = wmi.WMI() - self.comp_sys_prod = self.c.Win32_ComputerSystemProduct() - self.comp_sys = self.c.Win32_ComputerSystem() - self.memory = self.c.Win32_PhysicalMemory() - self.os = self.c.Win32_OperatingSystem() - self.base_board = self.c.Win32_BaseBoard() - self.bios = self.c.Win32_BIOS() - self.disk = self.c.Win32_DiskDrive() - self.network_adapter = self.c.Win32_NetworkAdapter() - self.network_config = self.c.Win32_NetworkAdapterConfiguration() - self.desktop_monitor = self.c.Win32_DesktopMonitor() - self.cpu = self.c.Win32_Processor() - self.usb = self.c.Win32_USBController() - - def get_all(self, obj): - ret = [] - for i in obj: - tmp = [ - {j: getattr(i, j)} - for j in list(i.properties) - if getattr(i, j) is not None - ] - ret.append(tmp) - - return ret - - -def system_info(): - info = SystemDetail() - return { - "comp_sys_prod": info.get_all(info.comp_sys_prod), - "comp_sys": info.get_all(info.comp_sys), - "mem": info.get_all(info.memory), - "os": info.get_all(info.os), - "base_board": info.get_all(info.base_board), - "bios": info.get_all(info.bios), - "disk": info.get_all(info.disk), - "network_adapter": info.get_all(info.network_adapter), - "network_config": info.get_all(info.network_config), - "desktop_monitor": info.get_all(info.desktop_monitor), - "cpu": info.get_all(info.cpu), - "usb": info.get_all(info.usb), - } diff --git a/_modules/win_agent.py b/_modules/win_agent.py index 5329e82b..01099ada 100644 --- a/_modules/win_agent.py +++ b/_modules/win_agent.py @@ -1,8 +1,19 @@ from __future__ import absolute_import import psutil import os +import datetime +import zlib +import json +import base64 +import wmi +import win32evtlog +import win32con +import win32evtlogutil +import winerror +from time import sleep PROGRAM_DIR = "C:\\Program Files\\TacticalAgent" +TAC_RMM = os.path.join(PROGRAM_DIR, "tacticalrmm.exe") def get_services(): @@ -27,12 +38,170 @@ def uninstall_agent(): def update_salt(): - tacrmm = os.path.join(PROGRAM_DIR, "tacticalrmm.exe") - __salt__["cmd.run_bg"]([tacrmm, "-m", "updatesalt"]) + __salt__["cmd.run_bg"]([TAC_RMM, "-m", "updatesalt"]) return "ok" def run_manual_checks(): - tacrmm = os.path.join(PROGRAM_DIR, "tacticalrmm.exe") - __salt__["cmd.run_bg"]([tacrmm, "-m", "runchecks"]) + __salt__["cmd.run_bg"]([TAC_RMM, "-m", "runchecks"]) return "ok" + + +class SystemDetail: + def __init__(self): + self.c = wmi.WMI() + self.comp_sys_prod = self.c.Win32_ComputerSystemProduct() + self.comp_sys = self.c.Win32_ComputerSystem() + self.memory = self.c.Win32_PhysicalMemory() + self.os = self.c.Win32_OperatingSystem() + self.base_board = self.c.Win32_BaseBoard() + self.bios = self.c.Win32_BIOS() + self.disk = self.c.Win32_DiskDrive() + self.network_adapter = self.c.Win32_NetworkAdapter() + self.network_config = self.c.Win32_NetworkAdapterConfiguration() + self.desktop_monitor = self.c.Win32_DesktopMonitor() + self.cpu = self.c.Win32_Processor() + self.usb = self.c.Win32_USBController() + + def get_all(self, obj): + ret = [] + for i in obj: + tmp = [ + {j: getattr(i, j)} + for j in list(i.properties) + if getattr(i, j) is not None + ] + ret.append(tmp) + + return ret + + +def system_info(): + info = SystemDetail() + return { + "comp_sys_prod": info.get_all(info.comp_sys_prod), + "comp_sys": info.get_all(info.comp_sys), + "mem": info.get_all(info.memory), + "os": info.get_all(info.os), + "base_board": info.get_all(info.base_board), + "bios": info.get_all(info.bios), + "disk": info.get_all(info.disk), + "network_adapter": info.get_all(info.network_adapter), + "network_config": info.get_all(info.network_config), + "desktop_monitor": info.get_all(info.desktop_monitor), + "cpu": info.get_all(info.cpu), + "usb": info.get_all(info.usb), + } + + +def get_procs(): + ret = [] + + # setup + for proc in psutil.process_iter(): + with proc.oneshot(): + proc.cpu_percent(interval=None) + + # need time for psutil to record cpu percent + sleep(1) + + for c, proc in enumerate(psutil.process_iter(), 1): + x = {} + with proc.oneshot(): + if proc.pid == 0 or not proc.name(): + continue + + x["name"] = proc.name() + x["cpu_percent"] = proc.cpu_percent(interval=None) / psutil.cpu_count() + x["memory_percent"] = proc.memory_percent() + x["pid"] = proc.pid + x["ppid"] = proc.ppid() + x["status"] = proc.status() + x["username"] = proc.username() + x["id"] = c + + ret.append(x) + + return ret + + +def _compress_json(j): + return { + "wineventlog": base64.b64encode( + zlib.compress(json.dumps(j).encode("utf-8", errors="ignore")) + ).decode("ascii", errors="ignore") + } + + +def get_eventlog(logtype, last_n_days): + + start_time = datetime.datetime.now() - datetime.timedelta(days=last_n_days) + flags = win32evtlog.EVENTLOG_BACKWARDS_READ | win32evtlog.EVENTLOG_SEQUENTIAL_READ + + status_dict = { + win32con.EVENTLOG_AUDIT_FAILURE: "AUDIT_FAILURE", + win32con.EVENTLOG_AUDIT_SUCCESS: "AUDIT_SUCCESS", + win32con.EVENTLOG_INFORMATION_TYPE: "INFO", + win32con.EVENTLOG_WARNING_TYPE: "WARNING", + win32con.EVENTLOG_ERROR_TYPE: "ERROR", + 0: "INFO", + } + + computer = "localhost" + hand = win32evtlog.OpenEventLog(computer, logtype) + total = win32evtlog.GetNumberOfEventLogRecords(hand) + log = [] + uid = 0 + done = False + + try: + while 1: + events = win32evtlog.ReadEventLog(hand, flags, 0) + for ev_obj in events: + + uid += 1 + # return once total number of events reach or we'll be stuck in an infinite loop + if uid >= total: + done = True + break + + the_time = ev_obj.TimeGenerated.Format() + time_obj = datetime.datetime.strptime(the_time, "%c") + if time_obj < start_time: + done = True + break + + computer = str(ev_obj.ComputerName) + src = str(ev_obj.SourceName) + evt_type = str(status_dict[ev_obj.EventType]) + evt_id = str(winerror.HRESULT_CODE(ev_obj.EventID)) + evt_category = str(ev_obj.EventCategory) + record = str(ev_obj.RecordNumber) + msg = ( + str(win32evtlogutil.SafeFormatMessage(ev_obj, logtype)) + .replace("<", "") + .replace(">", "") + ) + + event_dict = { + "computer": computer, + "source": src, + "eventType": evt_type, + "eventID": evt_id, + "eventCategory": evt_category, + "message": msg, + "time": the_time, + "record": record, + "uid": uid, + } + + log.append(event_dict) + + if done: + break + + except Exception: + pass + + win32evtlog.CloseEventLog(hand) + return _compress_json(log) diff --git a/api/tacticalrmm/agents/tasks.py b/api/tacticalrmm/agents/tasks.py index 7a95fd79..12084154 100644 --- a/api/tacticalrmm/agents/tasks.py +++ b/api/tacticalrmm/agents/tasks.py @@ -18,7 +18,7 @@ logger.configure(**settings.LOG_CONFIG) def get_wmi_detail_task(pk): agent = Agent.objects.get(pk=pk) resp = agent.salt_api_cmd( - hostname=agent.salt_id, timeout=30, func="system_info.system_info" + hostname=agent.salt_id, timeout=30, func="win_agent.system_info" ) agent.wmi_detail = resp.json()["return"][0][agent.salt_id] agent.save(update_fields=["wmi_detail"]) diff --git a/api/tacticalrmm/agents/views.py b/api/tacticalrmm/agents/views.py index e4b33ef3..63ce022d 100644 --- a/api/tacticalrmm/agents/views.py +++ b/api/tacticalrmm/agents/views.py @@ -155,7 +155,7 @@ def get_processes(request, pk): agent = get_object_or_404(Agent, pk=pk) try: resp = agent.salt_api_cmd( - hostname=agent.salt_id, timeout=70, func="process_manager.get_procs" + hostname=agent.salt_id, timeout=70, func="win_agent.get_procs" ) data = resp.json() except Exception: @@ -190,7 +190,7 @@ def get_event_log(request, pk, logtype, days): hostname=agent.salt_id, timeout=90, salt_timeout=85, - func="get_eventlog.get_eventlog", + func="win_agent.get_eventlog", arg=[logtype, int(days)], ) except Exception: