diff --git a/README.md b/README.md index e291ba6..c5f6d1d 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,13 @@ This script is designed to assist users in adding Mac agents to Tactical RMM without the need for upfront payment for code-signed agents. If you find this solution beneficial, please consider contributing to the Tactical RMM project! +> This script had a complete rewrite and now only supports MacOS 14 (Sonoma) and above. + # rmmagent-script Script for one-line installation and updating of the tacticalRMM agent. -> Currently, both amd64 and arm64 scripts are available; however, only the amd64 version has been tested on macOS 13 (Ventura). +> Currently, both amd64 and arm64 scripts are available and has been tested with MacOS 14 (Sonoma) and MacOS 15 (Sequoia); however, only the amd64 version has been tested on macOS 13 (Ventura). Scripts for additional platforms will be developed and released as they are adapted. You are welcome to modify the script and contribute your improvements back to the project. @@ -21,23 +23,13 @@ Download script with this url: `https://raw.githubusercontent.com/mattchis/MacRM To install agent launch the script with this argument: ```bash -./rmmagent-mac.sh install 'System type' 'Mesh agent' 'API URL' 'Client ID' 'Site ID' 'Auth Key' 'Agent Type' +./rmmagent-mac.sh install 'API URL' 'Client ID' 'Site ID' 'Auth Key' 'Agent Type' ``` The compiling can be quite long, don't panic and wait few minutes... USE THE 'SINGLE QUOTES' IN ALL FIELDS! The argument are: -2. System type - - Type of system. Can be 'amd64' 'arm64' - -3. Mesh agent - - The url given by mesh for installing new agent. - Go to mesh.fqdn.com > Add agent > Installation Executable Linux / BSD / macOS > **Select the good system type** - Copy **ONLY** the URL with the quote. - -4. API URL +2. API URL Your api URL for agent communication usually https://api.fqdn.com. @@ -62,7 +54,7 @@ The argument are: ### Example ```bash -./rmmagent-mac.sh install amd64 "https://mesh.fqdn.com/meshagents?id=XXXXX&installflags=X&meshinstall=X" "https://api.fqdn.com" 3 1 "XXXXX" server +./rmmagent-mac.sh install "https://api.fqdn.com" 3 1 "XXXXX" server ``` ## Update @@ -71,6 +63,17 @@ Simply launch the script that match your system with *update* as argument. ```bash ./rmmagent-mac.sh update ``` +## Enable Permissions +This sets up all the permissions for screenrecording, file, and disk access for the meshagent. + +```bash +./rmmagent-mac.sh enablepermissions +``` +## Seqouia Fix +This will fix issues with "Take Control" from the dashboard not displaying the screen. Credit goes to PeetMcK and si458 for the solution (https://github.com/Ylianst/MeshCentral/issues/6402) +```bash +./rmmagent-mac.sh sequoiafix +``` ## Uninstall To uninstall the agent, execute the script with the following argument: diff --git a/rmmagent-mac.sh b/rmmagent-mac.sh index 45430d7..7ef7b28 100644 --- a/rmmagent-mac.sh +++ b/rmmagent-mac.sh @@ -10,100 +10,87 @@ if [[ $1 == "help" ]]; then echo "" echo "List of INSTALL/UPDATE argument (no argument name):" echo "Arg 1: 'install' or 'update'" - echo "Arg 2: System type 'amd64' 'arm64'" - echo "Arg 3: Mesh agent URL" - echo "Arg 4: API URL" - echo "Arg 5: Client ID" - echo "Arg 6: Site ID" - echo "Arg 7: Auth Key" - echo "Arg 8: Agent Type 'server' or 'workstation'" + echo "Arg 2: API URL" + echo "Arg 3: Client ID" + echo "Arg 4: Site ID" + echo "Arg 5: Auth Key" + echo "Arg 6: Agent Type 'server' or 'workstation'" echo "" echo "List of UNINSTALL argument (no argument name):" echo "Arg 1: 'uninstall'" - echo "Arg 2: Mesh agent FQDN (i.e. mesh.domain.com)" - echo "Arg 3: Mesh agent id (The id needs to have single quotes around it)" echo "" - echo "Only argument 1 is needed for update" + echo "List of ENABLEPERMISSIONS argument (no argument name):" + echo "Arg 1: 'enablepermissions'" + echo "" + echo "List of SEQUOIAFIX argument (no argument name):" + echo "Arg 1: 'SEQUOIAFIX'" + echo "" + echo "Only argument 1 is needed for update and sequoiafix" echo "" exit 0 fi -if [[ $1 != "install" && $1 != "update" && $1 != "uninstall" ]]; then +if [[ $1 != "install" && $1 != "update" && $1 != "uninstall" && $1 != "enablepermissions" && $1 != "sequoiafix" ]]; then echo "First argument can only be 'install' or 'update' or 'uninstall' !" echo "Type help for more information" exit 1 fi if [[ $1 == "install" && $2 == "" ]]; then - echo "Argument 2 (System type) is empty !" - echo "Type help for more information" - exit 1 -fi - -if [[ $1 == "install" && $2 != "amd64" && $2 != "arm64" ]]; then - echo "This argument can only be 'amd64' 'arm64' !" + echo "Argument 2 (API URL) is empty !" echo "Type help for more information" exit 1 fi if [[ $1 == "install" && $3 == "" ]]; then - echo "Argument 3 (Mesh agent URL) is empty !" + echo "Argument 3 (Client ID) is empty !" echo "Type help for more information" exit 1 fi if [[ $1 == "install" && $4 == "" ]]; then - echo "Argument 4 (API URL) is empty !" + echo "Argument 4 (Site ID) is empty !" echo "Type help for more information" exit 1 fi if [[ $1 == "install" && $5 == "" ]]; then - echo "Argument 5 (Client ID) is empty !" + echo "Argument 5 (Auth Key) is empty !" echo "Type help for more information" exit 1 fi if [[ $1 == "install" && $6 == "" ]]; then - echo "Argument 6 (Site ID) is empty !" + echo "Argument 6 (Agent Type) is empty !" echo "Type help for more information" exit 1 fi -if [[ $1 == "install" && $7 == "" ]]; then - echo "Argument 7 (Auth Key) is empty !" - echo "Type help for more information" - exit 1 -fi - -if [[ $1 == "install" && $8 == "" ]]; then - echo "Argument 8 (Agent Type) is empty !" - echo "Type help for more information" - exit 1 -fi - -if [[ $1 == "install" && $8 != "server" && $8 != "workstation" ]]; then +if [[ $1 == "install" && $6 != "server" && $6 != "workstation" ]]; then echo "First argument can only be 'server' or 'workstation' !" echo "Type help for more information" exit 1 fi ## Setting var for easy scription -system=$2 -mesh_url=$3 -rmm_url=$4 -rmm_client_id=$5 -rmm_site_id=$6 -rmm_auth=$7 -rmm_agent_type=$8 +#system=$2 +#mesh_url=$2 +rmm_url=$2 +rmm_client_id=$3 +rmm_site_id=$4 +rmm_auth=$5 +rmm_agent_type=$6 -go_url_amd64="https://go.dev/dl/go1.20.2.darwin-amd64.pkg" -go_url_arm64="https://go.dev/dl/go1.20.2.darwin-arm64.pkg" +go_url_amd64="https://go.dev/dl/go1.24.4.darwin-amd64.pkg" +go_url_arm64="https://go.dev/dl/go1.24.4.darwin-arm64.pkg" function go_install() { ## Installing golang - case $system in - amd64) + echo "###########################" + echo "# Installing/Upgrading Go #" + echo "###########################" + case $(uname -m) in + x86_64) sudo curl -L -o /tmp/golang.pkg $go_url_amd64 ;; arm64) @@ -112,7 +99,7 @@ function go_install() { esac sudo mkdir /usr/local/go - sudo installer -pkg /tmp/golang.pkg -target /usr/local/go + sudo installer -pkg /tmp/golang.pkg -target /usr/local/go sudo rm /tmp/golang.pkg source /etc/profile @@ -120,44 +107,36 @@ function go_install() { echo "Golang Install Done !" } -function install_mesh() { - ## Installing mesh agent - sudo curl -L -o /tmp/meshagent $mesh_url - sudo chmod +x /tmp/meshagent - sudo mkdir /opt/tacticalmesh - sudo /tmp/meshagent -install --installPath="/opt/tacticalmesh" - sudo rm /tmp/meshagent - sudo rm /tmp/meshagent.msh -} - function getCSREQBlob(){ - # Sign the app - sudo codesign --detached /opt/tacticalmesh/meshagent.sig -s - /opt/tacticalmesh/meshagent + # Sign the app + sudo codesign --detached /opt/tacticalmesh/meshagent.sig -s - /opt/tacticalmesh/meshagent - # Get the requirement string from codesign - req_str=$(sudo codesign -d -r- --detached /opt/tacticalmesh/meshagent.sig /opt/tacticalmesh/meshagent 2>&1 | awk -F ' => ' '/designated/{print $2}') + # Get the requirement string from codesign + req_str=$(sudo codesign -d -r- --detached /opt/tacticalmesh/meshagent.sig /opt/tacticalmesh/meshagent 2>&1 | awk -F ' => ' '/designated/{print $2}') + + # Convert the requirements string into it's binary representation + # csreq requires the output to be a file so we just throw it in /tmp + echo "$req_str" | sudo csreq -r- -b /tmp/csreq.bin >/dev/null 2>&1 + + # Convert the binary form to hex, and print it nicely for use in sqlite + req_hex="X'$(sudo xxd -p /tmp/csreq.bin | tr -d '\n')'" + + echo "$req_hex" - # Convert the requirements string into it's binary representation - # csreq requires the output to be a file so we just throw it in /tmp - echo "$req_str" | sudo csreq -r- -b /tmp/csreq.bin - - # Convert the binary form to hex, and print it nicely for use in sqlite - req_hex="X'$(sudo xxd -p /tmp/csreq.bin | tr -d '\n')'" - - echo "$req_hex" - - # Remove csqeq.bin - sudo rm -f "/tmp/csreq.bin" + # Remove csqeq.bin + sudo rm -f "/tmp/csreq.bin" } function agent_compile() { ## Compiling and installing tactical agent from github - echo "Agent Compile begin" + echo "########################" + echo "# Compiling TRMM Agent #" + echo "########################" sudo curl -L -o /tmp/rmmagent.zip https://github.com/amidaware/rmmagent/archive/refs/heads/master.zip sudo unzip /tmp/rmmagent.zip -d /tmp/ sudo rm /tmp/rmmagent.zip - case $system in - amd64) + case $(uname -m) in + x86_64) sudo /bin/sh -c 'cd /tmp/rmmagent-master && env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags "-s -w" -o /tmp/temp_rmmagent' ;; arm64) @@ -170,63 +149,124 @@ function agent_compile() { } function install_agent() { + echo "#########################" + echo "# Installing TRMM Agent #" + echo "#########################" sudo cp /tmp/temp_rmmagent /usr/local/bin/rmmagent sudo /tmp/temp_rmmagent -m install -meshdir /opt/tacticalmesh -api $rmm_url -client-id $rmm_client_id -site-id $rmm_site_id -agent-type $rmm_agent_type -auth $rmm_auth sudo rm /tmp/temp_rmmagent + sudo xattr -r -d com.apple.quarantine /opt/tacticalmesh/meshagent } function update_agent() { - sudo launchctl unload /Library/LaunchDaemons/tacticalagent.plist + echo "#######################" + echo "# Updating TRMM Agent #" + echo "#######################" + sudo launchctl bootout system /Library/LaunchDaemons/tacticalagent.plist sudo cp /tmp/temp_rmmagent /opt/tacticalagent/tacticalagent sudo rm /tmp/temp_rmmagent sudo launchctl load -w /Library/LaunchDaemons/tacticalagent.plist + sudo xattr -r -d com.apple.quarantine /opt/tacticalmesh/meshagent } function config_securityandprivacy () { # Adding permissions to macOS to allow Accessibility, Screen Capture, and All File Access to the meshagent - echo "Applying Security and Privacy Exceptions" + echo "############################################" + echo "# Applying Security and Privacy Exceptions #" + echo "############################################" req_hex="$(getCSREQBlob)" - sudo sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db "REPLACE INTO access VALUES('kTCCServiceAccessibility','/opt/tacticalmesh/meshagent',1,2,4,1,$req_hex,NULL,0,NULL,NULL,0,NULL);" - sudo sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db "REPLACE INTO access VALUES('kTCCServiceScreenCapture','/opt/tacticalmesh/meshagent',1,2,4,1,$req_hex,NULL,0,NULL,NULL,0,NULL);" - sudo sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db "REPLACE INTO access VALUES('kTCCServiceSystemPolicyAllFiles','/opt/tacticalmesh/meshagent',1,2,4,1,$req_hex,NULL,0,NULL,NULL,0,NULL);" + echo "Hex value = $req_hex" + sudo sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db "REPLACE INTO access VALUES('kTCCServiceAccessibility','/opt/tacticalmesh/meshagent',1,2,4,1,$req_hex,NULL,0,'UNUSED',NULL,0,NULL,NULL,NULL,NULL,NULL);" + sudo sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db "REPLACE INTO access VALUES('kTCCServiceScreenCapture','/opt/tacticalmesh/meshagent',1,2,4,1,$req_hex,NULL,0,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL);" + sudo sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db "REPLACE INTO access VALUES('kTCCServiceSystemPolicyAllFiles','/opt/tacticalmesh/meshagent',1,2,4,1,$req_hex,NULL,0,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL);" } function uninstall_agent() { - sudo launchctl unload /Library/LaunchDaemons/tacticalagent.plist - sudo rm /Library/LaunchDaemons/tacticalagent.plist - sudo rm -Rf /opt/tacticalagent/ - sudo rm /etc/tacticalagent + echo "###########################" + echo "# Uninstalling TRMM Agent #" + echo "###########################" + if [ -e "/Library/LaunchDaemons/tacticalagent.plist" ]; then + sudo launchctl bootout system /Library/LaunchDaemons/tacticalagent.plist + sudo rm /Library/LaunchDaemons/tacticalagent.plist + fi + if [ -d "/opt/tacticalagent" ]; then + sudo rm -Rf /opt/tacticalagent/ + fi + if [ -e "/etc/tacticalagent" ]; then + sudo rm /etc/tacticalagent + fi + sudo sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db "delete from access where client='/opt/tacticalagent/tacticalagent';" } function uninstall_mesh() { - sudo launchctl unload /Library/LaunchDaemons/meshagent.plist - sudo /opt/tacticalmesh/meshagent -fulluninstall - rm -Rf /opt/tacticalmesh + echo "###########################" + echo "# Uninstalling Mesh Agent #" + echo "###########################" + if [ -e "/Library/LaunchDaemons/meshagent.plist" ]; then + sudo launchctl bootout system /Library/LaunchDaemons/meshagent.plist + fi + if [ -e "/Library/LaunchAgents/meshagent-agent.plist" ]; then + sudo rm /Library/LaunchAgents/meshagent-agent.plist + fi + if [ -e "/Library/LaunchAgents/meshagent.plist" ]; then + sudo rm /Library/LaunchAgents/meshagent.plist + fi + if [ -e "/opt/tacticalmesh/meshagent" ]; then + sudo /opt/tacticalmesh/meshagent -fulluninstall + fi + if [ -d "/opt/tacticalmesh" ]; then + rm -Rf /opt/tacticalmesh + fi sudo sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db "delete from access where client='/opt/tacticalmesh/meshagent';" } +function sequoia_fix() { + echo "########################" + echo "# Applying Sequoia Fix #" + echo "########################" + script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + if [ -e "/Library/LaunchAgents/meshagent-agent.plist" ]; then + sudo rm /Library/LaunchAgents/meshagent-agent.plist + fi + if [ -e "/Library/LaunchDaemons/meshagent.plist" ]; then + sudo rm /Library/LaunchDaemons/meshagent.plist + fi + sudo cp "${script_dir}/meshagent.plist" /Library/LaunchAgents/meshagent.plist + sudo chown root:wheel /Library/LaunchAgents/meshagent.plist + sudo chmod 666 /opt/tacticalmesh/meshagent.msh + sudo chmod 666 /opt/tacticalmesh/meshagent.db +} + case $1 in install) go_install - install_mesh agent_compile install_agent - config_securityandprivacy echo "Tactical Agent Install is done" + echo "Please wait about 5 min then run 'rmmagent-mac.sh enablepermissions'" exit 0;; +enablepermissions) + config_securityandprivacy + echo "Security and Privacy configuration is done" + echo "If the Mac is running Sequoia then run 'rmmagent-mac.sh sequoiafix'" + exit 0;; +sequoiafix) + sequoia_fix + echo "Sequoia Fix has been applied. Please reboot Mac for changes to take effect" + exit 0;; update) go_install agent_compile update_agent - config_securityandprivacy echo "Tactical Agent Update is done" + echo "Please wait about 5 min then run 'rmmagent-mac.sh enablepermissions'" exit 0;; uninstall) uninstall_agent uninstall_mesh - echo "Tactical Agent Uninstall is done" + echo "TacticalRMM/Mesh Agent Uninstall is complete" echo "You may need to manually remove the agents orphaned connections on TacticalRMM and MeshCentral" exit 0;; -esac \ No newline at end of file +esac