diff --git a/api/tacticalrmm/agents/tasks.py b/api/tacticalrmm/agents/tasks.py index df3a669b88..b2ea94a19e 100644 --- a/api/tacticalrmm/agents/tasks.py +++ b/api/tacticalrmm/agents/tasks.py @@ -11,7 +11,7 @@ from packaging import version as pyver from agents.models import Agent -from core.models import CoreSettings, CodeSignToken +from core.models import CodeSignToken, CoreSettings from logs.models import PendingAction from scripts.models import Script from tacticalrmm.celery import app diff --git a/api/tacticalrmm/agents/utils.py b/api/tacticalrmm/agents/utils.py index 6180fedc23..1c7f3583db 100644 --- a/api/tacticalrmm/agents/utils.py +++ b/api/tacticalrmm/agents/utils.py @@ -1,7 +1,7 @@ import random -import requests import urllib.parse +import requests from django.conf import settings diff --git a/api/tacticalrmm/agents/views.py b/api/tacticalrmm/agents/views.py index 1c7185685c..972aa77ae9 100644 --- a/api/tacticalrmm/agents/views.py +++ b/api/tacticalrmm/agents/views.py @@ -353,9 +353,10 @@ def patch(self, request): @api_view(["POST"]) def install_agent(request): - from agents.utils import get_winagent_url from knox.models import AuthToken + from agents.utils import get_winagent_url + client_id = request.data["client"] site_id = request.data["site"] version = settings.LATEST_AGENT_VER diff --git a/api/tacticalrmm/clients/models.py b/api/tacticalrmm/clients/models.py index facaa2c9ff..520f51e3b6 100644 --- a/api/tacticalrmm/clients/models.py +++ b/api/tacticalrmm/clients/models.py @@ -65,6 +65,10 @@ class Meta: def __str__(self): return self.name + @property + def agent_count(self) -> int: + return Agent.objects.filter(site__client=self).count() + @property def has_maintenanace_mode_agents(self): return ( @@ -173,6 +177,10 @@ class Meta: def __str__(self): return self.name + @property + def agent_count(self) -> int: + return Agent.objects.filter(site=self).count() + @property def has_maintenanace_mode_agents(self): return Agent.objects.filter(site=self, maintenance_mode=True).count() > 0 diff --git a/api/tacticalrmm/clients/serializers.py b/api/tacticalrmm/clients/serializers.py index 7244be11a9..edbd151f73 100644 --- a/api/tacticalrmm/clients/serializers.py +++ b/api/tacticalrmm/clients/serializers.py @@ -25,6 +25,7 @@ class Meta: class SiteSerializer(ModelSerializer): client_name = ReadOnlyField(source="client.name") custom_fields = SiteCustomFieldSerializer(many=True, read_only=True) + agent_count = ReadOnlyField() class Meta: model = Site @@ -37,6 +38,7 @@ class Meta: "client_name", "client", "custom_fields", + "agent_count", ) def validate(self, val): @@ -68,6 +70,7 @@ class Meta: class ClientSerializer(ModelSerializer): sites = SiteSerializer(many=True, read_only=True) custom_fields = ClientCustomFieldSerializer(many=True, read_only=True) + agent_count = ReadOnlyField() class Meta: model = Client @@ -79,6 +82,7 @@ class Meta: "alert_template", "sites", "custom_fields", + "agent_count", ) def validate(self, val): diff --git a/api/tacticalrmm/core/admin.py b/api/tacticalrmm/core/admin.py index 41a49099b2..301efd0964 100644 --- a/api/tacticalrmm/core/admin.py +++ b/api/tacticalrmm/core/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -from .models import CoreSettings, CustomField, CodeSignToken +from .models import CodeSignToken, CoreSettings, CustomField admin.site.register(CoreSettings) admin.site.register(CustomField) diff --git a/api/tacticalrmm/core/installer.ps1 b/api/tacticalrmm/core/installer.ps1 index eb6f3533b5..b0b15bdb71 100644 --- a/api/tacticalrmm/core/installer.ps1 +++ b/api/tacticalrmm/core/installer.ps1 @@ -9,6 +9,7 @@ $rdp = rdpchange $ping = pingchange $auth = '"tokenchange"' $downloadlink = 'downloadchange' +$apilink = $downloadlink.split('/') [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 @@ -47,24 +48,35 @@ If (Get-Service $serviceName -ErrorAction SilentlyContinue) { # pass } - Try - { - Invoke-WebRequest -Uri $downloadlink -OutFile $OutPath\$output - Start-Process -FilePath $OutPath\$output -ArgumentList ('/VERYSILENT /SUPPRESSMSGBOXES') -Wait - write-host ('Extracting...') - Start-Sleep -s 5 - Start-Process -FilePath "C:\Program Files\TacticalAgent\tacticalrmm.exe" -ArgumentList $installArgs -Wait - exit 0 - } - Catch - { - $ErrorMessage = $_.Exception.Message - $FailedItem = $_.Exception.ItemName - Write-Error -Message "$ErrorMessage $FailedItem" - exit 1 - } - Finally - { - Remove-Item -Path $OutPath\$output + $X = 0 + do { + Write-Output "Waiting for network" + Start-Sleep -s 5 + $X += 1 + } until(($connectreult = Test-NetConnection $apilink[2] -Port 443 | ? { $_.TcpTestSucceeded }) -or $X -eq 3) + + if ($connectreult.TcpTestSucceeded -eq $true){ + Try + { + Invoke-WebRequest -Uri $downloadlink -OutFile $OutPath\$output + Start-Process -FilePath $OutPath\$output -ArgumentList ('/VERYSILENT /SUPPRESSMSGBOXES') -Wait + write-host ('Extracting...') + Start-Sleep -s 5 + Start-Process -FilePath "C:\Program Files\TacticalAgent\tacticalrmm.exe" -ArgumentList $installArgs -Wait + exit 0 + } + Catch + { + $ErrorMessage = $_.Exception.Message + $FailedItem = $_.Exception.ItemName + Write-Error -Message "$ErrorMessage $FailedItem" + exit 1 + } + Finally + { + Remove-Item -Path $OutPath\$output + } + } else { + Write-Output "Unable to connect to server" } } diff --git a/api/tacticalrmm/core/serializers.py b/api/tacticalrmm/core/serializers.py index 0872593f3e..7d2f6eb062 100644 --- a/api/tacticalrmm/core/serializers.py +++ b/api/tacticalrmm/core/serializers.py @@ -1,7 +1,7 @@ import pytz from rest_framework import serializers -from .models import CoreSettings, CustomField, CodeSignToken +from .models import CodeSignToken, CoreSettings, CustomField class CoreSettingsSerializer(serializers.ModelSerializer): diff --git a/api/tacticalrmm/core/tests.py b/api/tacticalrmm/core/tests.py index fddb157195..193a93e6ed 100644 --- a/api/tacticalrmm/core/tests.py +++ b/api/tacticalrmm/core/tests.py @@ -1,6 +1,6 @@ -import requests from unittest.mock import patch +import requests from channels.db import database_sync_to_async from channels.testing import WebsocketCommunicator from model_bakery import baker diff --git a/api/tacticalrmm/core/views.py b/api/tacticalrmm/core/views.py index 5254df3e25..a126468350 100644 --- a/api/tacticalrmm/core/views.py +++ b/api/tacticalrmm/core/views.py @@ -11,11 +11,11 @@ from tacticalrmm.utils import notify_error -from .models import CoreSettings, CustomField, CodeSignToken +from .models import CodeSignToken, CoreSettings, CustomField from .serializers import ( + CodeSignTokenSerializer, CoreSettingsSerializer, CustomFieldSerializer, - CodeSignTokenSerializer, ) @@ -71,6 +71,7 @@ def dashboard_info(request): "client_tree_sort": request.user.client_tree_sort, "client_tree_splitter": request.user.client_tree_splitter, "loading_bar_color": request.user.loading_bar_color, + "no_code_sign": hasattr(settings, "NOCODESIGN") and settings.NOCODESIGN, } ) diff --git a/api/tacticalrmm/scripts/community_scripts.json b/api/tacticalrmm/scripts/community_scripts.json index 9a644cb275..b456f94d3e 100644 --- a/api/tacticalrmm/scripts/community_scripts.json +++ b/api/tacticalrmm/scripts/community_scripts.json @@ -1,7 +1,7 @@ [ { "guid": "6820cb5e-5a7f-4d9b-8c22-d54677e3cc04", - "filename": "Win_Clear_Firefox_Cache.ps1", + "filename": "Win_Firefox_Clear_Cache.ps1", "submittedBy": "https://github.com/Omnicef", "name": "Firefox - Clean Cache", "description": "This script will clean up Mozilla Firefox for all users.", @@ -10,7 +10,7 @@ }, { "guid": "3ff6a386-11d1-4f9d-8cca-1b0563bb6443", - "filename": "Win_Clear_Google_Chrome_Cache.ps1", + "filename": "Win_Google_Chrome_Clear_Cache.ps1", "submittedBy": "https://github.com/Omnicef", "name": "Chrome - Clear Cache for All Users", "description": "This script will clean up Google Chrome for all users.", @@ -82,7 +82,7 @@ }, { "guid": "9d34f482-1f0c-4b2f-b65f-a9cf3c13ef5f", - "filename": "Win_Rename_Installed_App.ps1", + "filename": "Win_TRMM_Rename_Installed_App.ps1", "submittedBy": "https://github.com/bradhawkins85", "name": "TacticalRMM Agent Rename", "description": "Updates the DisplayName registry entry for the Tactical RMM windows agent to your desired name. This script takes 1 required argument: the name you wish to set.", @@ -154,7 +154,7 @@ }, { "guid": "95a2ee6f-b89b-4551-856e-3081b041caa7", - "filename": "Win_Reset_High_Performance_Power_Profile_to_Defaults.ps1", + "filename": "Win_Power_Profile_Reset_High_Performance_to_Defaults.ps1", "submittedBy": "https://github.com/azulskyknight", "name": "Power Profile - Reset High Perf Power Profile to defaults", "description": "Resets monitor, disk, standby, and hibernate timers in the default High Performance power profile to their default values. It also re-indexes the AC and DC power profiles into their default order.", @@ -163,7 +163,7 @@ }, { "guid": "2cbd30b0-84dd-4388-a36d-2e2e980f1a3e", - "filename": "Win_Set_High_Performance_Power_Profile.ps1", + "filename": "Win_Power_Profile_Set_High_Performance.ps1", "submittedBy": "https://github.com/azulskyknight", "name": "Power Profile - Set High Performance", "description": "Sets the High Performance Power profile to the active power profile. Use this to keep machines from falling asleep.", @@ -192,7 +192,7 @@ "guid": "7c14beb4-d1c3-41aa-8e70-92a267d6e080", "filename": "Win_Duplicati_Status.ps1", "submittedBy": "https://github.com/dinger1986", - "name": "Duplicati - Check", + "name": "Duplicati - Check Status", "description": "Checks Duplicati Backup is running properly over the last 24 hours", "shell": "powershell", "category": "TRMM (Win):3rd Party Software" @@ -262,13 +262,23 @@ }, { "guid": "d980fda3-a068-47eb-8495-1aab07a24e64", - "filename": "Win_Defender_Status.ps1", + "filename": "Win_Defender_Status_Report_Last24hrs.ps1", "submittedBy": "https://github.com/dinger1986", - "name": "Defender - Status", - "description": "This will check for Malware, Antispyware, that Windows Defender is Healthy, last scan etc within the last 24 hours", + "name": "Defender - Status Report Last 24hr", + "description": "Using Event Viewer, this will check for Malware and Antispyware within the last 24 hours and display, otherwise will report as Healthy", "shell": "powershell", "category": "TRMM (Win):Security>Antivirus" }, + { + "guid": "6a0202fc-1b27-4905-95c0-0a03bb881893", + "filename": "Win_Defender_Status_Report_LastYear.ps1", + "submittedBy": "https://github.com/silversword411", + "name": "Defender - Status Report Last Year", + "description": "Using Event Viewer, this will check for Malware and Antispyware and display, otherwise will report as Healthy", + "shell": "powershell", + "category": "TRMM (Win):Security>Antivirus", + "default_timeout": "300" + }, { "guid": "9956e936-6fdb-4488-a9d8-8b274658037f", "filename": "Win_Disable_Fast_Startup.bat", @@ -289,7 +299,7 @@ }, { "guid": "2472bbaf-1941-4722-8a58-d1dd0f528801", - "filename": "Win_Update_Tactical_Exclusion.ps1", + "filename": "Win_TRMM_AV_Update_Exclusion.ps1", "submittedBy": "https://github.com/dinger1986", "name": "TRMM Defender Exclusions", "description": "Windows Defender Exclusions for Tactical RMM", @@ -389,19 +399,10 @@ }, { "guid": "f396dae2-c768-45c5-bd6c-176e56ed3614", - "filename": "Win_Finish_updates_and_restart.ps1", + "filename": "Win_Power_RestartorShutdown.ps1", "submittedBy": "https://github.com/tremor021", - "name": "Updates - Finish and restart", - "description": "Finish installing Windows updates and restart PC", - "shell": "powershell", - "category": "TRMM (Win):Updates" - }, - { - "guid": "63f89be0-a9c9-4c61-9b55-bce0b28b90b2", - "filename": "Win_Finish_updates_and_shutdown.ps1", - "submittedBy": "https://github.com/tremor021", - "name": "Updates - Finish and Shutdown", - "description": "Finish installing Windows updates and shutdown PC", + "name": "Power - Restart or Shutdown PC", + "description": "Restart PC. Add parameter: shutdown if you want to shutdown computer", "shell": "powershell", "category": "TRMM (Win):Updates" }, @@ -422,7 +423,7 @@ }, { "guid": "3abbb62a-3757-492c-8979-b4fc6174845d", - "filename": "Win_Disable_AutoRun.bat", + "filename": "Win_AutoRun_Disable.bat", "submittedBy": "https://github.com/silversword411", "name": "Autorun - Disable", "description": "Disable Autorun System Wide", @@ -432,7 +433,7 @@ }, { "guid": "4a11877a-7555-494c-ac74-29d6df3c1989", - "filename": "Win_Disable_Cortana.bat", + "filename": "Win_Cortana_Disable.bat", "submittedBy": "https://github.com/silversword411", "name": "Cortana - Disable", "description": "Disable Cortana System Wide", @@ -444,7 +445,7 @@ "guid": "28ef1387-dd4f-4bab-b042-26250914e370", "filename": "Win_WOL_Enable_Status.ps1", "submittedBy": "https://github.com/silversword411", - "name": "Network WoL - Enable function", + "name": "BROKEN Network WoL - Enable function", "description": "Wake on Lan enable on Dell, HP, Lenovo", "shell": "powershell", "category": "TRMM (Win):Network", @@ -454,7 +455,7 @@ "guid": "685d5432-0b84-46d5-98e8-3ec2054150fe", "filename": "Win_WOL_Test_State.ps1", "submittedBy": "https://github.com/silversword411", - "name": "Network WoL - Test State", + "name": "BROKEN Network WoL - Test State", "description": "Wake on Lan test status", "shell": "powershell", "category": "TRMM (Win):Network", @@ -470,6 +471,26 @@ "category": "TRMM (Win):Network", "default_timeout": "90" }, + { + "guid": "745bb7cd-b71a-4f2e-b6f2-c579b1828162", + "filename": "Win_Network_DHCP_Set.bat", + "submittedBy": "https://github.com/silversword411", + "name": "Network - Set Primary NIC to DHCP", + "description": "Enable DHCP on primary adapter", + "shell": "cmd", + "category": "TRMM (Win):Network", + "default_timeout": "90" + }, + { + "guid": "83aa4d51-63ce-41e7-829f-3c16e6115bbf", + "filename": "Win_Network_DNS_Set_to_1.1.1.2.ps1", + "submittedBy": "https://github.com/silversword411", + "name": "Network - Set all NICs to use DNS of 1.1.1.2", + "description": "Domain computers skipped. Sets all NICs to have primary DNS server of 1.1.1.2, backup of 1.0.0.2 (Cloudflare malware blocking)", + "shell": "powershell", + "category": "TRMM (Win):Network", + "default_timeout": "90" + }, { "guid": "6ce5682a-49db-4c0b-9417-609cf905ac43", "filename": "Win_Win10_Change_Key_and_Activate.ps1", @@ -484,8 +505,8 @@ "guid": "83f6c6ea-6120-4fd3-bec8-d3abc505dcdf", "filename": "Win_TRMM_Start_Menu_Delete_Shortcut.ps1", "submittedBy": "https://github.com/silversword411", - "name": "TRMM Delete Start Menu Shortcut for App", - "description": "Tactical RMM delete its application shortcut that's installed in the start menu", + "name": "TacticalRMM Delete Start Menu Shortcut for App", + "description": "Delete its application shortcut that's installed in the start menu by default", "shell": "powershell", "category": "TRMM (Win):TacticalRMM Related", "default_timeout": "10" diff --git a/api/tacticalrmm/scripts/models.py b/api/tacticalrmm/scripts/models.py index fa1350b530..c8a4df176d 100644 --- a/api/tacticalrmm/scripts/models.py +++ b/api/tacticalrmm/scripts/models.py @@ -1,10 +1,11 @@ import base64 import re -from loguru import logger from typing import Any, List, Union + from django.conf import settings from django.contrib.postgres.fields import ArrayField from django.db import models +from loguru import logger from logs.models import BaseAuditModel diff --git a/api/tacticalrmm/scripts/tests.py b/api/tacticalrmm/scripts/tests.py index 407bc2fcf0..2cac323937 100644 --- a/api/tacticalrmm/scripts/tests.py +++ b/api/tacticalrmm/scripts/tests.py @@ -1,6 +1,6 @@ -from email.policy import default import json import os +from email.policy import default from pathlib import Path from django.conf import settings diff --git a/api/tacticalrmm/tacticalrmm/settings.py b/api/tacticalrmm/tacticalrmm/settings.py index c62cca18e0..c98b5e01ad 100644 --- a/api/tacticalrmm/tacticalrmm/settings.py +++ b/api/tacticalrmm/tacticalrmm/settings.py @@ -15,16 +15,16 @@ AUTH_USER_MODEL = "accounts.User" # latest release -TRMM_VERSION = "0.6.1" +TRMM_VERSION = "0.6.2" # bump this version everytime vue code is changed # to alert user they need to manually refresh their browser -APP_VER = "0.0.130" +APP_VER = "0.0.131" # https://github.com/wh1te909/rmmagent -LATEST_AGENT_VER = "1.5.1" +LATEST_AGENT_VER = "1.5.2" -MESH_VER = "0.7.93" +MESH_VER = "0.8.17" # for the update script, bump when need to recreate venv or npm install PIP_VER = "15" diff --git a/docs/docs/code_signing.md b/docs/docs/code_signing.md new file mode 100644 index 0000000000..bd4a9c719d --- /dev/null +++ b/docs/docs/code_signing.md @@ -0,0 +1,22 @@ +# Code Signing + +*Version added: Tactical RMM v0.6.0 / Agent v1.5.0* + +Tactical RMM agents are now [code signed](https://comodosslstore.com/resources/what-is-microsoft-authenticode-code-signing-certificate/)! + +To get access to code signed agents, you must be a [Github Sponsor](https://github.com/sponsors/wh1te909) with a minumum monthly donation of $50.00 + +Once you have become a sponsor, please email **support@amidaware.com** with your Github username (and Discord username if you're on our [Discord](https://discord.gg/upGTkWp)) + +Please allow up to 24 hours for a response + +You will then be sent a code signing auth token, which you should enter into Tactical's web UI from *Settings > Code Signing* + + +## How does it work? + +Everytime you generate an agent or an agent does a self-update, your self-hosted instance sends a request to Tactical's code signing servers with your auth token. + +If the token is valid, the server sends you back a code signed agent. If not, it sends you back the un-signed agent. + +If you think your auth token has been compromised or stolen then please email support or contact wh1te909 on discord to get a new token / invalidate the old one. \ No newline at end of file diff --git a/docs/docs/contributing_community_scripts.md b/docs/docs/contributing_community_scripts.md new file mode 100644 index 0000000000..17a96bfb80 --- /dev/null +++ b/docs/docs/contributing_community_scripts.md @@ -0,0 +1,103 @@ +## Script Library Naming Conventions + +### File names + +Under `/scripts` the file name should generally follow this format: + +``` +(Platform)_(Category or Function)_(What It Does).xxx +``` + +!!!info + Although Tactical RMM only has a Windows agent for now, we're planning for a future with more platform support + +Platform for now are: + +``` +Win +OSX +Linux +iOS +Android +``` + + +Good filename examples include: + +``` +Win_Azure_Mars_Cloud_Backup_Status.ps1 +Win_AzureAD_Check_Connection_Status.ps1 +Win_Network_DHCP_Set.bat +Win_Network_DNS_Set_to_1.1.1.2.ps1 +``` + +!!!info + This is so that at a glance you can see if there is already a script with that function, and you can avoid duplication of functionality. If you can improve a script or allow Script Arguments/Parameters update existing if possible + +### Name field (in community_scripts.json) + +Consider they are viewed in 3 different locations: + +Script Manager + +- List View (sortable by any column) + +- Folder View (Grouped by Categories) + +Run or Add script + +- Running scripts manually or adding tasks (or adding in Automation Manager) + +!!!info + A good max length is 50-60 chars or less for display in these 3 locations + +Make sure your Name roughly follows the order of file naming as above + +``` +Category or Function - What It Does +``` + + Consider how the alphabetic sort will affect display + +![json_name_examples](images/community_scripts_name_field_example1.png) + +## Making Script Files + +### Good Habits + +- Try and make them fully self-contained. + +- If they pull data from elsewhere, create comment notes at the top with references for others to audit/validate + +- Good folder locations +``` +c:\ProgramData\TacticalRMM\ +c:\ProgramData\TacticalRMM\scripts +c:\ProgramData\TacticalRMM\toolbox +c:\ProgramData\TacticalRMM\logs +c:\ProgramData\TacticalRMM\temp +c:\ProgramData\TacticalRMM\ +``` + +- Command Parameters are good. Optional command parameters for extra functions are better. + +### Bad Habits + +- Assumes non-standard configurations + +- Doesn't play well with other community scripts (reused names etc.) + + +## Useful Reference Script Examples + +RunAsUser (since Tactical RMM runs as system) +[https://github.com/wh1te909/tacticalrmm/blob/develop/scripts/Win_Display_Message_To_User.ps1](https://github.com/wh1te909/tacticalrmm/blob/develop/scripts/Win_Display_Message_To_User.ps1) + +Command Paramater Ninja +[https://github.com/wh1te909/tacticalrmm/blob/develop/scripts/Win_ScreenConnectAIO.ps1](https://github.com/wh1te909/tacticalrmm/blob/develop/scripts/Win_ScreenConnectAIO.ps1) + +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) + + + diff --git a/docs/docs/contributing_using_vscode.md b/docs/docs/contributing_using_vscode.md index 73a8178ca3..047a16c77e 100644 --- a/docs/docs/contributing_using_vscode.md +++ b/docs/docs/contributing_using_vscode.md @@ -1,4 +1,5 @@ +## Getting Started ### 1. Install vscode [https://code.visualstudio.com/download](https://code.visualstudio.com/download) @@ -94,4 +95,16 @@ Then you're `push`ing that updated local repo to your online Github fork ### 8. Verify and Repeat -Check your Github fork in browser, should be up to date now with original. Repeat 6 or 7 as necessary \ No newline at end of file +Check your Github fork in browser, should be up to date now with original. Repeat 6 or 7 as necessary + +## Reference + +### Customizing the Admin Web Interface + +Created using quasar, it's all your .vue files in `web/src/components/modals/agents/RunScript.vue` + +Learn stuff here + +https://quasar.dev/ + + diff --git a/docs/docs/images/community_scripts_name_field_example1.png b/docs/docs/images/community_scripts_name_field_example1.png new file mode 100644 index 0000000000..4033883946 Binary files /dev/null and b/docs/docs/images/community_scripts_name_field_example1.png differ diff --git a/docs/docs/install_agent.md b/docs/docs/install_agent.md index 13a5193001..6d016143a7 100644 --- a/docs/docs/install_agent.md +++ b/docs/docs/install_agent.md @@ -1,6 +1,7 @@ # Installing an agent !!!warning + If you don't want to deal with AV flagging/deleting your agents, check the instructions for getting [code signed agents](code_signing.md)

You must add antivirus exlusions for the tactical agent.
Any decent AV will flag the agent as a virus, since it technically is one due to the nature of this software.
Adding the following exlucions will make sure everything works, including agent update:
diff --git a/docs/docs/install_server.md b/docs/docs/install_server.md index c600900beb..6c090efa80 100644 --- a/docs/docs/install_server.md +++ b/docs/docs/install_server.md @@ -7,7 +7,8 @@ The provided install script assumes a fresh server with no software installed on it. Attempting to run it on an existing server with other services **will** break things and the install will fail.

The install script has been tested on the following public cloud providers: DigitalOcean, Linode, Vultr, BuyVM (highly recommended), Hetzner, AWS, Google Cloud and Azure, as well as behind NAT on Hyper-V, Proxmox and ESXi. -- A real domain is needed to generate a Let's Encrypt wildcard cert.
If you cannot afford to purchase a domain ($12 a year) then you can get one for free at [freenom.com](https://www.freenom.com/)

+- A real (internet resolvable) domain is needed to generate a Let's Encrypt wildcard cert.
If you cannot afford to purchase a domain ($12 a year) then you can get one for free at [freenom.com](https://www.freenom.com/) +- example.local is __NOT__ a real domain. No you [don't have to expose your server](faq.md#can-i-run-tactical-rmm-locally-behind-nat-without-exposing-anything-to-the-internet) to the internet

- A TOTP based authenticator app. Some popular ones are Google Authenticator, Authy and Microsoft Authenticator.

diff --git a/docs/docs/troubleshooting.md b/docs/docs/troubleshooting.md index 78a97c3084..8d2e54f6c5 100644 --- a/docs/docs/troubleshooting.md +++ b/docs/docs/troubleshooting.md @@ -30,6 +30,9 @@ If you have agents that are relatively old, you will need to uninstall them manu #### Agents not checking in or showing up / General agent issues +First, reload NATS from tactical's web UI:
+*Tools > Server Maintenance > Reload Nats Configuration* + Open CMD as admin on the problem computer and stop the agent services: ```cmd @@ -51,7 +54,7 @@ This will print out a ton of info. You should be able to see the error from the Please then copy/paste the logs and post them either in our [Discord support chat](https://discord.gg/upGTkWp), or create a [github issue](https://github.com/wh1te909/tacticalrmm/issues). -
+If all else fails, simply uninstall the agent either from control panel or silently with `"C:\Program Files\TacticalAgent\unins000.exe" /VERYSILENT` and then reinstall the agent. #### All other errors diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 84e7c05326..3bf70e56e7 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -2,6 +2,7 @@ site_name: "Tactical RMM Documentation" nav: - Home: index.md - Sponsor: sponsor.md + - Code Signing: code_signing.md - RMM Installation: - "Traditional Install": install_server.md - "Docker Install": install_docker.md @@ -23,9 +24,10 @@ nav: - FAQ: faq.md - Management Commands: management_cmds.md - MeshCentral Integration: mesh_integration.md - - Contributing: + - Contributing: - "Contributing to Docs": contributing.md - "Contributing using VSCode": contributing_using_vscode.md + - "Contributing to Community Scripts": contributing_community_scripts.md - License: license.md site_description: "A remote monitoring and management tool" site_author: "wh1te909" diff --git a/scripts/Win_Disable_AutoRun.bat b/scripts/Win_AutoRun_Disable.bat similarity index 100% rename from scripts/Win_Disable_AutoRun.bat rename to scripts/Win_AutoRun_Disable.bat diff --git a/scripts/Win_Disable_Cortana.bat b/scripts/Win_Cortana_Disable.bat similarity index 100% rename from scripts/Win_Disable_Cortana.bat rename to scripts/Win_Cortana_Disable.bat diff --git a/scripts/Win_Defender_Status.ps1 b/scripts/Win_Defender_Status_Report_Last24hrs.ps1 similarity index 97% rename from scripts/Win_Defender_Status.ps1 rename to scripts/Win_Defender_Status_Report_Last24hrs.ps1 index 7b9b04cb7a..0a9fe77767 100644 --- a/scripts/Win_Defender_Status.ps1 +++ b/scripts/Win_Defender_Status_Report_Last24hrs.ps1 @@ -1,24 +1,24 @@ -# This will check for Malware, Antispyware, that Windows Defender is Healthy, last scan etc within the last 24 hours - -$ErrorActionPreference= 'silentlycontinue' -$TimeSpan = (Get-Date) - (New-TimeSpan -Day 1) - -if (Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Windows Defender/Operational';ID='1116','1118','1015','1006','5010','5012','5001','1123';StartTime=$TimeSpan}) - -{ -Write-Output "Virus Found or Issue with Defender" -Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Windows Defender/Operational';ID='1116','1118','1015','1006','5010','5012','5001','1123';StartTime=$TimeSpan} -exit 1 -} - - -else - -{ -Write-Output "No Virus Found, Defender is Healthy" -Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Windows Defender/Operational';ID='1150','1001';StartTime=$TimeSpan} -exit 0 -} - - -Exit $LASTEXITCODE +# This will check for Malware, Antispyware, that Windows Defender is Healthy, last scan etc within the last 24 hours + +$ErrorActionPreference= 'silentlycontinue' +$TimeSpan = (Get-Date) - (New-TimeSpan -Day 1) + +if (Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Windows Defender/Operational';ID='1116','1118','1015','1006','5010','5012','5001','1123';StartTime=$TimeSpan}) + +{ +Write-Output "Virus Found or Issue with Defender" +Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Windows Defender/Operational';ID='1116','1118','1015','1006','5010','5012','5001','1123';StartTime=$TimeSpan} +exit 1 +} + + +else + +{ +Write-Output "No Virus Found, Defender is Healthy" +Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Windows Defender/Operational';ID='1150','1001';StartTime=$TimeSpan} +exit 0 +} + + +Exit $LASTEXITCODE diff --git a/scripts/Win_Defender_Status_Report_LastYear.ps1 b/scripts/Win_Defender_Status_Report_LastYear.ps1 new file mode 100644 index 0000000000..794e6acf68 --- /dev/null +++ b/scripts/Win_Defender_Status_Report_LastYear.ps1 @@ -0,0 +1,22 @@ +# This will check for Malware, Antispyware, that Windows Defender is Healthy, last scan etc within the last 24 hours + +$ErrorActionPreference = 'silentlycontinue' +$TimeSpan = (Get-Date) - (New-TimeSpan -Day 365) + +if (Get-WinEvent -FilterHashtable @{LogName = 'Microsoft-Windows-Windows Defender/Operational'; ID = '1116', '1118', '1015', '1006', '5010', '5012', '5001', '1123'; StartTime = $TimeSpan }) +{ + Write-Output "Virus Found or Issue with Defender" + Get-WinEvent -FilterHashtable @{LogName = 'Microsoft-Windows-Windows Defender/Operational'; ID = '1116', '1118', '1015', '1006', '5010', '5012', '5001', '1123'; StartTime = $TimeSpan } + exit 1 +} + + +else +{ + Write-Output "No Virus Found, Defender is Healthy" + Get-WinEvent -FilterHashtable @{LogName = 'Microsoft-Windows-Windows Defender/Operational'; ID = '1150', '1001'; StartTime = $TimeSpan } + exit 0 +} + + +Exit $LASTEXITCODE diff --git a/scripts/Win_Finish_updates_and_restart.ps1 b/scripts/Win_Finish_updates_and_restart.ps1 deleted file mode 100644 index 289f983bc3..0000000000 --- a/scripts/Win_Finish_updates_and_restart.ps1 +++ /dev/null @@ -1,5 +0,0 @@ -# This script will force the computer to finish installing updates -# and restart. Normal restart doesn't install updates before issuing -# a reboot command. This one does. - -Restart-Computer -ComputerName $env:COMPUTERNAME -Force diff --git a/scripts/Win_Finish_updates_and_shutdown.ps1 b/scripts/Win_Finish_updates_and_shutdown.ps1 deleted file mode 100644 index 0924e82e24..0000000000 --- a/scripts/Win_Finish_updates_and_shutdown.ps1 +++ /dev/null @@ -1,5 +0,0 @@ -# This script will force the computer to finish installing updates -# and shutdown. Normal shutdown doesn't install updates before issuing -# a shutdown command. This one does. - -Stop-Computer -ComputerName $env:COMPUTERNAME -Force \ No newline at end of file diff --git a/scripts/Win_Clear_Firefox_Cache.ps1 b/scripts/Win_Firefox_Clear_Cache.ps1 similarity index 100% rename from scripts/Win_Clear_Firefox_Cache.ps1 rename to scripts/Win_Firefox_Clear_Cache.ps1 diff --git a/scripts/Win_Clear_Google_Chrome_Cache.ps1 b/scripts/Win_Google_Chrome_Clear_Cache.ps1 similarity index 100% rename from scripts/Win_Clear_Google_Chrome_Cache.ps1 rename to scripts/Win_Google_Chrome_Clear_Cache.ps1 diff --git a/scripts/Win_Network_DHCP_Set.bat b/scripts/Win_Network_DHCP_Set.bat new file mode 100644 index 0000000000..a53fcaef09 --- /dev/null +++ b/scripts/Win_Network_DHCP_Set.bat @@ -0,0 +1,13 @@ +@echo off +for /f "tokens=4-5 delims=. " %%i in ('ver') do set VERSION=%%i.%%j + +if "%version%" == "6.1" ( + rem Windows 7 + netsh interface ip set address "Local Area Connection" dhcp + netsh interface ip set dns "Local Area Connection" dhcp +) +if "%version%" == "10.0" ( + rem Windows 10 + netsh interface ip set address Ethernet dhcp + netsh interface ip set dns Ethernet dhcp +) \ No newline at end of file diff --git a/scripts/Win_Network_DNS_Set_to_1.1.1.2.ps1 b/scripts/Win_Network_DNS_Set_to_1.1.1.2.ps1 new file mode 100644 index 0000000000..d3e2ee0298 --- /dev/null +++ b/scripts/Win_Network_DNS_Set_to_1.1.1.2.ps1 @@ -0,0 +1,39 @@ +# Cloudflare Family DNS see https://blog.cloudflare.com/introducing-1-1-1-1-for-families/ + +$ErrorActionPreference = 'SilentlyContinue' + +if ((Get-WmiObject -Class Win32_ComputerSystem).PartOfDomain){ + write-host "Domain member, we better not update the DNS!!" + exit +} + +$PrimaryDNS = '1.1.1.2' +$SecondaryDNS = '1.0.0.2' + +$DNSServers = $PrimaryDNS,$SecondaryDNS + +$NICs = Get-WMIObject Win32_NetworkAdapterConfiguration | where{$_.IPEnabled -eq "TRUE"} + +function get-return-status { + Param ($code) + If ($code -eq 0) { + return "Success." + } elseif ($code -eq 1) { + return "Success, but Restart Required." + } else { + return "Error with Code $($code)!" + } +} + +Foreach($NIC in $NICs) { + "" + "-------" + "Attempting to modify DNS Servers for the following NIC:" + $NIC + $returnValue = $NIC.SetDNSServerSearchOrder($DNSServers).ReturnValue + $response = get-return-status($returnValue) + Write-Host "Setting DNS Servers to ${$NICs}...$($response)" + $returnValue = $NIC.SetDynamicDNSRegistration("True").ReturnValue + $response = get-return-status($returnValue) + Write-Host "Setting Dynamic DNS Registration to True...$($response)" +} \ No newline at end of file diff --git a/scripts/Win_Reset_High_Performance_Power_Profile_to_Defaults.ps1 b/scripts/Win_Power_Profile_Reset_High_Performance_to_Defaults.ps1 similarity index 100% rename from scripts/Win_Reset_High_Performance_Power_Profile_to_Defaults.ps1 rename to scripts/Win_Power_Profile_Reset_High_Performance_to_Defaults.ps1 diff --git a/scripts/Win_Set_High_Performance_Power_Profile.ps1 b/scripts/Win_Power_Profile_Set_High_Performance.ps1 similarity index 100% rename from scripts/Win_Set_High_Performance_Power_Profile.ps1 rename to scripts/Win_Power_Profile_Set_High_Performance.ps1 diff --git a/scripts/Win_Power_RestartorShutdown.ps1 b/scripts/Win_Power_RestartorShutdown.ps1 new file mode 100644 index 0000000000..c050cb0e2b --- /dev/null +++ b/scripts/Win_Power_RestartorShutdown.ps1 @@ -0,0 +1,11 @@ +# This script will force restart computer. Add command paramter: shutdown to shutdown instead +# Normal restart doesn't install updates before issuing + +$param1 = $args[0] + +if ($param1 -eq 'shutdown') { + Stop-Computer -ComputerName $env:COMPUTERNAME -Force +} +else { + Restart-Computer -ComputerName $env:COMPUTERNAME -Force +} \ No newline at end of file diff --git a/scripts/Win_Update_Tactical_Exclusion.ps1 b/scripts/Win_TRMM_AV_Update_Exclusion.ps1 similarity index 98% rename from scripts/Win_Update_Tactical_Exclusion.ps1 rename to scripts/Win_TRMM_AV_Update_Exclusion.ps1 index bf0fbc9079..251c33c847 100644 --- a/scripts/Win_Update_Tactical_Exclusion.ps1 +++ b/scripts/Win_TRMM_AV_Update_Exclusion.ps1 @@ -1,5 +1,5 @@ -#Windows Defender Exclusions for Tactical -Add-MpPreference -ExclusionPath "C:\Program Files\Mesh Agent\*" -Add-MpPreference -ExclusionPath "C:\Program Files\TacticalAgent\*" -Add-MpPreference -ExclusionPath "C:\Windows\Temp\trmm\*" -Add-MpPreference -ExclusionPath "C:\Windows\Temp\winagent-v*.exe" +#Windows Defender Exclusions for Tactical +Add-MpPreference -ExclusionPath "C:\Program Files\Mesh Agent\*" +Add-MpPreference -ExclusionPath "C:\Program Files\TacticalAgent\*" +Add-MpPreference -ExclusionPath "C:\Windows\Temp\trmm\*" +Add-MpPreference -ExclusionPath "C:\Windows\Temp\winagent-v*.exe" diff --git a/scripts/Win_Rename_Installed_App.ps1 b/scripts/Win_TRMM_Rename_Installed_App.ps1 similarity index 100% rename from scripts/Win_Rename_Installed_App.ps1 rename to scripts/Win_TRMM_Rename_Installed_App.ps1 diff --git a/web/src/components/AgentTable.vue b/web/src/components/AgentTable.vue index a671698655..a2aea80309 100644 --- a/web/src/components/AgentTable.vue +++ b/web/src/components/AgentTable.vue @@ -385,7 +385,7 @@ - + @@ -393,7 +393,7 @@ - + diff --git a/web/src/components/FileBar.vue b/web/src/components/FileBar.vue index 1070b6f854..ad229f3ea8 100644 --- a/web/src/components/FileBar.vue +++ b/web/src/components/FileBar.vue @@ -90,7 +90,7 @@ Global Settings - + Code Signing @@ -246,6 +246,11 @@ export default { showCodeSign: false, }; }, + computed: { + noCodeSigning() { + return this.$store.state.noCodeSign; + }, + }, methods: { showBulkActionModal(mode) { this.bulkMode = mode; diff --git a/web/src/components/SummaryTab.vue b/web/src/components/SummaryTab.vue index 89b558db55..3810e71d16 100644 --- a/web/src/components/SummaryTab.vue +++ b/web/src/components/SummaryTab.vue @@ -80,7 +80,16 @@ {{ summary.checks.info }} checks info - {{ summary.checks.total }} checks awaiting first synchronization @@ -113,8 +122,8 @@ export default { return {}; }, methods: { - awaitingSync(total, passing, failing) { - return total !== 0 && passing === 0 && failing === 0 ? true : false; + awaitingSync(total, passing, failing, warning, info) { + return total !== 0 && passing === 0 && failing === 0 && warning === 0 && info === 0; }, refreshSummary() { this.$q.loading.show(); diff --git a/web/src/components/modals/agents/InstallAgent.vue b/web/src/components/modals/agents/InstallAgent.vue index fd964e713b..dbf7d3150d 100644 --- a/web/src/components/modals/agents/InstallAgent.vue +++ b/web/src/components/modals/agents/InstallAgent.vue @@ -47,7 +47,11 @@
- + + + Enable ICMP echo requests in the local firewall + +
diff --git a/web/src/components/modals/clients/DeleteClient.vue b/web/src/components/modals/clients/DeleteClient.vue index e1971f771c..64e5381292 100644 --- a/web/src/components/modals/clients/DeleteClient.vue +++ b/web/src/components/modals/clients/DeleteClient.vue @@ -55,6 +55,7 @@ export default { return { siteOptions: [], selectedSite: null, + agentCount: 0, }; }, methods: { @@ -112,6 +113,7 @@ export default { }, getSites() { this.$axios.get("/clients/clients/").then(r => { + this.agentCount = this.getAgentCount(r.data, this.type, this.object.id); r.data.forEach(client => { // remove client that is being deleted from options if (this.type === "client") { diff --git a/web/src/mixins/mixins.js b/web/src/mixins/mixins.js index 65a7399f48..48345de304 100644 --- a/web/src/mixins/mixins.js +++ b/web/src/mixins/mixins.js @@ -147,6 +147,19 @@ export default { this.notifyError("There was an issue getting Custom Fields"); }); }, + getAgentCount(data, type, id) { + if (type === "client") { + return data.find(i => id === i.id).agent_count + } else { + const sites = data.map(i => i.sites) + for (let i of sites) { + for (let k of i) { + if (k.id === id) return k.agent_count; + } + } + return 0; + } + }, formatCustomFields(fields, values) { let tempArray = []; diff --git a/web/src/store/index.js b/web/src/store/index.js index 21c10a2373..26e0d29986 100644 --- a/web/src/store/index.js +++ b/web/src/store/index.js @@ -34,6 +34,7 @@ export default function () { defaultAgentTblTab: "server", clientTreeSort: "alphafail", clientTreeSplitter: 11, + noCodeSign: false, }, getters: { clientTreeSplitterModel(state) { @@ -153,6 +154,9 @@ export default function () { }, SET_CLIENT_TREE_SORT(state, val) { state.clientTreeSort = val + }, + SET_NO_CODE_SIGN(state, val) { + state.noCodeSign = val } }, actions: { @@ -285,7 +289,9 @@ export default function () { if (state.clientTreeSort === "alphafail") { // move failing clients to the top - const sortedByFailing = output.sort(a => a.color === "negative" ? -1 : 1); + const failing = output.filter(i => i.color === "negative" || i.color === "warning"); + const ok = output.filter(i => i.color !== "negative" && i.color !== "warning"); + const sortedByFailing = [...failing, ...ok]; commit("loadTree", sortedByFailing); } else { commit("loadTree", output); diff --git a/web/src/views/Dashboard.vue b/web/src/views/Dashboard.vue index d64d74f885..9c16bf1bae 100644 --- a/web/src/views/Dashboard.vue +++ b/web/src/views/Dashboard.vue @@ -721,6 +721,7 @@ export default { this.currentTRMMVersion = r.data.trmm_version; this.$store.commit("SET_AGENT_DBLCLICK_ACTION", r.data.dbl_click_action); this.$store.commit("setShowCommunityScripts", r.data.show_community_scripts); + this.$store.commit("SET_NO_CODE_SIGN", r.data.no_code_sign); }); }, showToggleMaintenance(node) {