Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
715982e40a | ||
|
|
d00cd4453a | ||
|
|
429c08c24a | ||
|
|
6a71490e20 | ||
|
|
9bceda0646 | ||
|
|
a1027a6773 | ||
|
|
302d4b75f9 | ||
|
|
5f6ee0e883 | ||
|
|
27f9720de1 | ||
|
|
22aa3fdbbc | ||
|
|
069ecdd33f | ||
|
|
dd545ae933 | ||
|
|
6650b705c4 | ||
|
|
59b0350289 | ||
|
|
1ad159f820 | ||
|
|
0bf42190e9 | ||
|
|
d2fa836232 | ||
|
|
c387774093 | ||
|
|
e99736ba3c | ||
|
|
16cb54fcc9 | ||
|
|
5aa15c51ec | ||
|
|
a8aedd9cf3 | ||
|
|
b851b632bc | ||
|
|
541e07fb65 | ||
|
|
6ad16a897d | ||
|
|
72f1053a93 | ||
|
|
fb15a2762c | ||
|
|
9165248b91 | ||
|
|
add18b29db | ||
|
|
1971653548 | ||
|
|
392cd64d7b | ||
|
|
b5affbb7c8 | ||
|
|
71d1206277 | ||
|
|
26e6a8c409 | ||
|
|
eb54fae11a | ||
|
|
ee773e5966 | ||
|
|
7218ccdba8 | ||
|
|
332400e48a | ||
|
|
ad1a5d3702 | ||
|
|
3006b4184d | ||
|
|
84eb84a080 | ||
|
|
60beea548b | ||
|
|
5f9c149e59 | ||
|
|
53367c6f04 | ||
|
|
d7f817ee44 | ||
|
|
d33a87da54 | ||
|
|
3aebfb12b7 | ||
|
|
1d6c55ffa6 | ||
|
|
5e7080aac3 | ||
|
|
fad739bc01 | ||
|
|
c6b7f23884 | ||
|
|
a6f7e446de |
@@ -115,7 +115,10 @@ services:
|
|||||||
redis-dev:
|
redis-dev:
|
||||||
container_name: trmm-redis-dev
|
container_name: trmm-redis-dev
|
||||||
restart: always
|
restart: always
|
||||||
|
command: redis-server --appendonly yes
|
||||||
image: redis:6.0-alpine
|
image: redis:6.0-alpine
|
||||||
|
volumes:
|
||||||
|
- redis-data-dev:/data
|
||||||
networks:
|
networks:
|
||||||
dev:
|
dev:
|
||||||
aliases:
|
aliases:
|
||||||
@@ -247,6 +250,7 @@ volumes:
|
|||||||
postgres-data-dev:
|
postgres-data-dev:
|
||||||
mongo-dev-data:
|
mongo-dev-data:
|
||||||
mesh-data-dev:
|
mesh-data-dev:
|
||||||
|
redis-data-dev:
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
dev:
|
dev:
|
||||||
|
|||||||
@@ -211,6 +211,7 @@ def agent_outages_task() -> None:
|
|||||||
|
|
||||||
agents = Agent.objects.only(
|
agents = Agent.objects.only(
|
||||||
"pk",
|
"pk",
|
||||||
|
"agent_id",
|
||||||
"last_seen",
|
"last_seen",
|
||||||
"offline_time",
|
"offline_time",
|
||||||
"overdue_time",
|
"overdue_time",
|
||||||
|
|||||||
@@ -321,11 +321,16 @@ class CheckRunner(APIView):
|
|||||||
|
|
||||||
def patch(self, request):
|
def patch(self, request):
|
||||||
check = get_object_or_404(Check, pk=request.data["id"])
|
check = get_object_or_404(Check, pk=request.data["id"])
|
||||||
|
if pyver.parse(check.agent.version) < pyver.parse("1.5.7"):
|
||||||
|
return notify_error("unsupported")
|
||||||
|
|
||||||
check.last_run = djangotime.now()
|
check.last_run = djangotime.now()
|
||||||
check.save(update_fields=["last_run"])
|
check.save(update_fields=["last_run"])
|
||||||
status = check.handle_checkv2(request.data)
|
status = check.handle_check(request.data)
|
||||||
|
if status == "failing" and check.assignedtask.exists(): # type: ignore
|
||||||
|
check.handle_assigned_task()
|
||||||
|
|
||||||
return Response(status)
|
return Response("ok")
|
||||||
|
|
||||||
|
|
||||||
class CheckRunnerInterval(APIView):
|
class CheckRunnerInterval(APIView):
|
||||||
@@ -378,9 +383,18 @@ class TaskRunner(APIView):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# get last line of stdout
|
# get last line of stdout
|
||||||
value = new_task.stdout.split("\n")[-1].strip()
|
value = (
|
||||||
|
new_task.stdout
|
||||||
|
if task.collector_all_output
|
||||||
|
else new_task.stdout.split("\n")[-1].strip()
|
||||||
|
)
|
||||||
|
|
||||||
if task.custom_field.type in ["text", "number", "single", "datetime"]:
|
if task.custom_field.type in [
|
||||||
|
"text",
|
||||||
|
"number",
|
||||||
|
"single",
|
||||||
|
"datetime",
|
||||||
|
]:
|
||||||
agent_field.string_value = value
|
agent_field.string_value = value
|
||||||
agent_field.save()
|
agent_field.save()
|
||||||
elif task.custom_field.type == "multiple":
|
elif task.custom_field.type == "multiple":
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from typing import Any, Dict, List, Union
|
|||||||
from tacticalrmm.celery import app
|
from tacticalrmm.celery import app
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@app.task(retry_backoff=5, retry_jitter=True, retry_kwargs={"max_retries": 5})
|
||||||
def generate_agent_checks_task(
|
def generate_agent_checks_task(
|
||||||
policy: int = None,
|
policy: int = None,
|
||||||
site: int = None,
|
site: int = None,
|
||||||
@@ -57,7 +57,9 @@ def generate_agent_checks_task(
|
|||||||
return "ok"
|
return "ok"
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@app.task(
|
||||||
|
acks_late=True, retry_backoff=5, retry_jitter=True, retry_kwargs={"max_retries": 5}
|
||||||
|
)
|
||||||
# updates policy managed check fields on agents
|
# updates policy managed check fields on agents
|
||||||
def update_policy_check_fields_task(check: int) -> str:
|
def update_policy_check_fields_task(check: int) -> str:
|
||||||
from checks.models import Check
|
from checks.models import Check
|
||||||
@@ -73,7 +75,7 @@ def update_policy_check_fields_task(check: int) -> str:
|
|||||||
return "ok"
|
return "ok"
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@app.task(retry_backoff=5, retry_jitter=True, retry_kwargs={"max_retries": 5})
|
||||||
# generates policy tasks on agents affected by a policy
|
# generates policy tasks on agents affected by a policy
|
||||||
def generate_agent_autotasks_task(policy: int = None) -> str:
|
def generate_agent_autotasks_task(policy: int = None) -> str:
|
||||||
from agents.models import Agent
|
from agents.models import Agent
|
||||||
@@ -100,7 +102,12 @@ def generate_agent_autotasks_task(policy: int = None) -> str:
|
|||||||
return "ok"
|
return "ok"
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@app.task(
|
||||||
|
acks_late=True,
|
||||||
|
retry_backoff=5,
|
||||||
|
retry_jitter=True,
|
||||||
|
retry_kwargs={"max_retries": 5},
|
||||||
|
)
|
||||||
def delete_policy_autotasks_task(task: int) -> str:
|
def delete_policy_autotasks_task(task: int) -> str:
|
||||||
from autotasks.models import AutomatedTask
|
from autotasks.models import AutomatedTask
|
||||||
|
|
||||||
@@ -120,7 +127,12 @@ def run_win_policy_autotasks_task(task: int) -> str:
|
|||||||
return "ok"
|
return "ok"
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@app.task(
|
||||||
|
acks_late=True,
|
||||||
|
retry_backoff=5,
|
||||||
|
retry_jitter=True,
|
||||||
|
retry_kwargs={"max_retries": 5},
|
||||||
|
)
|
||||||
def update_policy_autotasks_fields_task(task: int, update_agent: bool = False) -> str:
|
def update_policy_autotasks_fields_task(task: int, update_agent: bool = False) -> str:
|
||||||
from autotasks.models import AutomatedTask
|
from autotasks.models import AutomatedTask
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 3.2.1 on 2021-05-29 03:26
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('autotasks', '0021_alter_automatedtask_custom_field'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='automatedtask',
|
||||||
|
name='collector_all_output',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -10,6 +10,7 @@ from django.conf import settings
|
|||||||
from django.contrib.postgres.fields import ArrayField
|
from django.contrib.postgres.fields import ArrayField
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.fields import DateTimeField
|
from django.db.models.fields import DateTimeField
|
||||||
|
from django.db.utils import DatabaseError
|
||||||
from django.utils import timezone as djangotime
|
from django.utils import timezone as djangotime
|
||||||
from logs.models import BaseAuditModel
|
from logs.models import BaseAuditModel
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
@@ -104,6 +105,7 @@ class AutomatedTask(BaseAuditModel):
|
|||||||
task_type = models.CharField(
|
task_type = models.CharField(
|
||||||
max_length=100, choices=TASK_TYPE_CHOICES, default="manual"
|
max_length=100, choices=TASK_TYPE_CHOICES, default="manual"
|
||||||
)
|
)
|
||||||
|
collector_all_output = models.BooleanField(default=False)
|
||||||
run_time_date = DateTimeField(null=True, blank=True)
|
run_time_date = DateTimeField(null=True, blank=True)
|
||||||
remove_if_not_scheduled = models.BooleanField(default=False)
|
remove_if_not_scheduled = models.BooleanField(default=False)
|
||||||
run_asap_after_missed = models.BooleanField(default=False) # added in agent v1.4.7
|
run_asap_after_missed = models.BooleanField(default=False) # added in agent v1.4.7
|
||||||
@@ -182,6 +184,7 @@ class AutomatedTask(BaseAuditModel):
|
|||||||
"remove_if_not_scheduled",
|
"remove_if_not_scheduled",
|
||||||
"run_asap_after_missed",
|
"run_asap_after_missed",
|
||||||
"custom_field",
|
"custom_field",
|
||||||
|
"collector_all_output",
|
||||||
]
|
]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -363,9 +366,14 @@ class AutomatedTask(BaseAuditModel):
|
|||||||
|
|
||||||
if r != "ok" and "The system cannot find the file specified" not in r:
|
if r != "ok" and "The system cannot find the file specified" not in r:
|
||||||
self.sync_status = "pendingdeletion"
|
self.sync_status = "pendingdeletion"
|
||||||
self.save(update_fields=["sync_status"])
|
|
||||||
|
try:
|
||||||
|
self.save(update_fields=["sync_status"])
|
||||||
|
except DatabaseError:
|
||||||
|
pass
|
||||||
|
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"{agent.hostname} task {self.name} was successfully modified"
|
f"{agent.hostname} task {self.name} will be deleted on next checkin"
|
||||||
)
|
)
|
||||||
return "timeout"
|
return "timeout"
|
||||||
else:
|
else:
|
||||||
|
|||||||
22
api/tacticalrmm/checks/migrations/0024_auto_20210606_1632.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Generated by Django 3.2.1 on 2021-06-06 16:32
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('checks', '0023_check_run_interval'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='checkhistory',
|
||||||
|
name='check_history',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='checkhistory',
|
||||||
|
name='check_id',
|
||||||
|
field=models.PositiveIntegerField(default=0),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import asyncio
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import string
|
import string
|
||||||
@@ -14,9 +13,7 @@ from django.core.validators import MaxValueValidator, MinValueValidator
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from logs.models import BaseAuditModel
|
from logs.models import BaseAuditModel
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from packaging import version as pyver
|
|
||||||
|
|
||||||
from .utils import bytes2human
|
|
||||||
|
|
||||||
logger.configure(**settings.LOG_CONFIG)
|
logger.configure(**settings.LOG_CONFIG)
|
||||||
|
|
||||||
@@ -316,9 +313,9 @@ class Check(BaseAuditModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def add_check_history(self, value: int, more_info: Any = None) -> None:
|
def add_check_history(self, value: int, more_info: Any = None) -> None:
|
||||||
CheckHistory.objects.create(check_history=self, y=value, results=more_info)
|
CheckHistory.objects.create(check_id=self.pk, y=value, results=more_info)
|
||||||
|
|
||||||
def handle_checkv2(self, data):
|
def handle_check(self, data):
|
||||||
from alerts.models import Alert
|
from alerts.models import Alert
|
||||||
|
|
||||||
# cpuload or mem checks
|
# cpuload or mem checks
|
||||||
@@ -349,9 +346,6 @@ class Check(BaseAuditModel):
|
|||||||
elif self.check_type == "diskspace":
|
elif self.check_type == "diskspace":
|
||||||
if data["exists"]:
|
if data["exists"]:
|
||||||
percent_used = round(data["percent_used"])
|
percent_used = round(data["percent_used"])
|
||||||
total = bytes2human(data["total"])
|
|
||||||
free = bytes2human(data["free"])
|
|
||||||
|
|
||||||
if self.error_threshold and (100 - percent_used) < self.error_threshold:
|
if self.error_threshold and (100 - percent_used) < self.error_threshold:
|
||||||
self.status = "failing"
|
self.status = "failing"
|
||||||
self.alert_severity = "error"
|
self.alert_severity = "error"
|
||||||
@@ -365,7 +359,7 @@ class Check(BaseAuditModel):
|
|||||||
else:
|
else:
|
||||||
self.status = "passing"
|
self.status = "passing"
|
||||||
|
|
||||||
self.more_info = f"Total: {total}B, Free: {free}B"
|
self.more_info = data["more_info"]
|
||||||
|
|
||||||
# add check history
|
# add check history
|
||||||
self.add_check_history(100 - percent_used)
|
self.add_check_history(100 - percent_used)
|
||||||
@@ -381,12 +375,7 @@ class Check(BaseAuditModel):
|
|||||||
self.stdout = data["stdout"]
|
self.stdout = data["stdout"]
|
||||||
self.stderr = data["stderr"]
|
self.stderr = data["stderr"]
|
||||||
self.retcode = data["retcode"]
|
self.retcode = data["retcode"]
|
||||||
try:
|
self.execution_time = "{:.4f}".format(data["runtime"])
|
||||||
# python agent
|
|
||||||
self.execution_time = "{:.4f}".format(data["stop"] - data["start"])
|
|
||||||
except:
|
|
||||||
# golang agent
|
|
||||||
self.execution_time = "{:.4f}".format(data["runtime"])
|
|
||||||
|
|
||||||
if data["retcode"] in self.info_return_codes:
|
if data["retcode"] in self.info_return_codes:
|
||||||
self.alert_severity = "info"
|
self.alert_severity = "info"
|
||||||
@@ -422,22 +411,8 @@ class Check(BaseAuditModel):
|
|||||||
|
|
||||||
# ping checks
|
# ping checks
|
||||||
elif self.check_type == "ping":
|
elif self.check_type == "ping":
|
||||||
output = data["output"]
|
self.status = data["status"]
|
||||||
|
self.more_info = data["output"]
|
||||||
if pyver.parse(self.agent.version) <= pyver.parse("1.5.2"):
|
|
||||||
# DEPRECATED
|
|
||||||
success = ["Reply", "bytes", "time", "TTL"]
|
|
||||||
if data["has_stdout"]:
|
|
||||||
if all(x in output for x in success):
|
|
||||||
self.status = "passing"
|
|
||||||
else:
|
|
||||||
self.status = "failing"
|
|
||||||
elif data["has_stderr"]:
|
|
||||||
self.status = "failing"
|
|
||||||
else:
|
|
||||||
self.status = data["status"]
|
|
||||||
|
|
||||||
self.more_info = output
|
|
||||||
self.save(update_fields=["more_info"])
|
self.save(update_fields=["more_info"])
|
||||||
|
|
||||||
self.add_check_history(
|
self.add_check_history(
|
||||||
@@ -446,41 +421,8 @@ class Check(BaseAuditModel):
|
|||||||
|
|
||||||
# windows service checks
|
# windows service checks
|
||||||
elif self.check_type == "winsvc":
|
elif self.check_type == "winsvc":
|
||||||
svc_stat = data["status"]
|
self.status = data["status"]
|
||||||
self.more_info = f"Status {svc_stat.upper()}"
|
self.more_info = data["more_info"]
|
||||||
|
|
||||||
if data["exists"]:
|
|
||||||
if svc_stat == "running":
|
|
||||||
self.status = "passing"
|
|
||||||
elif svc_stat == "start_pending" and self.pass_if_start_pending:
|
|
||||||
self.status = "passing"
|
|
||||||
else:
|
|
||||||
if self.agent and self.restart_if_stopped:
|
|
||||||
nats_data = {
|
|
||||||
"func": "winsvcaction",
|
|
||||||
"payload": {"name": self.svc_name, "action": "start"},
|
|
||||||
}
|
|
||||||
r = asyncio.run(self.agent.nats_cmd(nats_data, timeout=32))
|
|
||||||
if r == "timeout" or r == "natsdown":
|
|
||||||
self.status = "failing"
|
|
||||||
elif not r["success"] and r["errormsg"]:
|
|
||||||
self.status = "failing"
|
|
||||||
elif r["success"]:
|
|
||||||
self.status = "passing"
|
|
||||||
self.more_info = f"Status RUNNING"
|
|
||||||
else:
|
|
||||||
self.status = "failing"
|
|
||||||
else:
|
|
||||||
self.status = "failing"
|
|
||||||
|
|
||||||
else:
|
|
||||||
if self.pass_if_svc_not_exist:
|
|
||||||
self.status = "passing"
|
|
||||||
else:
|
|
||||||
self.status = "failing"
|
|
||||||
|
|
||||||
self.more_info = f"Service {self.svc_name} does not exist"
|
|
||||||
|
|
||||||
self.save(update_fields=["more_info"])
|
self.save(update_fields=["more_info"])
|
||||||
|
|
||||||
self.add_check_history(
|
self.add_check_history(
|
||||||
@@ -488,49 +430,7 @@ class Check(BaseAuditModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
elif self.check_type == "eventlog":
|
elif self.check_type == "eventlog":
|
||||||
log = []
|
log = data["log"]
|
||||||
is_wildcard = self.event_id_is_wildcard
|
|
||||||
eventType = self.event_type
|
|
||||||
eventID = self.event_id
|
|
||||||
source = self.event_source
|
|
||||||
message = self.event_message
|
|
||||||
r = data["log"]
|
|
||||||
|
|
||||||
for i in r:
|
|
||||||
if i["eventType"] == eventType:
|
|
||||||
if not is_wildcard and not int(i["eventID"]) == eventID:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if not source and not message:
|
|
||||||
if is_wildcard:
|
|
||||||
log.append(i)
|
|
||||||
elif int(i["eventID"]) == eventID:
|
|
||||||
log.append(i)
|
|
||||||
continue
|
|
||||||
|
|
||||||
if source and message:
|
|
||||||
if is_wildcard:
|
|
||||||
if source in i["source"] and message in i["message"]:
|
|
||||||
log.append(i)
|
|
||||||
|
|
||||||
elif int(i["eventID"]) == eventID:
|
|
||||||
if source in i["source"] and message in i["message"]:
|
|
||||||
log.append(i)
|
|
||||||
|
|
||||||
continue
|
|
||||||
|
|
||||||
if source and source in i["source"]:
|
|
||||||
if is_wildcard:
|
|
||||||
log.append(i)
|
|
||||||
elif int(i["eventID"]) == eventID:
|
|
||||||
log.append(i)
|
|
||||||
|
|
||||||
if message and message in i["message"]:
|
|
||||||
if is_wildcard:
|
|
||||||
log.append(i)
|
|
||||||
elif int(i["eventID"]) == eventID:
|
|
||||||
log.append(i)
|
|
||||||
|
|
||||||
if self.fail_when == "contains":
|
if self.fail_when == "contains":
|
||||||
if log and len(log) >= self.number_of_events_b4_alert:
|
if log and len(log) >= self.number_of_events_b4_alert:
|
||||||
self.status = "failing"
|
self.status = "failing"
|
||||||
@@ -567,6 +467,11 @@ class Check(BaseAuditModel):
|
|||||||
|
|
||||||
return self.status
|
return self.status
|
||||||
|
|
||||||
|
def handle_assigned_task(self) -> None:
|
||||||
|
for task in self.assignedtask.all(): # type: ignore
|
||||||
|
if task.enabled:
|
||||||
|
task.run_win_task()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def serialize(check):
|
def serialize(check):
|
||||||
# serializes the check and returns json
|
# serializes the check and returns json
|
||||||
@@ -604,7 +509,12 @@ class Check(BaseAuditModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
for task in self.assignedtask.all(): # type: ignore
|
for task in self.assignedtask.all(): # type: ignore
|
||||||
task.create_policy_task(agent=agent, policy=policy, assigned_check=check)
|
if policy or (
|
||||||
|
agent and not agent.autotasks.filter(parent_task=task.pk).exists()
|
||||||
|
):
|
||||||
|
task.create_policy_task(
|
||||||
|
agent=agent, policy=policy, assigned_check=check
|
||||||
|
)
|
||||||
|
|
||||||
for field in self.policy_fields_to_copy:
|
for field in self.policy_fields_to_copy:
|
||||||
setattr(check, field, getattr(self, field))
|
setattr(check, field, getattr(self, field))
|
||||||
@@ -778,14 +688,10 @@ class Check(BaseAuditModel):
|
|||||||
|
|
||||||
|
|
||||||
class CheckHistory(models.Model):
|
class CheckHistory(models.Model):
|
||||||
check_history = models.ForeignKey(
|
check_id = models.PositiveIntegerField(default=0)
|
||||||
Check,
|
|
||||||
related_name="check_history",
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
)
|
|
||||||
x = models.DateTimeField(auto_now_add=True)
|
x = models.DateTimeField(auto_now_add=True)
|
||||||
y = models.PositiveIntegerField(null=True, blank=True, default=None)
|
y = models.PositiveIntegerField(null=True, blank=True, default=None)
|
||||||
results = models.JSONField(null=True, blank=True)
|
results = models.JSONField(null=True, blank=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.check_history.readable_desc
|
return self.x
|
||||||
|
|||||||
@@ -158,14 +158,8 @@ class AssignedTaskCheckRunnerField(serializers.ModelSerializer):
|
|||||||
|
|
||||||
class CheckRunnerGetSerializer(serializers.ModelSerializer):
|
class CheckRunnerGetSerializer(serializers.ModelSerializer):
|
||||||
# only send data needed for agent to run a check
|
# only send data needed for agent to run a check
|
||||||
assigned_tasks = serializers.SerializerMethodField()
|
|
||||||
script = ScriptCheckSerializer(read_only=True)
|
script = ScriptCheckSerializer(read_only=True)
|
||||||
|
|
||||||
def get_assigned_tasks(self, obj):
|
|
||||||
if obj.assignedtask.exists():
|
|
||||||
tasks = obj.assignedtask.all()
|
|
||||||
return AssignedTaskCheckRunnerField(tasks, many=True).data
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Check
|
model = Check
|
||||||
exclude = [
|
exclude = [
|
||||||
@@ -193,6 +187,7 @@ class CheckRunnerGetSerializer(serializers.ModelSerializer):
|
|||||||
"modified_by",
|
"modified_by",
|
||||||
"modified_time",
|
"modified_time",
|
||||||
"history",
|
"history",
|
||||||
|
"dashboard_alert",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -363,10 +363,10 @@ class TestCheckViews(TacticalTestCase):
|
|||||||
# setup data
|
# setup data
|
||||||
agent = baker.make_recipe("agents.agent")
|
agent = baker.make_recipe("agents.agent")
|
||||||
check = baker.make_recipe("checks.diskspace_check", agent=agent)
|
check = baker.make_recipe("checks.diskspace_check", agent=agent)
|
||||||
baker.make("checks.CheckHistory", check_history=check, _quantity=30)
|
baker.make("checks.CheckHistory", check_id=check.id, _quantity=30)
|
||||||
check_history_data = baker.make(
|
check_history_data = baker.make(
|
||||||
"checks.CheckHistory",
|
"checks.CheckHistory",
|
||||||
check_history=check,
|
check_id=check.id,
|
||||||
_quantity=30,
|
_quantity=30,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -400,17 +400,17 @@ class TestCheckTasks(TacticalTestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.authenticate()
|
self.authenticate()
|
||||||
self.setup_coresettings()
|
self.setup_coresettings()
|
||||||
self.agent = baker.make_recipe("agents.agent")
|
self.agent = baker.make_recipe("agents.agent", version="1.5.7")
|
||||||
|
|
||||||
def test_prune_check_history(self):
|
def test_prune_check_history(self):
|
||||||
from .tasks import prune_check_history
|
from .tasks import prune_check_history
|
||||||
|
|
||||||
# setup data
|
# setup data
|
||||||
check = baker.make_recipe("checks.diskspace_check")
|
check = baker.make_recipe("checks.diskspace_check")
|
||||||
baker.make("checks.CheckHistory", check_history=check, _quantity=30)
|
baker.make("checks.CheckHistory", check_id=check.id, _quantity=30)
|
||||||
check_history_data = baker.make(
|
check_history_data = baker.make(
|
||||||
"checks.CheckHistory",
|
"checks.CheckHistory",
|
||||||
check_history=check,
|
check_id=check.id,
|
||||||
_quantity=30,
|
_quantity=30,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -526,6 +526,7 @@ class TestCheckTasks(TacticalTestCase):
|
|||||||
"percent_used": 85,
|
"percent_used": 85,
|
||||||
"total": 500,
|
"total": 500,
|
||||||
"free": 400,
|
"free": 400,
|
||||||
|
"more_info": "More info",
|
||||||
}
|
}
|
||||||
|
|
||||||
resp = self.client.patch(url, data, format="json")
|
resp = self.client.patch(url, data, format="json")
|
||||||
@@ -543,6 +544,7 @@ class TestCheckTasks(TacticalTestCase):
|
|||||||
"percent_used": 95,
|
"percent_used": 95,
|
||||||
"total": 500,
|
"total": 500,
|
||||||
"free": 400,
|
"free": 400,
|
||||||
|
"more_info": "More info",
|
||||||
}
|
}
|
||||||
|
|
||||||
resp = self.client.patch(url, data, format="json")
|
resp = self.client.patch(url, data, format="json")
|
||||||
@@ -573,6 +575,7 @@ class TestCheckTasks(TacticalTestCase):
|
|||||||
"percent_used": 95,
|
"percent_used": 95,
|
||||||
"total": 500,
|
"total": 500,
|
||||||
"free": 400,
|
"free": 400,
|
||||||
|
"more_info": "More info",
|
||||||
}
|
}
|
||||||
|
|
||||||
resp = self.client.patch(url, data, format="json")
|
resp = self.client.patch(url, data, format="json")
|
||||||
@@ -592,6 +595,7 @@ class TestCheckTasks(TacticalTestCase):
|
|||||||
"percent_used": 95,
|
"percent_used": 95,
|
||||||
"total": 500,
|
"total": 500,
|
||||||
"free": 400,
|
"free": 400,
|
||||||
|
"more_info": "More info",
|
||||||
}
|
}
|
||||||
|
|
||||||
resp = self.client.patch(url, data, format="json")
|
resp = self.client.patch(url, data, format="json")
|
||||||
@@ -608,6 +612,7 @@ class TestCheckTasks(TacticalTestCase):
|
|||||||
"percent_used": 50,
|
"percent_used": 50,
|
||||||
"total": 500,
|
"total": 500,
|
||||||
"free": 400,
|
"free": 400,
|
||||||
|
"more_info": "More info",
|
||||||
}
|
}
|
||||||
|
|
||||||
resp = self.client.patch(url, data, format="json")
|
resp = self.client.patch(url, data, format="json")
|
||||||
@@ -791,12 +796,7 @@ class TestCheckTasks(TacticalTestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# test failing info
|
# test failing info
|
||||||
data = {
|
data = {"id": ping.id, "status": "failing", "output": "reply from a.com"}
|
||||||
"id": ping.id,
|
|
||||||
"output": "Reply from 192.168.1.27: Destination host unreachable",
|
|
||||||
"has_stdout": True,
|
|
||||||
"has_stderr": False,
|
|
||||||
}
|
|
||||||
|
|
||||||
resp = self.client.patch(url, data, format="json")
|
resp = self.client.patch(url, data, format="json")
|
||||||
self.assertEqual(resp.status_code, 200)
|
self.assertEqual(resp.status_code, 200)
|
||||||
@@ -806,13 +806,6 @@ class TestCheckTasks(TacticalTestCase):
|
|||||||
self.assertEqual(new_check.alert_severity, "info")
|
self.assertEqual(new_check.alert_severity, "info")
|
||||||
|
|
||||||
# test failing warning
|
# test failing warning
|
||||||
data = {
|
|
||||||
"id": ping.id,
|
|
||||||
"output": "Reply from 192.168.1.27: Destination host unreachable",
|
|
||||||
"has_stdout": True,
|
|
||||||
"has_stderr": False,
|
|
||||||
}
|
|
||||||
|
|
||||||
ping.alert_severity = "warning"
|
ping.alert_severity = "warning"
|
||||||
ping.save()
|
ping.save()
|
||||||
|
|
||||||
@@ -824,13 +817,6 @@ class TestCheckTasks(TacticalTestCase):
|
|||||||
self.assertEqual(new_check.alert_severity, "warning")
|
self.assertEqual(new_check.alert_severity, "warning")
|
||||||
|
|
||||||
# test failing error
|
# test failing error
|
||||||
data = {
|
|
||||||
"id": ping.id,
|
|
||||||
"output": "Reply from 192.168.1.27: Destination host unreachable",
|
|
||||||
"has_stdout": True,
|
|
||||||
"has_stderr": False,
|
|
||||||
}
|
|
||||||
|
|
||||||
ping.alert_severity = "error"
|
ping.alert_severity = "error"
|
||||||
ping.save()
|
ping.save()
|
||||||
|
|
||||||
@@ -842,13 +828,6 @@ class TestCheckTasks(TacticalTestCase):
|
|||||||
self.assertEqual(new_check.alert_severity, "error")
|
self.assertEqual(new_check.alert_severity, "error")
|
||||||
|
|
||||||
# test failing error
|
# test failing error
|
||||||
data = {
|
|
||||||
"id": ping.id,
|
|
||||||
"output": "some output",
|
|
||||||
"has_stdout": False,
|
|
||||||
"has_stderr": True,
|
|
||||||
}
|
|
||||||
|
|
||||||
resp = self.client.patch(url, data, format="json")
|
resp = self.client.patch(url, data, format="json")
|
||||||
self.assertEqual(resp.status_code, 200)
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
|
||||||
@@ -857,12 +836,7 @@ class TestCheckTasks(TacticalTestCase):
|
|||||||
self.assertEqual(new_check.alert_severity, "error")
|
self.assertEqual(new_check.alert_severity, "error")
|
||||||
|
|
||||||
# test passing
|
# test passing
|
||||||
data = {
|
data = {"id": ping.id, "status": "passing", "output": "reply from a.com"}
|
||||||
"id": ping.id,
|
|
||||||
"output": "Reply from 192.168.1.1: bytes=32 time<1ms TTL=64",
|
|
||||||
"has_stdout": True,
|
|
||||||
"has_stderr": False,
|
|
||||||
}
|
|
||||||
|
|
||||||
resp = self.client.patch(url, data, format="json")
|
resp = self.client.patch(url, data, format="json")
|
||||||
self.assertEqual(resp.status_code, 200)
|
self.assertEqual(resp.status_code, 200)
|
||||||
@@ -881,7 +855,7 @@ class TestCheckTasks(TacticalTestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# test passing running
|
# test passing running
|
||||||
data = {"id": winsvc.id, "exists": True, "status": "running"}
|
data = {"id": winsvc.id, "status": "passing", "more_info": "ok"}
|
||||||
|
|
||||||
resp = self.client.patch(url, data, format="json")
|
resp = self.client.patch(url, data, format="json")
|
||||||
self.assertEqual(resp.status_code, 200)
|
self.assertEqual(resp.status_code, 200)
|
||||||
@@ -889,20 +863,8 @@ class TestCheckTasks(TacticalTestCase):
|
|||||||
new_check = Check.objects.get(pk=winsvc.id)
|
new_check = Check.objects.get(pk=winsvc.id)
|
||||||
self.assertEqual(new_check.status, "passing")
|
self.assertEqual(new_check.status, "passing")
|
||||||
|
|
||||||
# test passing start pending
|
# test failing
|
||||||
winsvc.pass_if_start_pending = True
|
data = {"id": winsvc.id, "status": "failing", "more_info": "ok"}
|
||||||
winsvc.save()
|
|
||||||
|
|
||||||
data = {"id": winsvc.id, "exists": True, "status": "start_pending"}
|
|
||||||
|
|
||||||
resp = self.client.patch(url, data, format="json")
|
|
||||||
self.assertEqual(resp.status_code, 200)
|
|
||||||
|
|
||||||
new_check = Check.objects.get(pk=winsvc.id)
|
|
||||||
self.assertEqual(new_check.status, "passing")
|
|
||||||
|
|
||||||
# test failing no start
|
|
||||||
data = {"id": winsvc.id, "exists": True, "status": "not running"}
|
|
||||||
|
|
||||||
resp = self.client.patch(url, data, format="json")
|
resp = self.client.patch(url, data, format="json")
|
||||||
self.assertEqual(resp.status_code, 200)
|
self.assertEqual(resp.status_code, 200)
|
||||||
@@ -911,7 +873,7 @@ class TestCheckTasks(TacticalTestCase):
|
|||||||
self.assertEqual(new_check.status, "failing")
|
self.assertEqual(new_check.status, "failing")
|
||||||
self.assertEqual(new_check.alert_severity, "info")
|
self.assertEqual(new_check.alert_severity, "info")
|
||||||
|
|
||||||
# test failing and attempt start
|
""" # test failing and attempt start
|
||||||
winsvc.restart_if_stopped = True
|
winsvc.restart_if_stopped = True
|
||||||
winsvc.alert_severity = "warning"
|
winsvc.alert_severity = "warning"
|
||||||
winsvc.save()
|
winsvc.save()
|
||||||
@@ -976,9 +938,9 @@ class TestCheckTasks(TacticalTestCase):
|
|||||||
self.assertEqual(resp.status_code, 200)
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
|
||||||
new_check = Check.objects.get(pk=winsvc.id)
|
new_check = Check.objects.get(pk=winsvc.id)
|
||||||
self.assertEqual(new_check.status, "passing")
|
self.assertEqual(new_check.status, "passing") """
|
||||||
|
|
||||||
def test_handle_eventlog_check(self):
|
""" def test_handle_eventlog_check(self):
|
||||||
from checks.models import Check
|
from checks.models import Check
|
||||||
|
|
||||||
url = "/api/v3/checkrunner/"
|
url = "/api/v3/checkrunner/"
|
||||||
@@ -1180,4 +1142,4 @@ class TestCheckTasks(TacticalTestCase):
|
|||||||
|
|
||||||
new_check = Check.objects.get(pk=eventlog.id)
|
new_check = Check.objects.get(pk=eventlog.id)
|
||||||
|
|
||||||
self.assertEquals(new_check.status, "passing")
|
self.assertEquals(new_check.status, "passing") """
|
||||||
|
|||||||
@@ -8,5 +8,5 @@ urlpatterns = [
|
|||||||
path("<pk>/loadchecks/", views.load_checks),
|
path("<pk>/loadchecks/", views.load_checks),
|
||||||
path("getalldisks/", views.get_disks_for_policies),
|
path("getalldisks/", views.get_disks_for_policies),
|
||||||
path("runchecks/<pk>/", views.run_checks),
|
path("runchecks/<pk>/", views.run_checks),
|
||||||
path("history/<int:checkpk>/", views.CheckHistory.as_view()),
|
path("history/<int:checkpk>/", views.GetCheckHistory.as_view()),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ from automation.models import Policy
|
|||||||
from scripts.models import Script
|
from scripts.models import Script
|
||||||
from tacticalrmm.utils import notify_error
|
from tacticalrmm.utils import notify_error
|
||||||
|
|
||||||
from .models import Check
|
from .models import Check, CheckHistory
|
||||||
from .permissions import ManageChecksPerms, RunChecksPerms
|
from .permissions import ManageChecksPerms, RunChecksPerms
|
||||||
from .serializers import CheckHistorySerializer, CheckSerializer
|
from .serializers import CheckHistorySerializer, CheckSerializer
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@ class GetUpdateDeleteCheck(APIView):
|
|||||||
return Response(f"{check.readable_desc} was deleted!")
|
return Response(f"{check.readable_desc} was deleted!")
|
||||||
|
|
||||||
|
|
||||||
class CheckHistory(APIView):
|
class GetCheckHistory(APIView):
|
||||||
def patch(self, request, checkpk):
|
def patch(self, request, checkpk):
|
||||||
check = get_object_or_404(Check, pk=checkpk)
|
check = get_object_or_404(Check, pk=checkpk)
|
||||||
|
|
||||||
@@ -160,7 +160,7 @@ class CheckHistory(APIView):
|
|||||||
- djangotime.timedelta(days=request.data["timeFilter"]),
|
- djangotime.timedelta(days=request.data["timeFilter"]),
|
||||||
)
|
)
|
||||||
|
|
||||||
check_history = check.check_history.filter(timeFilter).order_by("-x") # type: ignore
|
check_history = CheckHistory.objects.filter(check_id=checkpk).filter(timeFilter).order_by("-x") # type: ignore
|
||||||
|
|
||||||
return Response(
|
return Response(
|
||||||
CheckHistorySerializer(
|
CheckHistorySerializer(
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
from agents.models import Agent
|
|
||||||
from logs.models import PendingAction
|
from logs.models import PendingAction
|
||||||
from scripts.models import Script
|
from scripts.models import Script
|
||||||
|
|
||||||
@@ -9,22 +8,6 @@ class Command(BaseCommand):
|
|||||||
help = "Collection of tasks to run after updating the rmm, after migrations"
|
help = "Collection of tasks to run after updating the rmm, after migrations"
|
||||||
|
|
||||||
def handle(self, *args, **kwargs):
|
def handle(self, *args, **kwargs):
|
||||||
# 10-16-2020 changed the type of the agent's 'disks' model field
|
|
||||||
# from a dict of dicts, to a list of disks in the golang agent
|
|
||||||
# the following will convert dicts to lists for agent's still on the python agent
|
|
||||||
agents = Agent.objects.only("pk", "disks")
|
|
||||||
for agent in agents:
|
|
||||||
if agent.disks is not None and isinstance(agent.disks, dict):
|
|
||||||
new = []
|
|
||||||
for k, v in agent.disks.items():
|
|
||||||
new.append(v)
|
|
||||||
|
|
||||||
agent.disks = new
|
|
||||||
agent.save(update_fields=["disks"])
|
|
||||||
self.stdout.write(
|
|
||||||
self.style.SUCCESS(f"Migrated disks on {agent.hostname}")
|
|
||||||
)
|
|
||||||
|
|
||||||
# remove task pending actions. deprecated 4/20/2021
|
# remove task pending actions. deprecated 4/20/2021
|
||||||
PendingAction.objects.filter(action_type="taskaction").delete()
|
PendingAction.objects.filter(action_type="taskaction").delete()
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ def dashboard_info(request):
|
|||||||
"client_tree_sort": request.user.client_tree_sort,
|
"client_tree_sort": request.user.client_tree_sort,
|
||||||
"client_tree_splitter": request.user.client_tree_splitter,
|
"client_tree_splitter": request.user.client_tree_splitter,
|
||||||
"loading_bar_color": request.user.loading_bar_color,
|
"loading_bar_color": request.user.loading_bar_color,
|
||||||
"no_code_sign": hasattr(settings, "NOCODESIGN") and settings.NOCODESIGN,
|
"hosted": hasattr(settings, "HOSTED") and settings.HOSTED,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
asgiref==3.3.4
|
asgiref==3.3.4
|
||||||
asyncio-nats-client==0.11.4
|
asyncio-nats-client==0.11.4
|
||||||
celery==5.0.5
|
celery==5.1.0
|
||||||
certifi==2020.12.5
|
certifi==2021.5.30
|
||||||
cffi==1.14.5
|
cffi==1.14.5
|
||||||
channels==3.0.3
|
channels==3.0.3
|
||||||
channels_redis==3.2.0
|
channels_redis==3.2.0
|
||||||
chardet==4.0.0
|
chardet==4.0.0
|
||||||
cryptography==3.4.7
|
cryptography==3.4.7
|
||||||
daphne==3.0.2
|
daphne==3.0.2
|
||||||
Django==3.2.2
|
Django==3.2.4
|
||||||
django-cors-headers==3.7.0
|
django-cors-headers==3.7.0
|
||||||
django-rest-knox==4.1.0
|
django-rest-knox==4.1.0
|
||||||
djangorestframework==3.12.4
|
djangorestframework==3.12.4
|
||||||
future==0.18.2
|
future==0.18.2
|
||||||
kombu==5.0.2
|
|
||||||
loguru==0.5.3
|
loguru==0.5.3
|
||||||
msgpack==1.0.2
|
msgpack==1.0.2
|
||||||
packaging==20.9
|
packaging==20.9
|
||||||
@@ -26,10 +25,10 @@ pytz==2021.1
|
|||||||
qrcode==6.1
|
qrcode==6.1
|
||||||
redis==3.5.3
|
redis==3.5.3
|
||||||
requests==2.25.1
|
requests==2.25.1
|
||||||
six==1.15.0
|
six==1.16.0
|
||||||
sqlparse==0.4.1
|
sqlparse==0.4.1
|
||||||
twilio==6.57.0
|
twilio==6.59.1
|
||||||
urllib3==1.26.4
|
urllib3==1.26.5
|
||||||
uWSGI==2.0.19.1
|
uWSGI==2.0.19.1
|
||||||
validators==0.18.2
|
validators==0.18.2
|
||||||
vine==5.0.0
|
vine==5.0.0
|
||||||
|
|||||||
@@ -6,7 +6,9 @@
|
|||||||
"name": "Firefox - Clean Cache",
|
"name": "Firefox - Clean Cache",
|
||||||
"description": "This script will clean up Mozilla Firefox for all users.",
|
"description": "This script will clean up Mozilla Firefox for all users.",
|
||||||
"shell": "powershell",
|
"shell": "powershell",
|
||||||
"category": "TRMM (Win):Browsers"
|
"category": "TRMM (Win):Browsers",
|
||||||
|
"default_timeout": "300"
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"guid": "3ff6a386-11d1-4f9d-8cca-1b0563bb6443",
|
"guid": "3ff6a386-11d1-4f9d-8cca-1b0563bb6443",
|
||||||
@@ -15,7 +17,8 @@
|
|||||||
"name": "Chrome - Clear Cache for All Users",
|
"name": "Chrome - Clear Cache for All Users",
|
||||||
"description": "This script will clean up Google Chrome for all users.",
|
"description": "This script will clean up Google Chrome for all users.",
|
||||||
"shell": "powershell",
|
"shell": "powershell",
|
||||||
"category": "TRMM (Win):Browsers"
|
"category": "TRMM (Win):Browsers",
|
||||||
|
"default_timeout": "300"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"guid": "be1de837-f677-4ac5-aa0c-37a0fc9991fc",
|
"guid": "be1de837-f677-4ac5-aa0c-37a0fc9991fc",
|
||||||
@@ -24,7 +27,8 @@
|
|||||||
"name": "Adobe Reader DC - Install",
|
"name": "Adobe Reader DC - Install",
|
||||||
"description": "Installs Adobe Reader DC.",
|
"description": "Installs Adobe Reader DC.",
|
||||||
"shell": "powershell",
|
"shell": "powershell",
|
||||||
"category": "TRMM (Win):3rd Party Software>Chocolatey"
|
"category": "TRMM (Win):3rd Party Software>Chocolatey",
|
||||||
|
"default_timeout": "300"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"guid": "2ee134d5-76aa-4160-b334-a1efbc62079f",
|
"guid": "2ee134d5-76aa-4160-b334-a1efbc62079f",
|
||||||
@@ -33,7 +37,8 @@
|
|||||||
"name": "Duplicati - Install",
|
"name": "Duplicati - Install",
|
||||||
"description": "This script installs Duplicati 2.0.5.1 as a service.",
|
"description": "This script installs Duplicati 2.0.5.1 as a service.",
|
||||||
"shell": "powershell",
|
"shell": "powershell",
|
||||||
"category": "TRMM (Win):3rd Party Software"
|
"category": "TRMM (Win):3rd Party Software",
|
||||||
|
"default_timeout": "300"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"guid": "81cc5bcb-01bf-4b0c-89b9-0ac0f3fe0c04",
|
"guid": "81cc5bcb-01bf-4b0c-89b9-0ac0f3fe0c04",
|
||||||
@@ -42,7 +47,8 @@
|
|||||||
"name": "Windows Update - Reset",
|
"name": "Windows Update - Reset",
|
||||||
"description": "This script will reset all of the Windows Updates components to DEFAULT SETTINGS.",
|
"description": "This script will reset all of the Windows Updates components to DEFAULT SETTINGS.",
|
||||||
"shell": "powershell",
|
"shell": "powershell",
|
||||||
"category": "TRMM (Win):Updates"
|
"category": "TRMM (Win):Updates",
|
||||||
|
"default_timeout": "300"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"guid": "8db87ff0-a9b4-4d9d-bc55-377bbcb85b6d",
|
"guid": "8db87ff0-a9b4-4d9d-bc55-377bbcb85b6d",
|
||||||
@@ -51,7 +57,8 @@
|
|||||||
"name": "Disk - Cleanup C: drive",
|
"name": "Disk - Cleanup C: drive",
|
||||||
"description": "Cleans the C: drive's Window Temperary files, Windows SoftwareDistribution folder, the local users Temperary folder, IIS logs (if applicable) and empties the recycling bin. All deleted files will go into a log transcript in $env:TEMP. By default this script leaves files that are newer than 7 days old however this variable can be edited.",
|
"description": "Cleans the C: drive's Window Temperary files, Windows SoftwareDistribution folder, the local users Temperary folder, IIS logs (if applicable) and empties the recycling bin. All deleted files will go into a log transcript in $env:TEMP. By default this script leaves files that are newer than 7 days old however this variable can be edited.",
|
||||||
"shell": "powershell",
|
"shell": "powershell",
|
||||||
"category": "TRMM (Win):Maintenance"
|
"category": "TRMM (Win):Maintenance",
|
||||||
|
"default_timeout": "25000"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"guid": "2f28e8c1-ae0f-4b46-a826-f513974526a3",
|
"guid": "2f28e8c1-ae0f-4b46-a826-f513974526a3",
|
||||||
@@ -78,7 +85,8 @@
|
|||||||
"name": "Speed Test - Python",
|
"name": "Speed Test - Python",
|
||||||
"description": "Runs a Speed Test using Python",
|
"description": "Runs a Speed Test using Python",
|
||||||
"shell": "python",
|
"shell": "python",
|
||||||
"category": "TRMM (Win):Network"
|
"category": "TRMM (Win):Network",
|
||||||
|
"default_timeout": "120"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"guid": "9d34f482-1f0c-4b2f-b65f-a9cf3c13ef5f",
|
"guid": "9d34f482-1f0c-4b2f-b65f-a9cf3c13ef5f",
|
||||||
@@ -161,6 +169,18 @@
|
|||||||
"shell": "powershell",
|
"shell": "powershell",
|
||||||
"category": "TRMM (Win):Collectors"
|
"category": "TRMM (Win):Collectors"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"guid": "973c34d7-cab0-4fda-999c-b4933655f946",
|
||||||
|
"filename": "Win_Screenconnect_GetGUID.ps1",
|
||||||
|
"submittedBy": "https://github.com/silversword411",
|
||||||
|
"name": "Screenconnect - Get GUID for client",
|
||||||
|
"description": "Returns Screenconnect GUID for client - Use with Custom Fields for later use. ",
|
||||||
|
"args": [
|
||||||
|
"-serviceName {{client.ScreenConnectService}}"
|
||||||
|
],
|
||||||
|
"shell": "powershell",
|
||||||
|
"category": "TRMM (Win):Collectors"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"guid": "95a2ee6f-b89b-4551-856e-3081b041caa7",
|
"guid": "95a2ee6f-b89b-4551-856e-3081b041caa7",
|
||||||
"filename": "Win_Power_Profile_Reset_High_Performance_to_Defaults.ps1",
|
"filename": "Win_Power_Profile_Reset_High_Performance_to_Defaults.ps1",
|
||||||
@@ -186,7 +206,8 @@
|
|||||||
"name": "Windows 10 Upgrade",
|
"name": "Windows 10 Upgrade",
|
||||||
"description": "Forces an upgrade to the latest release of Windows 10.",
|
"description": "Forces an upgrade to the latest release of Windows 10.",
|
||||||
"shell": "powershell",
|
"shell": "powershell",
|
||||||
"category": "TRMM (Win):Updates"
|
"category": "TRMM (Win):Updates",
|
||||||
|
"default_timeout": "25000"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"guid": "375323e5-cac6-4f35-a304-bb7cef35902d",
|
"guid": "375323e5-cac6-4f35-a304-bb7cef35902d",
|
||||||
@@ -222,7 +243,8 @@
|
|||||||
"name": "SSH - Install Feature and Enable",
|
"name": "SSH - Install Feature and Enable",
|
||||||
"description": "Installs and enabled OpenSSH Server Feature in Win10",
|
"description": "Installs and enabled OpenSSH Server Feature in Win10",
|
||||||
"shell": "powershell",
|
"shell": "powershell",
|
||||||
"category": "TRMM (Win):Windows Features"
|
"category": "TRMM (Win):Windows Features",
|
||||||
|
"default_timeout": "300"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"guid": "2435297a-6263-4e90-8688-1847400d0e22",
|
"guid": "2435297a-6263-4e90-8688-1847400d0e22",
|
||||||
@@ -339,7 +361,8 @@
|
|||||||
"name": "Update Installed Apps",
|
"name": "Update Installed Apps",
|
||||||
"description": "Update all apps that were installed using Chocolatey.",
|
"description": "Update all apps that were installed using Chocolatey.",
|
||||||
"shell": "cmd",
|
"shell": "cmd",
|
||||||
"category": "TRMM (Win):3rd Party Software>Chocolatey"
|
"category": "TRMM (Win):3rd Party Software>Chocolatey",
|
||||||
|
"default_timeout": "3600"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"guid": "fff8024d-d72e-4457-84fa-6c780f69a16f",
|
"guid": "fff8024d-d72e-4457-84fa-6c780f69a16f",
|
||||||
@@ -660,4 +683,4 @@
|
|||||||
"category": "TRMM (Win):Misc>Reference",
|
"category": "TRMM (Win):Misc>Reference",
|
||||||
"default_timeout": "1"
|
"default_timeout": "1"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ app.conf.beat_schedule = {
|
|||||||
},
|
},
|
||||||
"get-wmi": {
|
"get-wmi": {
|
||||||
"task": "agents.tasks.get_wmi_task",
|
"task": "agents.tasks.get_wmi_task",
|
||||||
"schedule": crontab(minute="*/18"),
|
"schedule": crontab(minute=18, hour="*/5"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,22 +15,22 @@ EXE_DIR = os.path.join(BASE_DIR, "tacticalrmm/private/exe")
|
|||||||
AUTH_USER_MODEL = "accounts.User"
|
AUTH_USER_MODEL = "accounts.User"
|
||||||
|
|
||||||
# latest release
|
# latest release
|
||||||
TRMM_VERSION = "0.6.11"
|
TRMM_VERSION = "0.6.14"
|
||||||
|
|
||||||
# bump this version everytime vue code is changed
|
# bump this version everytime vue code is changed
|
||||||
# to alert user they need to manually refresh their browser
|
# to alert user they need to manually refresh their browser
|
||||||
APP_VER = "0.0.136"
|
APP_VER = "0.0.138"
|
||||||
|
|
||||||
# https://github.com/wh1te909/rmmagent
|
# https://github.com/wh1te909/rmmagent
|
||||||
LATEST_AGENT_VER = "1.5.6"
|
LATEST_AGENT_VER = "1.5.8"
|
||||||
|
|
||||||
MESH_VER = "0.8.35"
|
MESH_VER = "0.8.60"
|
||||||
|
|
||||||
# for the update script, bump when need to recreate venv or npm install
|
# for the update script, bump when need to recreate venv or npm install
|
||||||
PIP_VER = "16"
|
PIP_VER = "18"
|
||||||
NPM_VER = "15"
|
NPM_VER = "17"
|
||||||
|
|
||||||
SETUPTOOLS_VER = "56.1.0"
|
SETUPTOOLS_VER = "57.0.0"
|
||||||
WHEEL_VER = "0.36.2"
|
WHEEL_VER = "0.36.2"
|
||||||
|
|
||||||
DL_64 = f"https://github.com/wh1te909/rmmagent/releases/download/v{LATEST_AGENT_VER}/winagent-v{LATEST_AGENT_VER}.exe"
|
DL_64 = f"https://github.com/wh1te909/rmmagent/releases/download/v{LATEST_AGENT_VER}/winagent-v{LATEST_AGENT_VER}.exe"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
SCRIPT_VERSION="12"
|
SCRIPT_VERSION="13"
|
||||||
SCRIPT_URL='https://raw.githubusercontent.com/wh1te909/tacticalrmm/master/backup.sh'
|
SCRIPT_URL='https://raw.githubusercontent.com/wh1te909/tacticalrmm/master/backup.sh'
|
||||||
|
|
||||||
GREEN='\033[0;32m'
|
GREEN='\033[0;32m'
|
||||||
@@ -59,6 +59,7 @@ mkdir ${tmp_dir}/nginx
|
|||||||
mkdir ${tmp_dir}/systemd
|
mkdir ${tmp_dir}/systemd
|
||||||
mkdir ${tmp_dir}/rmm
|
mkdir ${tmp_dir}/rmm
|
||||||
mkdir ${tmp_dir}/confd
|
mkdir ${tmp_dir}/confd
|
||||||
|
mkdir ${tmp_dir}/redis
|
||||||
|
|
||||||
|
|
||||||
pg_dump --dbname=postgresql://"${POSTGRES_USER}":"${POSTGRES_PW}"@127.0.0.1:5432/tacticalrmm | gzip -9 > ${tmp_dir}/postgres/db-${dt_now}.psql.gz
|
pg_dump --dbname=postgresql://"${POSTGRES_USER}":"${POSTGRES_PW}"@127.0.0.1:5432/tacticalrmm | gzip -9 > ${tmp_dir}/postgres/db-${dt_now}.psql.gz
|
||||||
@@ -72,6 +73,8 @@ sudo tar -czvf ${tmp_dir}/nginx/etc-nginx.tar.gz -C /etc/nginx .
|
|||||||
|
|
||||||
sudo tar -czvf ${tmp_dir}/confd/etc-confd.tar.gz -C /etc/conf.d .
|
sudo tar -czvf ${tmp_dir}/confd/etc-confd.tar.gz -C /etc/conf.d .
|
||||||
|
|
||||||
|
sudo tar -czvf ${tmp_dir}/redis/etc-redis.tar.gz -C /var/lib/redis/appendonly.aof
|
||||||
|
|
||||||
sudo cp ${sysd}/rmm.service ${sysd}/celery.service ${sysd}/celerybeat.service ${sysd}/meshcentral.service ${sysd}/nats.service ${tmp_dir}/systemd/
|
sudo cp ${sysd}/rmm.service ${sysd}/celery.service ${sysd}/celerybeat.service ${sysd}/meshcentral.service ${sysd}/nats.service ${tmp_dir}/systemd/
|
||||||
if [ -f "${sysd}/daphne.service" ]; then
|
if [ -f "${sysd}/daphne.service" ]; then
|
||||||
sudo cp ${sysd}/daphne.service ${tmp_dir}/systemd/
|
sudo cp ${sysd}/daphne.service ${tmp_dir}/systemd/
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM nats:2.2-alpine
|
FROM nats:2.2.6-alpine
|
||||||
|
|
||||||
ENV TACTICAL_DIR /opt/tactical
|
ENV TACTICAL_DIR /opt/tactical
|
||||||
ENV TACTICAL_READY_FILE ${TACTICAL_DIR}/tmp/tactical.ready
|
ENV TACTICAL_READY_FILE ${TACTICAL_DIR}/tmp/tactical.ready
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ volumes:
|
|||||||
postgres_data:
|
postgres_data:
|
||||||
mongo_data:
|
mongo_data:
|
||||||
mesh_data:
|
mesh_data:
|
||||||
|
redis_data:
|
||||||
|
|
||||||
services:
|
services:
|
||||||
# postgres database for api service
|
# postgres database for api service
|
||||||
@@ -38,7 +39,10 @@ services:
|
|||||||
tactical-redis:
|
tactical-redis:
|
||||||
container_name: trmm-redis
|
container_name: trmm-redis
|
||||||
image: redis:6.0-alpine
|
image: redis:6.0-alpine
|
||||||
|
command: redis-server --appendonly yes
|
||||||
restart: always
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- redis_data:/data
|
||||||
networks:
|
networks:
|
||||||
- redis
|
- redis
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ Category or Function - What It Does
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
*****
|
||||||
|
|
||||||
## Making Script Files
|
## Making Script Files
|
||||||
|
|
||||||
### Good Habits
|
### Good Habits
|
||||||
@@ -117,6 +119,8 @@ c:\ProgramData\TacticalRMM\
|
|||||||
- Doesn't play well with other community scripts (reused names etc.)
|
- Doesn't play well with other community scripts (reused names etc.)
|
||||||
|
|
||||||
|
|
||||||
|
*****
|
||||||
|
|
||||||
## Useful Reference Script Examples
|
## Useful Reference Script Examples
|
||||||
|
|
||||||
RunAsUser (since Tactical RMM runs as system)
|
RunAsUser (since Tactical RMM runs as system)
|
||||||
@@ -128,6 +132,8 @@ Command Paramater Ninja
|
|||||||
Optional Command Parameters and testing for errors
|
Optional Command Parameters and testing for errors
|
||||||
[https://github.com/wh1te909/tacticalrmm/blob/develop/scripts/Win_Rename_Computer.ps1](https://github.com/wh1te909/tacticalrmm/blob/develop/scripts/Win_Rename_Computer.ps1)
|
[https://github.com/wh1te909/tacticalrmm/blob/develop/scripts/Win_Rename_Computer.ps1](https://github.com/wh1te909/tacticalrmm/blob/develop/scripts/Win_Rename_Computer.ps1)
|
||||||
|
|
||||||
|
*****
|
||||||
|
|
||||||
## Volunteers Needed
|
## Volunteers Needed
|
||||||
|
|
||||||
If you want to contribute back to the project there are a lot of scripts that need some TLC (Tender Loving Care) please paruse thru them here: [https://github.com/wh1te909/tacticalrmm/tree/develop/scripts_wip](https://github.com/wh1te909/tacticalrmm/tree/develop/scripts_wip)
|
If you want to contribute back to the project there are a lot of scripts that need some TLC (Tender Loving Care) please paruse thru them here: [https://github.com/wh1te909/tacticalrmm/tree/develop/scripts_wip](https://github.com/wh1te909/tacticalrmm/tree/develop/scripts_wip)
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ Then you're `push`ing that updated local repo to your online Github fork
|
|||||||
|
|
||||||
Check your Github fork in browser, should be up to date now with original. Repeat 6 or 7 as necessary
|
Check your Github fork in browser, should be up to date now with original. Repeat 6 or 7 as necessary
|
||||||
|
|
||||||
|
*****
|
||||||
## Reference
|
## Reference
|
||||||
|
|
||||||
### Customizing the Admin Web Interface
|
### Customizing the Admin Web Interface
|
||||||
|
|||||||
31
docs/docs/functions/examples.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# Examples
|
||||||
|
|
||||||
|
## Create Run URL Action to Computer support page
|
||||||
|
|
||||||
|
This will create a URL link that will take you to the support page for a computer based on the computers Serial Number
|
||||||
|
|
||||||
|
1. Goto `Settings | Global Settings | Custom Fields`
|
||||||
|
|
||||||
|
Under Agents tab Add Custom Field (CaSe SeNsItIve)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
2. Create Task (best to use `Settings | Automation Manager` if you want to apply it to all computers). Add script that has an output of the data you want.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
3. Create URL Action (under `Settings | Global Settings | URL ACTIONS`) for Manufacturer websites
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Dell Support Page
|
||||||
|
|
||||||
|
```
|
||||||
|
https://www.dell.com/support/home/en-us/product-support/servicetag/{{agent.SerialNumber}}/overview
|
||||||
|
```
|
||||||
|
|
||||||
|
Lenovo Support Page
|
||||||
|
|
||||||
|
```
|
||||||
|
https://www.dell.com/support/home/en-us/product-support/servicetag/{{agent.SerialNumber}}/overview
|
||||||
|
```
|
||||||
58
docs/docs/howitallworks.md
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# How It All Works
|
||||||
|
|
||||||
|
INSERT WIREFRAME GRAPHIC HERE USING <https://www.yworks.com/yed-live/>
|
||||||
|
|
||||||
|
## Server
|
||||||
|
|
||||||
|
## Windows Agent
|
||||||
|
|
||||||
|
Found in `%programfiles%\TacticalAgent`
|
||||||
|
|
||||||
|
### Services
|
||||||
|
|
||||||
|
3 services exist on all clients
|
||||||
|
|
||||||
|
* `Mesh Agent`
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
**AND**
|
||||||
|
|
||||||
|
* `TacticalAgent` and `Tactical RMM RPC Service`
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
The [MeshCentral](https://meshcentral.com/) system which is accessible from <https://mesh.example.com> and is used
|
||||||
|
|
||||||
|
`Tactical RMM Agent`
|
||||||
|
|
||||||
|
* It runs 2 goroutines
|
||||||
|
* one is the checkrunner which runs all the checks and then just sleeps until it's time to run more checks
|
||||||
|
* 2nd goroutine periodically sends info about the agent to the rmm and also handles agent recovery
|
||||||
|
|
||||||
|
!!!note
|
||||||
|
In Task Manager you will see additional `Tactical RMM Agent` processes appear and disappear. These are your Checks and Tasks running at scheduled intervals
|
||||||
|
|
||||||
|
`Tactical RMM RPC Service`
|
||||||
|
|
||||||
|
* Uses the pub/sub model so anytime you do anything realtime from rmm (like a send command or run script)
|
||||||
|
* It maintains a persistent connection to your to the api.example.com rmm server on port **443 CONFIRM** and is listening for events
|
||||||
|
* It handles your Agent updates (Auto triggers at 35mins past every hour or when run manually from server Agents | Update Agents menu)
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
### Agent Installation Process
|
||||||
|
|
||||||
|
Adds Defender AV exclusions
|
||||||
|
|
||||||
|
Copies
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
### Agent Update Process
|
||||||
|
|
||||||
|
Downloads latest `winagent-vx.x.x-x86/64.exe` to `%programfiles%`
|
||||||
|
|
||||||
|
Executes the file (INNO setup exe)
|
||||||
|
|
||||||
|
Files create `c:\Windows\temp\Tacticalxxxx\` folder for install (and log files)
|
||||||
BIN
docs/docs/images/example1_customfield.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
docs/docs/images/example1_taskcollectorscript.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
docs/docs/images/example1_urlaction.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
docs/docs/images/trmm_services.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
docs/docs/images/trmm_services__taskmanager_agent.png
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
docs/docs/images/trmm_services__taskmanager_mesh.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
docs/docs/images/trmm_services_mesh.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
docs/docs/images/trmm_user_preferences.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
@@ -14,6 +14,10 @@
|
|||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
|
!!!info
|
||||||
|
It is recommended that you keep your server updated regularly (monthly). SSL wildcard certs will expire every 3 months and need manual updating as well. <br/><br/>
|
||||||
|
Until we reach production release, there may be architectural changes that may be made to Tactical RMM and only a regular patching schedule is supported by developers.
|
||||||
|
|
||||||
#### Run updates and setup the linux user
|
#### Run updates and setup the linux user
|
||||||
SSH into the server as **root**.<br/><br/>
|
SSH into the server as **root**.<br/><br/>
|
||||||
Download and run the prereqs and latest updates<br/>
|
Download and run the prereqs and latest updates<br/>
|
||||||
|
|||||||
52
docs/docs/tipsntricks.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# Tips and Tricks
|
||||||
|
|
||||||
|
## Customize User Interface
|
||||||
|
|
||||||
|
Top right click Username, look at preferences pane. Set default tab: Servers|Workstations|Mixed
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
*****
|
||||||
|
|
||||||
|
## Screenconnect / Connectwise Control
|
||||||
|
|
||||||
|
### Install Tactical RMM via Screeconnect commands window
|
||||||
|
|
||||||
|
1. Create a Deplopment under Agents | Manage Deployments
|
||||||
|
2. Replace `<deployment URL>` below with your Deployment Download Link.
|
||||||
|
|
||||||
|
**x64**
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
#!ps
|
||||||
|
#maxlength=500000
|
||||||
|
#timeout=600000
|
||||||
|
|
||||||
|
Invoke-WebRequest "<deployment URL>" -OutFile ( New-Item -Path "C:\temp\trmminstallx64.exe" -Force )
|
||||||
|
$proc = Start-Process c:\temp\trmminstallx64.exe -ArgumentList '-silent' -PassThru
|
||||||
|
Wait-Process -InputObject $proc
|
||||||
|
|
||||||
|
if ($proc.ExitCode -ne 0) {
|
||||||
|
Write-Warning "$_ exited with status code $($proc.ExitCode)"
|
||||||
|
}
|
||||||
|
Remove-Item -Path "c:\temp\trmminstallx64.exe" -Force
|
||||||
|
```
|
||||||
|
|
||||||
|
**x86**
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
#!ps
|
||||||
|
#maxlength=500000
|
||||||
|
#timeout=600000
|
||||||
|
|
||||||
|
Invoke-WebRequest "<deployment URL>" -OutFile ( New-Item -Path "C:\temp\trmminstallx86.exe" -Force )
|
||||||
|
$proc = Start-Process c:\temp\trmminstallx86.exe -ArgumentList '-silent' -PassThru
|
||||||
|
Wait-Process -InputObject $proc
|
||||||
|
|
||||||
|
if ($proc.ExitCode -ne 0) {
|
||||||
|
Write-Warning "$_ exited with status code $($proc.ExitCode)"
|
||||||
|
}
|
||||||
|
Remove-Item -Path "c:\temp\trmminstallx86.exe" -Force
|
||||||
|
```
|
||||||
|
|
||||||
|
###
|
||||||
@@ -23,6 +23,7 @@ nav:
|
|||||||
- "User Interface Preferences": functions/user_ui.md
|
- "User Interface Preferences": functions/user_ui.md
|
||||||
- "Django Admin": functions/django_admin.md
|
- "Django Admin": functions/django_admin.md
|
||||||
- "Settings Override": functions/settings_override.md
|
- "Settings Override": functions/settings_override.md
|
||||||
|
- "Examples": functions/examples.md
|
||||||
- Backup: backup.md
|
- Backup: backup.md
|
||||||
- Restore: restore.md
|
- Restore: restore.md
|
||||||
- Troubleshooting: troubleshooting.md
|
- Troubleshooting: troubleshooting.md
|
||||||
|
|||||||
2
go.mod
@@ -5,6 +5,6 @@ go 1.16
|
|||||||
require (
|
require (
|
||||||
github.com/nats-io/nats-server/v2 v2.1.8-0.20201129161730-ebe63db3e3ed // indirect
|
github.com/nats-io/nats-server/v2 v2.1.8-0.20201129161730-ebe63db3e3ed // indirect
|
||||||
github.com/nats-io/nats.go v1.11.0
|
github.com/nats-io/nats.go v1.11.0
|
||||||
github.com/ugorji/go/codec v1.2.5
|
github.com/ugorji/go/codec v1.2.6
|
||||||
golang.org/x/sys v0.0.0-20210122235752-a8b976e07c7b // indirect
|
golang.org/x/sys v0.0.0-20210122235752-a8b976e07c7b // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
8
go.sum
@@ -34,10 +34,10 @@ github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=
|
|||||||
github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
|
github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
|
||||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||||
github.com/ugorji/go v1.2.5 h1:NozRHfUeEta89taVkyfsDVSy2f7v89Frft4pjnWuGuc=
|
github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E=
|
||||||
github.com/ugorji/go v1.2.5/go.mod h1:gat2tIT8KJG8TVI8yv77nEO/KYT6dV7JE1gfUa8Xuls=
|
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
|
||||||
github.com/ugorji/go/codec v1.2.5 h1:8WobZKAk18Msm2CothY2jnztY56YVY8kF1oQrj21iis=
|
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
|
||||||
github.com/ugorji/go/codec v1.2.5/go.mod h1:QPxoTbPKSEAlAHPYt02++xp/en9B/wUdwFCz+hj5caA=
|
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
|||||||
20
install.sh
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
SCRIPT_VERSION="48"
|
SCRIPT_VERSION="50"
|
||||||
SCRIPT_URL='https://raw.githubusercontent.com/wh1te909/tacticalrmm/master/install.sh'
|
SCRIPT_URL='https://raw.githubusercontent.com/wh1te909/tacticalrmm/master/install.sh'
|
||||||
|
|
||||||
sudo apt install -y curl wget dirmngr gnupg lsb-release
|
sudo apt install -y curl wget dirmngr gnupg lsb-release
|
||||||
@@ -167,11 +167,11 @@ sudo chmod 775 -R /etc/letsencrypt
|
|||||||
print_green 'Downloading NATS'
|
print_green 'Downloading NATS'
|
||||||
|
|
||||||
nats_tmp=$(mktemp -d -t nats-XXXXXXXXXX)
|
nats_tmp=$(mktemp -d -t nats-XXXXXXXXXX)
|
||||||
wget https://github.com/nats-io/nats-server/releases/download/v2.2.3/nats-server-v2.2.3-linux-amd64.tar.gz -P ${nats_tmp}
|
wget https://github.com/nats-io/nats-server/releases/download/v2.2.6/nats-server-v2.2.6-linux-amd64.tar.gz -P ${nats_tmp}
|
||||||
|
|
||||||
tar -xzf ${nats_tmp}/nats-server-v2.2.3-linux-amd64.tar.gz -C ${nats_tmp}
|
tar -xzf ${nats_tmp}/nats-server-v2.2.6-linux-amd64.tar.gz -C ${nats_tmp}
|
||||||
|
|
||||||
sudo mv ${nats_tmp}/nats-server-v2.2.3-linux-amd64/nats-server /usr/local/bin/
|
sudo mv ${nats_tmp}/nats-server-v2.2.6-linux-amd64/nats-server /usr/local/bin/
|
||||||
sudo chmod +x /usr/local/bin/nats-server
|
sudo chmod +x /usr/local/bin/nats-server
|
||||||
sudo chown ${USER}:${USER} /usr/local/bin/nats-server
|
sudo chown ${USER}:${USER} /usr/local/bin/nats-server
|
||||||
rm -rf ${nats_tmp}
|
rm -rf ${nats_tmp}
|
||||||
@@ -217,6 +217,10 @@ sudo rm -rf Python-3.9.2 Python-3.9.2.tgz
|
|||||||
print_green 'Installing redis and git'
|
print_green 'Installing redis and git'
|
||||||
sudo apt install -y ca-certificates redis git
|
sudo apt install -y ca-certificates redis git
|
||||||
|
|
||||||
|
# apply redis configuration
|
||||||
|
sudo redis-cli config set appendonly yes
|
||||||
|
sudo redis-cli config rewrite
|
||||||
|
|
||||||
print_green 'Installing postgresql'
|
print_green 'Installing postgresql'
|
||||||
|
|
||||||
echo "$postgresql_repo" | sudo tee /etc/apt/sources.list.d/pgdg.list
|
echo "$postgresql_repo" | sudo tee /etc/apt/sources.list.d/pgdg.list
|
||||||
@@ -487,12 +491,14 @@ map \$http_user_agent \$ignore_ua {
|
|||||||
|
|
||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
server_name ${rmmdomain};
|
server_name ${rmmdomain};
|
||||||
return 301 https://\$server_name\$request_uri;
|
return 301 https://\$server_name\$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 443 ssl;
|
listen 443 ssl;
|
||||||
|
listen [::]:443 ssl;
|
||||||
server_name ${rmmdomain};
|
server_name ${rmmdomain};
|
||||||
client_max_body_size 300M;
|
client_max_body_size 300M;
|
||||||
access_log /rmm/api/tacticalrmm/tacticalrmm/private/log/access.log combined if=\$ignore_ua;
|
access_log /rmm/api/tacticalrmm/tacticalrmm/private/log/access.log combined if=\$ignore_ua;
|
||||||
@@ -549,6 +555,7 @@ echo "${nginxrmm}" | sudo tee /etc/nginx/sites-available/rmm.conf > /dev/null
|
|||||||
nginxmesh="$(cat << EOF
|
nginxmesh="$(cat << EOF
|
||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
server_name ${meshdomain};
|
server_name ${meshdomain};
|
||||||
return 301 https://\$server_name\$request_uri;
|
return 301 https://\$server_name\$request_uri;
|
||||||
}
|
}
|
||||||
@@ -556,6 +563,7 @@ server {
|
|||||||
server {
|
server {
|
||||||
|
|
||||||
listen 443 ssl;
|
listen 443 ssl;
|
||||||
|
listen [::]:443 ssl;
|
||||||
proxy_send_timeout 330s;
|
proxy_send_timeout 330s;
|
||||||
proxy_read_timeout 330s;
|
proxy_read_timeout 330s;
|
||||||
server_name ${meshdomain};
|
server_name ${meshdomain};
|
||||||
@@ -710,6 +718,7 @@ server {
|
|||||||
access_log /var/log/nginx/frontend-access.log;
|
access_log /var/log/nginx/frontend-access.log;
|
||||||
|
|
||||||
listen 443 ssl;
|
listen 443 ssl;
|
||||||
|
listen [::]:443 ssl;
|
||||||
ssl_certificate ${CERT_PUB_KEY};
|
ssl_certificate ${CERT_PUB_KEY};
|
||||||
ssl_certificate_key ${CERT_PRIV_KEY};
|
ssl_certificate_key ${CERT_PRIV_KEY};
|
||||||
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
|
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
|
||||||
@@ -720,7 +729,8 @@ server {
|
|||||||
return 301 https://\$host\$request_uri;
|
return 301 https://\$host\$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
listen 80;
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
server_name ${frontenddomain};
|
server_name ${frontenddomain};
|
||||||
return 404;
|
return 404;
|
||||||
}
|
}
|
||||||
|
|||||||
15
restore.sh
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
SCRIPT_VERSION="26"
|
SCRIPT_VERSION="28"
|
||||||
SCRIPT_URL='https://raw.githubusercontent.com/wh1te909/tacticalrmm/master/restore.sh'
|
SCRIPT_URL='https://raw.githubusercontent.com/wh1te909/tacticalrmm/master/restore.sh'
|
||||||
|
|
||||||
sudo apt update
|
sudo apt update
|
||||||
@@ -108,11 +108,11 @@ sudo apt update
|
|||||||
print_green 'Downloading NATS'
|
print_green 'Downloading NATS'
|
||||||
|
|
||||||
nats_tmp=$(mktemp -d -t nats-XXXXXXXXXX)
|
nats_tmp=$(mktemp -d -t nats-XXXXXXXXXX)
|
||||||
wget https://github.com/nats-io/nats-server/releases/download/v2.2.3/nats-server-v2.2.3-linux-amd64.tar.gz -P ${nats_tmp}
|
wget https://github.com/nats-io/nats-server/releases/download/v2.2.6/nats-server-v2.2.6-linux-amd64.tar.gz -P ${nats_tmp}
|
||||||
|
|
||||||
tar -xzf ${nats_tmp}/nats-server-v2.2.3-linux-amd64.tar.gz -C ${nats_tmp}
|
tar -xzf ${nats_tmp}/nats-server-v2.2.6-linux-amd64.tar.gz -C ${nats_tmp}
|
||||||
|
|
||||||
sudo mv ${nats_tmp}/nats-server-v2.2.3-linux-amd64/nats-server /usr/local/bin/
|
sudo mv ${nats_tmp}/nats-server-v2.2.6-linux-amd64/nats-server /usr/local/bin/
|
||||||
sudo chmod +x /usr/local/bin/nats-server
|
sudo chmod +x /usr/local/bin/nats-server
|
||||||
sudo chown ${USER}:${USER} /usr/local/bin/nats-server
|
sudo chown ${USER}:${USER} /usr/local/bin/nats-server
|
||||||
rm -rf ${nats_tmp}
|
rm -rf ${nats_tmp}
|
||||||
@@ -189,6 +189,13 @@ sudo rm -rf Python-3.9.2 Python-3.9.2.tgz
|
|||||||
print_green 'Installing redis and git'
|
print_green 'Installing redis and git'
|
||||||
sudo apt install -y ca-certificates redis git
|
sudo apt install -y ca-certificates redis git
|
||||||
|
|
||||||
|
# redis configuration
|
||||||
|
sudo tar -xzf ${tmp_dir}/redis/etc-redis.tar.gz -C /var/lib/redis
|
||||||
|
sudo redis-check-aof --fix /var/lib/redis/appendonly.aof
|
||||||
|
|
||||||
|
sudo redis-cli config set appendonly yes
|
||||||
|
sudo redis-cli config rewrite
|
||||||
|
|
||||||
print_green 'Installing postgresql'
|
print_green 'Installing postgresql'
|
||||||
|
|
||||||
echo "$postgresql_repo" | sudo tee /etc/apt/sources.list.d/pgdg.list
|
echo "$postgresql_repo" | sudo tee /etc/apt/sources.list.d/pgdg.list
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
#antivirusName must match the "displayName" exactly
|
#antivirusName must match the "displayName" exactly
|
||||||
#If no antivirusName parameter is specified, the tool returns success if there is any active up to date antivirus on the system
|
#If no antivirusName parameter is specified, the tool returns success if there is any active up to date antivirus on the system
|
||||||
|
|
||||||
|
# OS Build must be greater than 14393 to support this script. If it's not it returns exit code 2
|
||||||
|
|
||||||
|
|
||||||
param($antivirusName = "*")
|
param($antivirusName = "*")
|
||||||
|
|
||||||
@@ -93,6 +95,11 @@ function Add-ProductStates {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ([environment]::OSVersion.Version.Build -le 14393) {
|
||||||
|
write-host "Antivirus check not supported on this OS. Returning Exit Code 2."
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$return = Get-CimInstance -Namespace root/SecurityCenter2 -className AntivirusProduct |
|
$return = Get-CimInstance -Namespace root/SecurityCenter2 -className AntivirusProduct |
|
||||||
Where-Object {
|
Where-Object {
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
## Copied from https://github.com/ThatsNASt/tacticalrmm to add to new pull request for https://github.com/wh1te909/tacticalrmm
|
## Copied from https://github.com/ThatsNASt/tacticalrmm to add to new pull request for https://github.com/wh1te909/tacticalrmm
|
||||||
|
#
|
||||||
|
# WARNING
|
||||||
|
# 1. Only applies to drive C
|
||||||
|
# 2. Assumes you're encrypting more than the used space. "Used Space Only Encrypted" is the default windows behavior which is not compatible here.
|
||||||
|
|
||||||
function Log-Message {
|
function Log-Message {
|
||||||
Param
|
Param
|
||||||
(
|
(
|
||||||
@@ -22,7 +27,7 @@ function Log-Message {
|
|||||||
$log = "BitlockerReport.txt"
|
$log = "BitlockerReport.txt"
|
||||||
|
|
||||||
#Find BL info
|
#Find BL info
|
||||||
$mbde = [string](manage-bde -status)
|
$mbde = [string](manage-bde -status C:)
|
||||||
$mbdeProt = (manage-bde -protectors -get c: | Select-Object -Skip 6)
|
$mbdeProt = (manage-bde -protectors -get c: | Select-Object -Skip 6)
|
||||||
#Dig out the recovery password, check for PIN
|
#Dig out the recovery password, check for PIN
|
||||||
ForEach ($line in $mbdeProt) {
|
ForEach ($line in $mbdeProt) {
|
||||||
@@ -94,4 +99,4 @@ if ($Encrypted -eq "Yes" -and $RecoveryPassword -and $PIN -eq $true) {
|
|||||||
Log-Message "SUCCESS: Encrypted, PIN enabled, password is set." $log e
|
Log-Message "SUCCESS: Encrypted, PIN enabled, password is set." $log e
|
||||||
Write-Host "Script check passed"
|
Write-Host "Script check passed"
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
cup -y all
|
cup all -y
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ else {
|
|||||||
Install-Module -Name RunAsUser -Force
|
Install-Module -Name RunAsUser -Force
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Used to pull variables in and use them inside the script block. Contains message to show user
|
||||||
Set-Content -Path c:\windows\temp\message.txt -Value $args
|
Set-Content -Path c:\windows\temp\message.txt -Value $args
|
||||||
|
|
||||||
Invoke-AsCurrentUser -scriptblock {
|
Invoke-AsCurrentUser -scriptblock {
|
||||||
@@ -55,5 +56,5 @@ Invoke-AsCurrentUser -scriptblock {
|
|||||||
Submit-BTNotification -Content $Content
|
Submit-BTNotification -Content $Content
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Cleanup temp file for message variables
|
||||||
Remove-Item -Path c:\windows\temp\message.txt
|
Remove-Item -Path c:\windows\temp\message.txt
|
||||||
|
|||||||
@@ -10,28 +10,6 @@
|
|||||||
Submitted by: https://github.com/dinger1986
|
Submitted by: https://github.com/dinger1986
|
||||||
#>
|
#>
|
||||||
|
|
||||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
|
||||||
|
|
||||||
$regpath = HKCU:\Software\Microsoft\Office\16.0\Outlook\Preferences
|
|
||||||
$regname = DelegateSentItemsStyle
|
|
||||||
$regvalue = 1
|
|
||||||
$regproperty = Dword
|
|
||||||
|
|
||||||
|
|
||||||
If (!(test-path '%ProgramData%\Tactical RMM\temp')) {
|
|
||||||
New-Item -ItemType Directory -Force -Path '%ProgramData%\Tactical RMM\temp'
|
|
||||||
}
|
|
||||||
|
|
||||||
If (!(test-path C:\TEMP\curpsxpolicy.txt)) {
|
|
||||||
$curexpolicy = Get-ExecutionPolicy
|
|
||||||
|
|
||||||
(
|
|
||||||
echo $curexpolicy
|
|
||||||
)>"%ProgramData%\Tactical RMM\temp\curpsxpolicy.txt"
|
|
||||||
}
|
|
||||||
|
|
||||||
Set-ExecutionPolicy -ExecutionPolicy Unrestricted
|
|
||||||
|
|
||||||
if (Get-PackageProvider -Name NuGet) {
|
if (Get-PackageProvider -Name NuGet) {
|
||||||
Write-Output "NuGet Already Added"
|
Write-Output "NuGet Already Added"
|
||||||
}
|
}
|
||||||
@@ -48,14 +26,30 @@ else {
|
|||||||
Install-Module -Name RunAsUser -Force
|
Install-Module -Name RunAsUser -Force
|
||||||
}
|
}
|
||||||
|
|
||||||
|
If (!(test-path $env:programdata\TacticalRMM\temp\)) {
|
||||||
|
New-Item -ItemType Directory -Force -Path $env:programdata\TacticalRMM\temp\
|
||||||
|
}
|
||||||
|
|
||||||
|
If (!(test-path $env:programdata\TacticalRMM\temp\curpsxpolicy.txt)) {
|
||||||
|
$curexpolicy = Get-ExecutionPolicy
|
||||||
|
|
||||||
|
(
|
||||||
|
Write-Output $curexpolicy
|
||||||
|
)>$env:programdata\TacticalRMM\temp\curpsxpolicy.txt
|
||||||
|
}
|
||||||
|
Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell -Name ExecutionPolicy -Value Unrestricted
|
||||||
|
|
||||||
Invoke-AsCurrentUser -scriptblock {
|
Invoke-AsCurrentUser -scriptblock {
|
||||||
New-ItemProperty -Path "$regpath" -Name "$regname" -Value "$regvalue" -PropertyType "$regproperty"
|
# Modify below for other versions of Office
|
||||||
|
$regpath = 'Software\Microsoft\Office\16.0\Outlook\Preferences'
|
||||||
|
$regname = "DelegateSentItemsStyle"
|
||||||
|
$regvalue = "1"
|
||||||
|
$regproperty = "Dword"
|
||||||
|
New-ItemProperty -Path HKCU:\$regpath -Name $regname -Value $regvalue -PropertyType $regproperty
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Output "Successfully changed Sent Items for Delegated folders"
|
Write-Output "Successfully changed Sent Items for Delegated folders"
|
||||||
|
|
||||||
$curpsxpol = Get-Content -Path "%ProgramData%\Tactical RMM\temp\curpsxpolicy.txt";
|
$curpsxpol = Get-Content -Path $env:programdata\TacticalRMM\temp\curpsxpolicy.txt;
|
||||||
|
|
||||||
Set-ExecutionPolicy -ExecutionPolicy $curpsxpol
|
Set-ExecutionPolicy -ExecutionPolicy $curpsxpol
|
||||||
|
|
||||||
del "%ProgramData%\Tactical RMM\temp\curpsxpolicy.txt"
|
|
||||||
26
scripts/Win_Screenconnect_GetGUID.ps1
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<#
|
||||||
|
Requires global variables for serviceName "ScreenConnectService"
|
||||||
|
serviceName is the name of the ScreenConnect Service once it is installed EG: "ScreenConnect Client (1327465grctq84yrtocq)"
|
||||||
|
Variable value must start and end with " (Prior to TRMM Version 0.6.5), remove / don't use " on TRMM Version 0.6.5 or later.
|
||||||
|
Requires Custom Fields Agent entry Name: ScreenConnectGUID Type: text
|
||||||
|
URL Action entry (check your screenconnect to see what folder name is your "All Machines" folder): https://YOURNAME.screenconnect.com/Host#Access/All%20Machines//{{agent.ScreenConnectGUID}}/Join
|
||||||
|
or https://YOURNAME.screenconnect.com/Host#Access/All%20Machines%20by%20Company//{{agent.ScreenConnectGUID}}/Join
|
||||||
|
#>
|
||||||
|
|
||||||
|
param (
|
||||||
|
[string] $serviceName
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!$serviceName) {
|
||||||
|
write-output "Variable not specified ScreenConnectService, please create a global custom field under Client called ScreenConnectService, Example Value: `"ScreenConnect Client (1327465grctq84yrtocq)`" `n"
|
||||||
|
$ErrorCount += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$ErrorCount -eq 0) {
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$imagePath = Get-Itempropertyvalue "HKLM:\SYSTEM\ControlSet001\Services\$serviceName" -Name "ImagePath"
|
||||||
|
$imagePath2 = ($imagePath -split "&s=")[1]
|
||||||
|
$machineGUID = ($imagePath2 -split "&k=")[0]
|
||||||
|
Write-Output $machineGUID
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
# Needs to be parameterized: $icofile, $URL, $ShortcutPath
|
|
||||||
# Need to change paths and test/create if don't exist
|
|
||||||
|
|
||||||
|
|
||||||
wget "https://www.example.com/logos/example.ico" -outfile "c:\agent\example.ico"
|
|
||||||
|
|
||||||
$WshShell = New-Object -comObject WScript.Shell
|
|
||||||
$path = "C:\Users\All Users\desktop\example.url"
|
|
||||||
$targetpath = "https://example.com/"
|
|
||||||
$iconlocation = "c:\agent\example.ico"
|
|
||||||
$iconfile = "IconFile=" + $iconlocation
|
|
||||||
$Shortcut = $WshShell.CreateShortcut($path)
|
|
||||||
$Shortcut.TargetPath = $targetpath
|
|
||||||
$Shortcut.Save()
|
|
||||||
Add-Content $path "HotKey=0"
|
|
||||||
Add-Content $path "$iconfile"
|
|
||||||
Add-Content $path "IconIndex=0"
|
|
||||||
|
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
REM Print Spooler reset script. Will stop spooler, fix permissions on print folders, clear all files in print queues, and restart spooler service.
|
||||||
|
|
||||||
REM Stop Print Spooler
|
REM Stop Print Spooler
|
||||||
net stop "Spooler"
|
net stop "Spooler"
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
net stop "Print Spooler"
|
|
||||||
net start "Print Spooler"
|
|
||||||
25
scripts_wip/Win_Print_Spooler_Restart_Service.ps1
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<#
|
||||||
|
.Synopsis
|
||||||
|
Restart Print Spooler Service
|
||||||
|
.DESCRIPTION
|
||||||
|
Will force-restart the spooler service. With additional command parameter will also delete any pending print jobs
|
||||||
|
.EXAMPLE
|
||||||
|
Another example of how to use this cmdlet
|
||||||
|
.OUTPUTS
|
||||||
|
Any print jobs that are deleted
|
||||||
|
.NOTES
|
||||||
|
v1.0 5/2021
|
||||||
|
https://github.com/silversword411
|
||||||
|
.FUNCTIONALITY
|
||||||
|
Print Spooler Troubleshooting, restarts spooler service. Can also delete all print jobs that are pending
|
||||||
|
#>
|
||||||
|
|
||||||
|
#Restart Spooler service
|
||||||
|
Restart-Service -Name spooler -Force
|
||||||
|
|
||||||
|
#Deletes All print jobs within the last 15 years
|
||||||
|
$PrintJobs = get-wmiobject -class "Win32_PrintJob" -namespace "root\CIMV2" -computername . | Where-Object { [System.Management.ManagementDateTimeConverter]::ToDateTime($_.TimeSubmitted) -lt (Get-Date).AddDays(-5500) }
|
||||||
|
foreach ($job in $PrintJobs) {
|
||||||
|
# Write-Host "Canceling job $($job.JobId)"
|
||||||
|
$job.Delete()
|
||||||
|
}
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#Update with command parameters
|
|
||||||
#Deletes All print jobs within the last 2 days
|
|
||||||
|
|
||||||
$PrintJobs = get-wmiobject -class "Win32_PrintJob" -namespace "root\CIMV2" -computername . | Where-Object { [System.Management.ManagementDateTimeConverter]::ToDateTime($_.TimeSubmitted) -lt (Get-Date).AddDays(-2) }
|
|
||||||
foreach ($job in $PrintJobs) {
|
|
||||||
# Write-Host "Canceling job $($job.JobId)"
|
|
||||||
$job.Delete()
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
md -Path 'C:\agent' -Force
|
|
||||||
wget "http://www.yourwebsite.com/logos/yourico.ico" -outfile "c:\agent\yourico.ico"
|
|
||||||
|
mkdir -Path 'C:\agent' -Force
|
||||||
|
Invoke-WebRequest "http://www.yourwebsite.com/logos/yourico.ico" -outfile "c:\agent\yourico.ico"
|
||||||
$WshShell = New-Object -comObject WScript.Shell
|
$WshShell = New-Object -comObject WScript.Shell
|
||||||
$path = "C:\Users\All Users\desktop\Jaxsupport.url"
|
$path = "C:\Users\All Users\desktop\Shortcut.url"
|
||||||
$targetpath = "https://yourwebsite.com"
|
$targetpath = "https://yourwebsite.com"
|
||||||
$iconlocation = "c:\agent\yourico.ico"
|
$iconlocation = "c:\agent\yourico.ico"
|
||||||
$iconfile = "IconFile=" + $iconlocation
|
$iconfile = "IconFile=" + $iconlocation
|
||||||
|
|||||||
16
update.sh
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
SCRIPT_VERSION="121"
|
SCRIPT_VERSION="123"
|
||||||
SCRIPT_URL='https://raw.githubusercontent.com/wh1te909/tacticalrmm/master/update.sh'
|
SCRIPT_URL='https://raw.githubusercontent.com/wh1te909/tacticalrmm/master/update.sh'
|
||||||
LATEST_SETTINGS_URL='https://raw.githubusercontent.com/wh1te909/tacticalrmm/master/api/tacticalrmm/tacticalrmm/settings.py'
|
LATEST_SETTINGS_URL='https://raw.githubusercontent.com/wh1te909/tacticalrmm/master/api/tacticalrmm/tacticalrmm/settings.py'
|
||||||
YELLOW='\033[1;33m'
|
YELLOW='\033[1;33m'
|
||||||
@@ -184,14 +184,14 @@ if ! [[ $HAS_PY39 ]]; then
|
|||||||
sudo rm -rf Python-3.9.2 Python-3.9.2.tgz
|
sudo rm -rf Python-3.9.2 Python-3.9.2.tgz
|
||||||
fi
|
fi
|
||||||
|
|
||||||
HAS_NATS220=$(/usr/local/bin/nats-server -version | grep v2.2.3)
|
HAS_NATS220=$(/usr/local/bin/nats-server -version | grep v2.2.6)
|
||||||
if ! [[ $HAS_NATS220 ]]; then
|
if ! [[ $HAS_NATS220 ]]; then
|
||||||
printf >&2 "${GREEN}Updating nats to v2.2.3${NC}\n"
|
printf >&2 "${GREEN}Updating nats to v2.2.6${NC}\n"
|
||||||
nats_tmp=$(mktemp -d -t nats-XXXXXXXXXX)
|
nats_tmp=$(mktemp -d -t nats-XXXXXXXXXX)
|
||||||
wget https://github.com/nats-io/nats-server/releases/download/v2.2.3/nats-server-v2.2.3-linux-amd64.tar.gz -P ${nats_tmp}
|
wget https://github.com/nats-io/nats-server/releases/download/v2.2.6/nats-server-v2.2.6-linux-amd64.tar.gz -P ${nats_tmp}
|
||||||
tar -xzf ${nats_tmp}/nats-server-v2.2.3-linux-amd64.tar.gz -C ${nats_tmp}
|
tar -xzf ${nats_tmp}/nats-server-v2.2.6-linux-amd64.tar.gz -C ${nats_tmp}
|
||||||
sudo rm -f /usr/local/bin/nats-server
|
sudo rm -f /usr/local/bin/nats-server
|
||||||
sudo mv ${nats_tmp}/nats-server-v2.2.3-linux-amd64/nats-server /usr/local/bin/
|
sudo mv ${nats_tmp}/nats-server-v2.2.6-linux-amd64/nats-server /usr/local/bin/
|
||||||
sudo chmod +x /usr/local/bin/nats-server
|
sudo chmod +x /usr/local/bin/nats-server
|
||||||
sudo chown ${USER}:${USER} /usr/local/bin/nats-server
|
sudo chown ${USER}:${USER} /usr/local/bin/nats-server
|
||||||
rm -rf ${nats_tmp}
|
rm -rf ${nats_tmp}
|
||||||
@@ -307,5 +307,9 @@ if [[ "${CURRENT_MESH_VER}" != "${LATEST_MESH_VER}" ]] || [[ "$force" = true ]];
|
|||||||
sudo systemctl start meshcentral
|
sudo systemctl start meshcentral
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# apply redis configuration
|
||||||
|
sudo redis-cli config set appendonly yes
|
||||||
|
sudo redis-cli config rewrite
|
||||||
|
|
||||||
rm -f $TMP_SETTINGS
|
rm -f $TMP_SETTINGS
|
||||||
printf >&2 "${GREEN}Update finished!${NC}\n"
|
printf >&2 "${GREEN}Update finished!${NC}\n"
|
||||||
1996
web/package-lock.json
generated
@@ -10,33 +10,27 @@
|
|||||||
"test:e2e:ci": "cross-env E2E_TEST=true start-test \"quasar dev\" http-get://localhost:8080 \"cypress run\""
|
"test:e2e:ci": "cross-env E2E_TEST=true start-test \"quasar dev\" http-get://localhost:8080 \"cypress run\""
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@quasar/extras": "^1.10.4",
|
"@quasar/extras": "^1.10.6",
|
||||||
"apexcharts": "^3.23.1",
|
"apexcharts": "^3.23.1",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
"prismjs": "^1.22.0",
|
"prismjs": "^1.22.0",
|
||||||
"qrcode.vue": "^1.7.0",
|
"qrcode.vue": "^1.7.0",
|
||||||
"quasar": "^1.15.13",
|
"quasar": "^1.15.20",
|
||||||
"vue-apexcharts": "^1.6.0",
|
"vue-apexcharts": "^1.6.0",
|
||||||
"vue-prism-editor": "^1.2.2"
|
"vue-prism-editor": "^1.2.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@quasar/app": "^2.2.6",
|
"@quasar/app": "^2.2.10",
|
||||||
"@quasar/cli": "^1.1.3",
|
"@quasar/cli": "^1.2.1",
|
||||||
"core-js": "^3.11.2",
|
"core-js": "^3.14.0",
|
||||||
"eslint-plugin-cypress": "^2.11.2",
|
"eslint-plugin-cypress": "^2.11.2",
|
||||||
"flush-promises": "^1.0.2",
|
"flush-promises": "^1.0.2",
|
||||||
"fs-extra": "^9.1.0"
|
"fs-extra": "^9.1.0"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"last 4 Chrome versions",
|
"last 3 Chrome versions",
|
||||||
"last 4 Firefox versions",
|
"last 3 Firefox versions",
|
||||||
"last 2 Edge versions",
|
"last 2 Edge versions"
|
||||||
"last 3 Safari versions",
|
|
||||||
"last 3 Android versions",
|
|
||||||
"last 3 ChromeAndroid versions",
|
|
||||||
"last 3 FirefoxAndroid versions",
|
|
||||||
"last 3 iOS versions",
|
|
||||||
"last 2 Opera versions"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -261,6 +261,9 @@
|
|||||||
@click="eventLogMoreInfo(props.row)"
|
@click="eventLogMoreInfo(props.row)"
|
||||||
>Last Output</span
|
>Last Output</span
|
||||||
>
|
>
|
||||||
|
<span v-else-if="props.row.check_type === 'diskspace' || props.row.check_type === 'winsvc'">{{
|
||||||
|
props.row.more_info
|
||||||
|
}}</span>
|
||||||
</q-td>
|
</q-td>
|
||||||
<q-td>{{ props.row.last_run || "Never" }}</q-td>
|
<q-td>{{ props.row.last_run || "Never" }}</q-td>
|
||||||
<q-td v-if="props.row.assigned_task !== null && props.row.assigned_task.length > 1"
|
<q-td v-if="props.row.assigned_task !== null && props.row.assigned_task.length > 1"
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
@input="value => $emit('input', value)"
|
@input="value => $emit('input', value)"
|
||||||
:rules="[...validationRules]"
|
:rules="[...validationRules]"
|
||||||
reactive-rules
|
reactive-rules
|
||||||
|
autogrow
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<q-toggle
|
<q-toggle
|
||||||
|
|||||||
@@ -94,7 +94,7 @@
|
|||||||
<q-item-section>Global Settings</q-item-section>
|
<q-item-section>Global Settings</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
<!-- code sign -->
|
<!-- code sign -->
|
||||||
<q-item v-if="!noCodeSigning" clickable v-close-popup @click="showCodeSign = true">
|
<q-item v-if="!hosted" clickable v-close-popup @click="showCodeSign = true">
|
||||||
<q-item-section>Code Signing</q-item-section>
|
<q-item-section>Code Signing</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
</q-list>
|
</q-list>
|
||||||
@@ -124,7 +124,7 @@
|
|||||||
</q-menu>
|
</q-menu>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
<!-- help -->
|
<!-- help -->
|
||||||
<q-btn size="md" dense no-caps flat label="Help">
|
<q-btn v-if="!hosted" size="md" dense no-caps flat label="Help">
|
||||||
<q-menu auto-close>
|
<q-menu auto-close>
|
||||||
<q-list dense style="min-width: 100px">
|
<q-list dense style="min-width: 100px">
|
||||||
<q-item clickable v-close-popup @click="openHelp('docs')">
|
<q-item clickable v-close-popup @click="openHelp('docs')">
|
||||||
@@ -272,8 +272,8 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
noCodeSigning() {
|
hosted() {
|
||||||
return this.$store.state.noCodeSign;
|
return this.$store.state.hosted;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ export default {
|
|||||||
getOptions() {
|
getOptions() {
|
||||||
this.getClients();
|
this.getClients();
|
||||||
this.getSites();
|
this.getSites();
|
||||||
this.agentOptions = Object.freeze(this.getAgentOptions());
|
this.agentOptions = this.getAgentOptions();
|
||||||
},
|
},
|
||||||
show() {
|
show() {
|
||||||
this.$refs.dialog.show();
|
this.$refs.dialog.show();
|
||||||
@@ -152,7 +152,7 @@ export default {
|
|||||||
this.hide();
|
this.hide();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
created() {
|
||||||
this.getOptions();
|
this.getOptions();
|
||||||
|
|
||||||
// copy prop data locally
|
// copy prop data locally
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ export default {
|
|||||||
getOptions() {
|
getOptions() {
|
||||||
this.getClients();
|
this.getClients();
|
||||||
this.getSites();
|
this.getSites();
|
||||||
this.agentOptions = Object.freeze(this.getAgentOptions());
|
this.agentOptions = this.getAgentOptions();
|
||||||
},
|
},
|
||||||
show() {
|
show() {
|
||||||
this.$refs.dialog.show();
|
this.$refs.dialog.show();
|
||||||
@@ -159,7 +159,7 @@ export default {
|
|||||||
this.hide();
|
this.hide();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
created() {
|
||||||
this.getOptions();
|
this.getOptions();
|
||||||
|
|
||||||
// copy prop data locally
|
// copy prop data locally
|
||||||
|
|||||||
@@ -111,6 +111,7 @@
|
|||||||
dense
|
dense
|
||||||
options-dense
|
options-dense
|
||||||
outlined
|
outlined
|
||||||
|
clearable
|
||||||
v-model="template.action"
|
v-model="template.action"
|
||||||
:options="scriptOptions"
|
:options="scriptOptions"
|
||||||
map-options
|
map-options
|
||||||
@@ -174,6 +175,7 @@
|
|||||||
dense
|
dense
|
||||||
options-dense
|
options-dense
|
||||||
outlined
|
outlined
|
||||||
|
clearable
|
||||||
v-model="template.resolved_action"
|
v-model="template.resolved_action"
|
||||||
:options="scriptOptions"
|
:options="scriptOptions"
|
||||||
map-options
|
map-options
|
||||||
@@ -696,4 +698,4 @@ export default {
|
|||||||
if (this.editing) Object.assign(this.template, this.alertTemplate);
|
if (this.editing) Object.assign(this.template, this.alertTemplate);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
stack-label
|
stack-label
|
||||||
filled
|
filled
|
||||||
counter
|
counter
|
||||||
|
class="full-width"
|
||||||
accept=".exe"
|
accept=".exe"
|
||||||
>
|
>
|
||||||
<template v-slot:prepend>
|
<template v-slot:prepend>
|
||||||
|
|||||||
@@ -138,6 +138,7 @@
|
|||||||
v-model="localField.default_value_string"
|
v-model="localField.default_value_string"
|
||||||
:rules="[...defaultValueRules]"
|
:rules="[...defaultValueRules]"
|
||||||
reactive-rules
|
reactive-rules
|
||||||
|
autogrow
|
||||||
/>
|
/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
stack-label
|
stack-label
|
||||||
filled
|
filled
|
||||||
counter
|
counter
|
||||||
|
class="full-width"
|
||||||
accept=".ps1, .bat, .py"
|
accept=".ps1, .bat, .py"
|
||||||
>
|
>
|
||||||
<template v-slot:prepend>
|
<template v-slot:prepend>
|
||||||
|
|||||||
@@ -73,7 +73,12 @@
|
|||||||
label="Collector Task"
|
label="Collector Task"
|
||||||
v-model="collector"
|
v-model="collector"
|
||||||
class="q-pb-sm"
|
class="q-pb-sm"
|
||||||
@input="autotask.custom_field = null"
|
@input="
|
||||||
|
() => {
|
||||||
|
autotask.custom_field = null;
|
||||||
|
autotask.collector_all_ouput = false;
|
||||||
|
}
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
<q-select
|
<q-select
|
||||||
v-if="collector"
|
v-if="collector"
|
||||||
@@ -87,6 +92,13 @@
|
|||||||
options-dense
|
options-dense
|
||||||
hint="The last line of script output will be saved to custom field selected"
|
hint="The last line of script output will be saved to custom field selected"
|
||||||
/>
|
/>
|
||||||
|
<q-checkbox
|
||||||
|
v-if="collector"
|
||||||
|
dense
|
||||||
|
label="Save all output (Only for text area)"
|
||||||
|
v-model="autotask.collector_all_output"
|
||||||
|
class="q-py-sm"
|
||||||
|
/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-select
|
<q-select
|
||||||
@@ -229,6 +241,7 @@ export default {
|
|||||||
task_type: "scheduled",
|
task_type: "scheduled",
|
||||||
timeout: 120,
|
timeout: 120,
|
||||||
alert_severity: "info",
|
alert_severity: "info",
|
||||||
|
collector_all_output: false,
|
||||||
},
|
},
|
||||||
policyChecks: [],
|
policyChecks: [],
|
||||||
severityOptions: [
|
severityOptions: [
|
||||||
|
|||||||
@@ -90,6 +90,13 @@
|
|||||||
options-dense
|
options-dense
|
||||||
hint="The return value of script will be saved to custom field selected"
|
hint="The return value of script will be saved to custom field selected"
|
||||||
/>
|
/>
|
||||||
|
<q-checkbox
|
||||||
|
v-if="collector"
|
||||||
|
dense
|
||||||
|
label="Save all output (Only for text area)"
|
||||||
|
v-model="autotask.collector_all_output"
|
||||||
|
class="q-py-sm"
|
||||||
|
/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-input
|
<q-input
|
||||||
@@ -131,6 +138,7 @@ export default {
|
|||||||
alert_severity: null,
|
alert_severity: null,
|
||||||
timeout: 120,
|
timeout: 120,
|
||||||
custom_field: null,
|
custom_field: null,
|
||||||
|
collector_all_output: false,
|
||||||
},
|
},
|
||||||
collector: false,
|
collector: false,
|
||||||
customFieldOptions: [],
|
customFieldOptions: [],
|
||||||
@@ -197,6 +205,7 @@ export default {
|
|||||||
this.autotask.alert_severity = this.task.alert_severity;
|
this.autotask.alert_severity = this.task.alert_severity;
|
||||||
this.autotask.timeout = this.task.timeout;
|
this.autotask.timeout = this.task.timeout;
|
||||||
this.autotask.custom_field = this.task.custom_field;
|
this.autotask.custom_field = this.task.custom_field;
|
||||||
|
this.autotask.collector_all_output = this.task.collector_all_output;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@@ -72,18 +72,18 @@ export default {
|
|||||||
|
|
||||||
isValidThreshold(warning, error, diskcheck = false) {
|
isValidThreshold(warning, error, diskcheck = false) {
|
||||||
if (warning === 0 && error === 0) {
|
if (warning === 0 && error === 0) {
|
||||||
Notify.create(notifyErrorConfig("Warning Threshold or Error Threshold need to be set", 2000));
|
Notify.create({ type: "negative", timeout: 2000, message: "Warning Threshold or Error Threshold need to be set" });
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!diskcheck && warning > error && warning > 0 && error > 0) {
|
if (!diskcheck && warning > error && warning > 0 && error > 0) {
|
||||||
Notify.create(notifyErrorConfig("Warning Threshold must be less than Error Threshold", 2000));
|
Notify.create({ type: "negative", timeout: 2000, message: "Warning Threshold must be less than Error Threshold" });
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (diskcheck && warning < error && warning > 0 && error > 0) {
|
if (diskcheck && warning < error && warning > 0 && error > 0) {
|
||||||
Notify.create(notifyErrorConfig("Warning Threshold must be more than Error Threshold", 2000));
|
Notify.create({ type: "negative", timeout: 2000, message: "Warning Threshold must be more than Error Threshold" });
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export default function () {
|
|||||||
defaultAgentTblTab: "server",
|
defaultAgentTblTab: "server",
|
||||||
clientTreeSort: "alphafail",
|
clientTreeSort: "alphafail",
|
||||||
clientTreeSplitter: 11,
|
clientTreeSplitter: 11,
|
||||||
noCodeSign: false,
|
hosted: false,
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
clientTreeSplitterModel(state) {
|
clientTreeSplitterModel(state) {
|
||||||
@@ -159,8 +159,8 @@ export default function () {
|
|||||||
SET_CLIENT_TREE_SORT(state, val) {
|
SET_CLIENT_TREE_SORT(state, val) {
|
||||||
state.clientTreeSort = val
|
state.clientTreeSort = val
|
||||||
},
|
},
|
||||||
SET_NO_CODE_SIGN(state, val) {
|
SET_HOSTED(state, val) {
|
||||||
state.noCodeSign = val
|
state.hosted = val
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
|||||||
@@ -742,7 +742,7 @@ export default {
|
|||||||
this.$store.commit("SET_AGENT_DBLCLICK_ACTION", r.data.dbl_click_action);
|
this.$store.commit("SET_AGENT_DBLCLICK_ACTION", r.data.dbl_click_action);
|
||||||
this.$store.commit("SET_URL_ACTION", r.data.url_action);
|
this.$store.commit("SET_URL_ACTION", r.data.url_action);
|
||||||
this.$store.commit("setShowCommunityScripts", r.data.show_community_scripts);
|
this.$store.commit("setShowCommunityScripts", r.data.show_community_scripts);
|
||||||
this.$store.commit("SET_NO_CODE_SIGN", r.data.no_code_sign);
|
this.$store.commit("SET_HOSTED", r.data.hosted);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
showToggleMaintenance(node) {
|
showToggleMaintenance(node) {
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
stack-label
|
stack-label
|
||||||
filled
|
filled
|
||||||
counter
|
counter
|
||||||
|
class="full-width"
|
||||||
accept=".exe"
|
accept=".exe"
|
||||||
>
|
>
|
||||||
<template v-slot:prepend>
|
<template v-slot:prepend>
|
||||||
|
|||||||