예제 #1
0
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"
예제 #2
0
    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"
예제 #3
0
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"
예제 #4
0
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"
예제 #5
0
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"
예제 #6
0
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"
예제 #7
0
    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}
예제 #8
0
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"
예제 #9
0
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"
예제 #10
0
    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
        ]