def delete_win_task_schedule(pk, pending_action=False): task = AutomatedTask.objects.get(pk=pk) nats_data = { "func": "delschedtask", "schedtaskpayload": { "name": task.win_task_name }, } r = asyncio.run(task.agent.nats_cmd(nats_data, timeout=10)) if r != "ok": # don't create pending action if this task was initiated by a pending action if not pending_action: PendingAction( agent=task.agent, action_type="taskaction", details={ "action": "taskdelete", "task_id": task.id }, ).save() task.sync_status = "pendingdeletion" task.save(update_fields=["sync_status"]) return # complete pending action since it was successful if pending_action: pendingaction = PendingAction.objects.get(pk=pending_action) pendingaction.status = "completed" pendingaction.save(update_fields=["status"]) task.delete() return "ok"
def schedule_reboot(self, obj): start_date = dt.datetime.strftime(obj, "%Y-%m-%d") start_time = dt.datetime.strftime(obj, "%H:%M") # let windows task scheduler automatically delete the task after it runs end_obj = obj + dt.timedelta(minutes=15) end_date = dt.datetime.strftime(end_obj, "%Y-%m-%d") end_time = dt.datetime.strftime(end_obj, "%H:%M") task_name = "TacticalRMM_SchedReboot_" + "".join( random.choice(string.ascii_letters) for _ in range(10)) r = self.salt_api_cmd( timeout=15, func="task.create_task", arg=[ f"name={task_name}", "force=True", "action_type=Execute", 'cmd="C:\\Windows\\System32\\shutdown.exe"', 'arguments="/r /t 5 /f"', "trigger_type=Once", f'start_date="{start_date}"', f'start_time="{start_time}"', f'end_date="{end_date}"', f'end_time="{end_time}"', "ac_only=False", "stop_if_on_batteries=False", "delete_after=Immediately", ], ) if r == "error" or (isinstance(r, bool) and not r): return "failed" elif r == "timeout": return "timeout" elif isinstance(r, bool) and r: from logs.models import PendingAction details = { "taskname": task_name, "time": str(obj), } PendingAction(agent=self, action_type="schedreboot", details=details).save() nice_time = dt.datetime.strftime(obj, "%B %d, %Y at %I:%M %p") return {"msg": {"time": nice_time, "agent": self.hostname}} else: return "failed"
def delete_win_task_schedule(pk, pending_action=False): task = AutomatedTask.objects.get(pk=pk) nats_data = { "func": "delschedtask", "schedtaskpayload": { "name": task.win_task_name }, } r = asyncio.run(task.agent.nats_cmd(nats_data, timeout=10)) if r != "ok" and "The system cannot find the file specified" not in r: # don't create pending action if this task was initiated by a pending action if not pending_action: # complete any other pending actions on agent with same task_id task.agent.remove_matching_pending_task_actions(task.id) PendingAction( agent=task.agent, action_type="taskaction", details={ "action": "taskdelete", "task_id": task.id }, ).save() task.sync_status = "pendingdeletion" task.save(update_fields=["sync_status"]) return "timeout" # complete pending action since it was successful if pending_action: pendingaction = PendingAction.objects.get(pk=pending_action) pendingaction.status = "completed" pendingaction.save(update_fields=["status"]) # complete any other pending actions on agent with same task_id task.agent.remove_matching_pending_task_actions(task.id) task.delete() return "ok"
def enable_or_disable_win_task(pk, action, pending_action=False): task = AutomatedTask.objects.get(pk=pk) nats_data = { "func": "enableschedtask", "schedtaskpayload": { "name": task.win_task_name, "enabled": action, }, } r = asyncio.run(task.agent.nats_cmd(nats_data)) if r != "ok": # don't create pending action if this task was initiated by a pending action if not pending_action: PendingAction( agent=task.agent, action_type="taskaction", details={ "action": "tasktoggle", "value": action, "task_id": task.id, }, ).save() task.sync_status = "notsynced" task.save(update_fields=["sync_status"]) return # clear pending action since it was successful if pending_action: pendingaction = PendingAction.objects.get(pk=pending_action) pendingaction.status = "completed" pendingaction.save(update_fields=["status"]) task.sync_status = "synced" task.save(update_fields=["sync_status"]) return "ok"
def enable_or_disable_win_task(pk, action, pending_action=False): task = AutomatedTask.objects.get(pk=pk) r = task.agent.salt_api_cmd( timeout=20, func="task.edit_task", arg=[f"name={task.win_task_name}", f"enabled={action}"], ) if r == "timeout" or r == "error" or (isinstance(r, bool) and not r): # don't create pending action if this task was initiated by a pending action if not pending_action: PendingAction( agent=task.agent, action_type="taskaction", details={ "action": "tasktoggle", "value": action, "task_id": task.id, }, ).save() task.sync_status = "notsynced" task.save(update_fields=["sync_status"]) logger.error( f"Unable to update the scheduled task {task.win_task_name} on {task.agent.hostname}. It will be updated when the agent checks in." ) return # clear pending action since it was successful if pending_action: pendingaction = PendingAction.objects.get(pk=pending_action) pendingaction.status = "completed" pendingaction.save(update_fields=["status"]) task.sync_status = "synced" task.save(update_fields=["sync_status"]) logger.info(f"{task.agent.hostname} task {task.name} was edited.") return "ok"
def delete_win_task_schedule(pk, pending_action=False): task = AutomatedTask.objects.get(pk=pk) r = task.agent.salt_api_cmd( timeout=20, func="task.delete_task", arg=[f"name={task.win_task_name}"], ) if r == "timeout" or r == "error" or (isinstance(r, bool) and not r): # don't create pending action if this task was initiated by a pending action if not pending_action: PendingAction( agent=task.agent, action_type="taskaction", details={ "action": "taskdelete", "task_id": task.id }, ).save() task.sync_status = "pendingdeletion" task.save(update_fields=["sync_status"]) logger.error( f"Unable to delete scheduled task {task.win_task_name} on {task.agent.hostname}. It was marked pending deletion and will be removed when the agent checks in." ) return # complete pending action since it was successful if pending_action: pendingaction = PendingAction.objects.get(pk=pending_action) pendingaction.status = "completed" pendingaction.save(update_fields=["status"]) task.delete() logger.info(f"{task.agent.hostname} task {task.name} was deleted.") return "ok"
def schedule_reboot(self, obj): start_date = dt.datetime.strftime(obj, "%Y-%m-%d") start_time = dt.datetime.strftime(obj, "%H:%M") # let windows task scheduler automatically delete the task after it runs end_obj = obj + dt.timedelta(minutes=15) end_date = dt.datetime.strftime(end_obj, "%Y-%m-%d") end_time = dt.datetime.strftime(end_obj, "%H:%M") task_name = "TacticalRMM_SchedReboot_" + "".join( random.choice(string.ascii_letters) for _ in range(10) ) try: r = self.salt_api_cmd( hostname=self.salt_id, timeout=20, func="task.create_task", arg=[ f"name={task_name}", "force=True", "action_type=Execute", 'cmd="C:\\Windows\\System32\\shutdown.exe"', 'arguments="/r /t 5 /f"', "trigger_type=Once", f'start_date="{start_date}"', f'start_time="{start_time}"', f'end_date="{end_date}"', f'end_time="{end_time}"', "ac_only=False", "stop_if_on_batteries=False", "delete_after=Immediately", ], ) except Exception: return {"ret": False, "msg": "Unable to contact the agent"} salt_resp = r.json()["return"][0][self.salt_id] if isinstance(salt_resp, bool) and salt_resp == True: from logs.models import PendingAction details = { "taskname": task_name, "time": str(obj), } PendingAction(agent=self, action_type="schedreboot", details=details).save() nice_time = dt.datetime.strftime(obj, "%B %d, %Y at %I:%M %p") return { "ret": True, "msg": {"time": nice_time, "agent": self.hostname}, "success": True, } elif isinstance(salt_resp, bool) and salt_resp == False: return { "ret": True, "msg": "Unable to create task (possibly because date/time cannot be in the past)", "success": False, } else: return {"ret": True, "msg": salt_resp, "success": False}
def create_win_task_schedule(pk, pending_action=False): task = AutomatedTask.objects.get(pk=pk) if task.task_type == "scheduled": nats_data = { "func": "schedtask", "schedtaskpayload": { "type": "rmm", "trigger": "weekly", "weekdays": task.run_time_bit_weekdays, "pk": task.pk, "name": task.win_task_name, "hour": dt.datetime.strptime(task.run_time_minute, "%H:%M").hour, "min": dt.datetime.strptime(task.run_time_minute, "%H:%M").minute, }, } elif task.task_type == "runonce": # check if scheduled time is in the past agent_tz = pytz.timezone(task.agent.timezone) task_time_utc = task.run_time_date.replace(tzinfo=agent_tz).astimezone(pytz.utc) now = djangotime.now() if task_time_utc < now: task.run_time_date = now.astimezone(agent_tz).replace( tzinfo=pytz.utc ) + djangotime.timedelta(minutes=5) task.save(update_fields=["run_time_date"]) nats_data = { "func": "schedtask", "schedtaskpayload": { "type": "rmm", "trigger": "once", "pk": task.pk, "name": task.win_task_name, "year": int(dt.datetime.strftime(task.run_time_date, "%Y")), "month": dt.datetime.strftime(task.run_time_date, "%B"), "day": int(dt.datetime.strftime(task.run_time_date, "%d")), "hour": int(dt.datetime.strftime(task.run_time_date, "%H")), "min": int(dt.datetime.strftime(task.run_time_date, "%M")), }, } if task.run_asap_after_missed and pyver.parse( task.agent.version ) >= pyver.parse("1.4.7"): nats_data["schedtaskpayload"]["run_asap_after_missed"] = True if task.remove_if_not_scheduled: nats_data["schedtaskpayload"]["deleteafter"] = True elif task.task_type == "checkfailure" or task.task_type == "manual": nats_data = { "func": "schedtask", "schedtaskpayload": { "type": "rmm", "trigger": "manual", "pk": task.pk, "name": task.win_task_name, }, } else: return "error" r = asyncio.run(task.agent.nats_cmd(nats_data, timeout=10)) if r != "ok": # don't create pending action if this task was initiated by a pending action if not pending_action: # complete any other pending actions on agent with same task_id task.agent.remove_matching_pending_task_actions(task.id) PendingAction( agent=task.agent, action_type="taskaction", details={"action": "taskcreate", "task_id": task.id}, ).save() task.sync_status = "notsynced" task.save(update_fields=["sync_status"]) logger.error( f"Unable to create scheduled task {task.win_task_name} on {task.agent.hostname}. It will be created when the agent checks in." ) return # clear pending action since it was successful if pending_action: pendingaction = PendingAction.objects.get(pk=pending_action) pendingaction.status = "completed" pendingaction.save(update_fields=["status"]) task.sync_status = "synced" task.save(update_fields=["sync_status"]) logger.info(f"{task.agent.hostname} task {task.name} was successfully created") return "ok"
def create_win_task_schedule(pk, pending_action=False): task = AutomatedTask.objects.get(pk=pk) if task.task_type == "scheduled": run_days = [DAYS_OF_WEEK.get(day) for day in task.run_time_days] r = task.agent.salt_api_cmd( timeout=20, func="task.create_task", arg=[ f"name={task.win_task_name}", "force=True", "action_type=Execute", 'cmd="C:\\Program Files\\TacticalAgent\\tacticalrmm.exe"', f'arguments="-m taskrunner -p {task.pk}"', "start_in=C:\\Program Files\\TacticalAgent", "trigger_type=Weekly", f'start_time="{task.run_time_minute}"', "ac_only=False", "stop_if_on_batteries=False", ], kwargs={"days_of_week": run_days}, ) elif task.task_type == "checkfailure" or task.task_type == "manual": r = task.agent.salt_api_cmd( timeout=20, func="task.create_task", arg=[ f"name={task.win_task_name}", "force=True", "action_type=Execute", 'cmd="C:\\Program Files\\TacticalAgent\\tacticalrmm.exe"', f'arguments="-m taskrunner -p {task.pk}"', "start_in=C:\\Program Files\\TacticalAgent", "trigger_type=Once", "ac_only=False", "stop_if_on_batteries=False", ], ) if r == "timeout" or r == "error" or (isinstance(r, bool) and not r): # don't create pending action if this task was initiated by a pending action if not pending_action: PendingAction( agent=task.agent, action_type="taskaction", details={ "action": "taskcreate", "task_id": task.id }, ).save() task.sync_status = "notsynced" task.save(update_fields=["sync_status"]) logger.error( f"Unable to create scheduled task {task.win_task_name} on {task.agent.hostname}. It will be created when the agent checks in." ) return # clear pending action since it was successful if pending_action: pendingaction = PendingAction.objects.get(pk=pending_action) pendingaction.status = "completed" pendingaction.save(update_fields=["status"]) task.sync_status = "synced" task.save(update_fields=["sync_status"]) logger.info( f"{task.agent.hostname} task {task.name} was successfully created") return "ok"
def cascade_policy_tasks(agent): from autotasks.tasks import delete_win_task_schedule from autotasks.models import AutomatedTask from logs.models import PendingAction # List of all tasks to be applied tasks = list() added_task_pks = list() agent_tasks_parent_pks = [ task.parent_task for task in agent.autotasks.filter(managed_by_policy=True) ] # Get policies applied to agent and agent site and client client = agent.client site = agent.site default_policy = None client_policy = None site_policy = None agent_policy = agent.policy # Get the Client/Site policy based on if the agent is server or workstation if agent.monitoring_type == "server": default_policy = CoreSettings.objects.first().server_policy client_policy = client.server_policy site_policy = site.server_policy elif agent.monitoring_type == "workstation": default_policy = CoreSettings.objects.first().workstation_policy client_policy = client.workstation_policy site_policy = site.workstation_policy if agent_policy and agent_policy.active: for task in agent_policy.autotasks.all(): if task.pk not in added_task_pks: tasks.append(task) added_task_pks.append(task.pk) if site_policy and site_policy.active: for task in site_policy.autotasks.all(): if task.pk not in added_task_pks: tasks.append(task) added_task_pks.append(task.pk) if client_policy and client_policy.active: for task in client_policy.autotasks.all(): if task.pk not in added_task_pks: tasks.append(task) added_task_pks.append(task.pk) if default_policy and default_policy.active: for task in default_policy.autotasks.all(): if task.pk not in added_task_pks: tasks.append(task) added_task_pks.append(task.pk) # remove policy tasks from agent not included in policy for task in agent.autotasks.filter(parent_task__in=[ taskpk for taskpk in agent_tasks_parent_pks if taskpk not in added_task_pks ]): delete_win_task_schedule.delay(task.pk) # handle matching tasks that haven't synced to agent yet or pending deletion due to agent being offline for action in agent.pendingactions.exclude(status="completed"): task = AutomatedTask.objects.get(pk=action.details["task_id"]) if (task.parent_task in agent_tasks_parent_pks and task.parent_task in added_task_pks): agent.remove_matching_pending_task_actions(task.id) PendingAction( agent=agent, action_type="taskaction", details={ "action": "taskcreate", "task_id": task.id }, ).save() task.sync_status = "notsynced" task.save(update_fields=["sync_status"]) return [ task for task in tasks if task.pk not in agent_tasks_parent_pks ]