Skip to content

Commit

Permalink
Merge pull request #1676 from NiceGuyIT/feature/cross-platform-scripting
Browse files Browse the repository at this point in the history
[Feature] Add cross site scripting
  • Loading branch information
wh1te909 authored Feb 22, 2024
2 parents fe1e71d + 4ac1030 commit ac7642c
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 4 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Demo database resets every hour. A lot of features are disabled for obvious reas
- Teamviewer-like remote desktop control
- Real-time remote shell
- Remote file browser (download and upload files)
- Remote command and script execution (batch, powershell and python scripts)
- Remote command and script execution (batch, powershell, python, nushell and deno scripts)
- Event log viewer
- Services management
- Windows patch management
Expand Down
2 changes: 2 additions & 0 deletions api/tacticalrmm/agents/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,8 @@ def run_script(
},
"run_as_user": run_as_user,
"env_vars": parsed_env_vars,
"nushell_enable_config": settings.NUSHELL_ENABLE_CONFIG,
"deno_default_permissions": settings.DENO_DEFAULT_PERMISSIONS,
}

if history_pk != 0:
Expand Down
4 changes: 4 additions & 0 deletions api/tacticalrmm/alerts/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1429,6 +1429,8 @@ def test_alert_actions(
"run_as_user": False,
"env_vars": ["hello=world", "foo=bar"],
"id": AgentHistory.objects.last().pk, # type: ignore
"nushell_enable_config": settings.NUSHELL_ENABLE_CONFIG,
"deno_default_permissions": settings.DENO_DEFAULT_PERMISSIONS,
}

nats_cmd.assert_called_with(data, timeout=30, wait=True)
Expand Down Expand Up @@ -1460,6 +1462,8 @@ def test_alert_actions(
"run_as_user": False,
"env_vars": ["resolved=action", "env=vars"],
"id": AgentHistory.objects.last().pk, # type: ignore
"nushell_enable_config": settings.NUSHELL_ENABLE_CONFIG,
"deno_default_permissions": settings.DENO_DEFAULT_PERMISSIONS,
}

nats_cmd.assert_called_with(data, timeout=35, wait=True)
Expand Down
8 changes: 8 additions & 0 deletions api/tacticalrmm/apiv3/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,12 @@ def get_agent_config() -> AgentCheckInConfig:
*getattr(settings, "CHECKIN_SYNCMESH", (800, 1200))
),
limit_data=getattr(settings, "LIMIT_DATA", False),
install_nushell=getattr(settings, "INSTALL_NUSHELL", False),
install_nushell_version=getattr(settings, "INSTALL_NUSHELL_VERSION", ""),
install_nushell_url=getattr(settings, "INSTALL_NUSHELL_URL", ""),
nushell_enable_config=getattr(settings, "NUSHELL_ENABLE_CONFIG", False),
install_deno=getattr(settings, "INSTALL_DENO", False),
install_deno_version=getattr(settings, "INSTALL_DENO_VERSION", ""),
install_deno_url=getattr(settings, "INSTALL_DENO_URL", ""),
deno_default_permissions=getattr(settings, "DENO_DEFAULT_PERMISSIONS", ""),
)
3 changes: 3 additions & 0 deletions api/tacticalrmm/autotasks/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from django.utils import timezone as djangotime
from rest_framework import serializers
from django.conf import settings

from scripts.models import Script
from tacticalrmm.constants import TaskType
Expand Down Expand Up @@ -257,6 +258,8 @@ def get_task_actions(self, obj):
shell=script.shell,
env_vars=env_vars,
),
"nushell_enable_config": settings.NUSHELL_ENABLE_CONFIG,
"deno_default_permissions": settings.DENO_DEFAULT_PERMISSIONS,
}
)
if actions_to_remove:
Expand Down
13 changes: 10 additions & 3 deletions api/tacticalrmm/core/agent_linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ agentBin="${agentBinPath}/${binName}"
agentConf='/etc/tacticalagent'
agentSvcName='tacticalagent.service'
agentSysD="/etc/systemd/system/${agentSvcName}"
agentDir='/opt/tacticalagent'
meshDir='/opt/tacticalmesh'
meshSystemBin="${meshDir}/meshagent"
meshSvcName='meshagent.service'
Expand All @@ -65,16 +66,20 @@ RemoveOldAgent() {
if [ -f "${agentSysD}" ]; then
systemctl disable ${agentSvcName}
systemctl stop ${agentSvcName}
rm -f ${agentSysD}
rm -f "${agentSysD}"
systemctl daemon-reload
fi

if [ -f "${agentConf}" ]; then
rm -f ${agentConf}
rm -f "${agentConf}"
fi

if [ -f "${agentBin}" ]; then
rm -f ${agentBin}
rm -f "${agentBin}"
fi

if [ -d "${agentDir}" ]; then
rm -rf "${agentDir}"
fi
}

Expand Down Expand Up @@ -134,6 +139,8 @@ Uninstall() {

if [ $# -ne 0 ] && [ $1 == 'uninstall' ]; then
Uninstall
# Remove the current script
rm "$0"
exit 0
fi

Expand Down
4 changes: 4 additions & 0 deletions api/tacticalrmm/scripts/tasks.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import asyncio

from django.conf import settings

from agents.models import Agent, AgentHistory
from scripts.models import Script
from tacticalrmm.celery import app
Expand Down Expand Up @@ -78,6 +80,8 @@ def bulk_script_task(
},
"run_as_user": run_as_user,
"env_vars": script.parse_script_env_vars(agent, script.shell, env_vars),
"nushell_enable_config": settings.NUSHELL_ENABLE_CONFIG,
"deno_default_permissions": settings.DENO_DEFAULT_PERMISSIONS,
}
tup = (agent.agent_id, data)
items.append(tup)
Expand Down
7 changes: 7 additions & 0 deletions api/tacticalrmm/scripts/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from django.conf import settings

from agents.permissions import RunScriptPerms
from tacticalrmm.constants import ScriptShell, ScriptType
Expand Down Expand Up @@ -162,6 +163,8 @@ def post(self, request, agent_id):
},
"run_as_user": request.data["run_as_user"],
"env_vars": parsed_env_vars,
"nushell_enable_config": settings.NUSHELL_ENABLE_CONFIG,
"deno_default_permissions": settings.DENO_DEFAULT_PERMISSIONS,
}

r = asyncio.run(
Expand Down Expand Up @@ -190,6 +193,10 @@ def download(request, pk):
ext = ".py"
case ScriptShell.SHELL:
ext = ".sh"
case ScriptShell.NUSHELL:
ext = ".nu"
case ScriptShell.DENO:
ext = ".ts"
case _:
ext = ""

Expand Down
2 changes: 2 additions & 0 deletions api/tacticalrmm/tacticalrmm/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ class ScriptShell(models.TextChoices):
CMD = "cmd", "Batch (CMD)"
PYTHON = "python", "Python"
SHELL = "shell", "Shell"
NUSHELL = "nushell", "Nushell"
DENO = "deno", "Deno"


class ScriptType(models.TextChoices):
Expand Down
43 changes: 43 additions & 0 deletions api/tacticalrmm/tacticalrmm/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,49 @@

NATS_SERVER_VER = "2.10.11"

# Install Nushell on the agent
# https://github.com/nushell/nushell
INSTALL_NUSHELL = False
# GitHub version to download. The file will be downloaded from GitHub, extracted and installed.
# Version to download. If INSTALL_NUSHELL_URL is not provided, the file will be downloaded from GitHub,
# extracted and installed.
INSTALL_NUSHELL_VERSION = ""
# URL to download directly. This is expected to be the direct URL, unauthenticated, uncompressed, ready to be installed.
# Use {OS}, {ARCH} and {VERSION} to specify the GOOS, GOARCH and INSTALL_NUSHELL_VERSION respectively.
# Windows: The ".exe" extension will be added automatically.
# Examples:
# https://examplle.com/download/nushell/{OS}/{ARCH}/{VERSION}/nu
# https://examplle.com/download/nushell/nu-{VERSION}-{OS}-{ARCH}
INSTALL_NUSHELL_URL = ""
# Enable Nushell config on the agent
# The default is to not enable the config because it could change how scripts run.
# However, disabling the config prevents plugins from being registered.
# https://github.com/nushell/nushell/issues/10754
# False: --no-config-file option is added to the command line.
# True: --config and --env-config options are added to the command line and point to the Agent's directory.
NUSHELL_ENABLE_CONFIG = False

# Install Deno on the agent
# https://github.com/denoland/deno
INSTALL_DENO = False
# Version to download. If INSTALL_DENO_URL is not provided, the file will be downloaded from GitHub,
# extracted and installed.
INSTALL_DENO_VERSION = ""
# URL to download directly. This is expected to be the direct URL, unauthenticated, uncompressed, ready to be installed.
# Use {OS}, {ARCH} and {VERSION} to specify the GOOS, GOARCH and INSTALL_DENO_VERSION respectively.
# Windows: The ".exe" extension will be added automatically.
# Examples:
# https://examplle.com/download/deno/{OS}/{ARCH}/{VERSION}/deno
# https://examplle.com/download/deno/deno-{VERSION}-{OS}-{ARCH}
INSTALL_DENO_URL = ""
# Default permissions for Deno
# Space separated list of permissions as listed in the documentation.
# https://docs.deno.com/runtime/manual/basics/permissions#permissions
# Examples:
# DENO_DEFAULT_PERMISSIONS = "--allow-sys --allow-net --allow-env"
# DENO_DEFAULT_PERMISSIONS = "--allow-all"
DENO_DEFAULT_PERMISSIONS = ""

# for the update script, bump when need to recreate venv
PIP_VER = "42"

Expand Down
8 changes: 8 additions & 0 deletions api/tacticalrmm/tacticalrmm/structs.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,11 @@ class AgentCheckInConfig(TRMMStruct):
checkin_wmi: int
checkin_syncmesh: int
limit_data: bool
install_nushell: bool
install_nushell_version: str
install_nushell_url: str
nushell_enable_config: bool
install_deno: bool
install_deno_version: str
install_deno_url: str
deno_default_permissions: str

0 comments on commit ac7642c

Please sign in to comment.