mac agent
This commit is contained in:
parent
e0cfb7c90e
commit
852dfee29f
@ -76,6 +76,12 @@ const (
|
|||||||
winExeName = "tacticalrmm.exe"
|
winExeName = "tacticalrmm.exe"
|
||||||
winSvcName = "tacticalrmm"
|
winSvcName = "tacticalrmm"
|
||||||
meshSvcName = "mesh agent"
|
meshSvcName = "mesh agent"
|
||||||
|
etcConfig = "/etc/tacticalagent"
|
||||||
|
nixAgentDir = "/opt/tacticalagent"
|
||||||
|
nixAgentBin = nixAgentDir + "/tacticalagent"
|
||||||
|
macPlistPath = "/Library/LaunchDaemons/tacticalagent.plist"
|
||||||
|
macPlistName = "tacticalagent"
|
||||||
|
macMeshSvcDir = "/usr/local/mesh_services"
|
||||||
)
|
)
|
||||||
|
|
||||||
var winTempDir = filepath.Join(os.Getenv("PROGRAMDATA"), "TacticalRMM")
|
var winTempDir = filepath.Join(os.Getenv("PROGRAMDATA"), "TacticalRMM")
|
||||||
@ -120,18 +126,19 @@ func New(logger *logrus.Logger, version string) *Agent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var MeshSysExe string
|
var MeshSysExe string
|
||||||
if len(ac.CustomMeshDir) > 0 {
|
switch runtime.GOOS {
|
||||||
MeshSysExe = filepath.Join(ac.CustomMeshDir, "MeshAgent.exe")
|
case "windows":
|
||||||
} else {
|
if len(ac.CustomMeshDir) > 0 {
|
||||||
MeshSysExe = filepath.Join(os.Getenv("ProgramFiles"), "Mesh Agent", "MeshAgent.exe")
|
MeshSysExe = filepath.Join(ac.CustomMeshDir, "MeshAgent.exe")
|
||||||
}
|
} else {
|
||||||
|
MeshSysExe = filepath.Join(os.Getenv("ProgramFiles"), "Mesh Agent", "MeshAgent.exe")
|
||||||
if runtime.GOOS == "linux" {
|
}
|
||||||
|
case "linux":
|
||||||
|
MeshSysExe = "/opt/tacticalmesh/meshagent"
|
||||||
|
case "darwin":
|
||||||
|
MeshSysExe = "/usr/local/mesh_services/meshagent/meshagent"
|
||||||
|
default:
|
||||||
MeshSysExe = "/opt/tacticalmesh/meshagent"
|
MeshSysExe = "/opt/tacticalmesh/meshagent"
|
||||||
}
|
|
||||||
|
|
||||||
if runtime.GOOS == "darwin" {
|
|
||||||
MeshSysExe = "/usr/local/mesh_services/meshagent/meshagent_osx64"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
svcConf := &service.Config{
|
svcConf := &service.Config{
|
||||||
|
@ -50,7 +50,7 @@ func (a *Agent) GetDisks() []trmm.Disk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, p := range partitions {
|
for _, p := range partitions {
|
||||||
if strings.Contains(p.Device, "dev/loop") {
|
if strings.Contains(p.Device, "dev/loop") || strings.Contains(p.Device, "devfs") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
usage, err := disk.Usage(p.Mountpoint)
|
usage, err := disk.Usage(p.Mountpoint)
|
||||||
@ -283,7 +283,7 @@ func (a *Agent) AgentUpdate(url, inno, version string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.seEnforcing() {
|
if runtime.GOOS == "linux" && a.seEnforcing() {
|
||||||
se := a.NewCMDOpts()
|
se := a.NewCMDOpts()
|
||||||
se.Command = fmt.Sprintf("restorecon -rv %s", self)
|
se.Command = fmt.Sprintf("restorecon -rv %s", self)
|
||||||
out := a.CmdV2(se)
|
out := a.CmdV2(se)
|
||||||
@ -292,7 +292,15 @@ func (a *Agent) AgentUpdate(url, inno, version string) {
|
|||||||
|
|
||||||
opts := a.NewCMDOpts()
|
opts := a.NewCMDOpts()
|
||||||
opts.Detached = true
|
opts.Detached = true
|
||||||
opts.Command = "systemctl restart tacticalagent.service"
|
switch runtime.GOOS {
|
||||||
|
case "linux":
|
||||||
|
opts.Command = "systemctl restart tacticalagent.service"
|
||||||
|
case "darwin":
|
||||||
|
opts.Command = "launchctl kickstart -k system/tacticalagent"
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
a.CmdV2(opts)
|
a.CmdV2(opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,7 +318,9 @@ func (a *Agent) AgentUninstall(code string) {
|
|||||||
opts := a.NewCMDOpts()
|
opts := a.NewCMDOpts()
|
||||||
opts.IsScript = true
|
opts.IsScript = true
|
||||||
opts.Shell = f.Name()
|
opts.Shell = f.Name()
|
||||||
opts.Args = []string{"uninstall"}
|
if runtime.GOOS == "linux" {
|
||||||
|
opts.Args = []string{"uninstall"}
|
||||||
|
}
|
||||||
opts.Detached = true
|
opts.Detached = true
|
||||||
a.CmdV2(opts)
|
a.CmdV2(opts)
|
||||||
}
|
}
|
||||||
@ -354,7 +364,15 @@ func (a *Agent) getMeshNodeID() (string, error) {
|
|||||||
func (a *Agent) RecoverMesh() {
|
func (a *Agent) RecoverMesh() {
|
||||||
a.Logger.Infoln("Attempting mesh recovery")
|
a.Logger.Infoln("Attempting mesh recovery")
|
||||||
opts := a.NewCMDOpts()
|
opts := a.NewCMDOpts()
|
||||||
opts.Command = "systemctl restart meshagent.service"
|
def := "systemctl restart meshagent.service"
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "linux":
|
||||||
|
opts.Command = def
|
||||||
|
case "darwin":
|
||||||
|
opts.Command = "launchctl kickstart -k system/meshagent"
|
||||||
|
default:
|
||||||
|
opts.Command = def
|
||||||
|
}
|
||||||
a.CmdV2(opts)
|
a.CmdV2(opts)
|
||||||
a.SyncMeshNodeID()
|
a.SyncMeshNodeID()
|
||||||
}
|
}
|
||||||
@ -413,18 +431,25 @@ func (a *Agent) GetWMIInfo() map[string]interface{} {
|
|||||||
wmiInfo["make_model"] = ""
|
wmiInfo["make_model"] = ""
|
||||||
chassis, err := ghw.Chassis(ghw.WithDisableWarnings())
|
chassis, err := ghw.Chassis(ghw.WithDisableWarnings())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.Logger.Errorln("ghw.Chassis()", err)
|
a.Logger.Debugln("ghw.Chassis()", err)
|
||||||
} else {
|
} else {
|
||||||
if chassis.Vendor != "" || chassis.Version != "" {
|
if chassis.Vendor != "" || chassis.Version != "" {
|
||||||
wmiInfo["make_model"] = fmt.Sprintf("%s %s", chassis.Vendor, chassis.Version)
|
wmiInfo["make_model"] = fmt.Sprintf("%s %s", chassis.Vendor, chassis.Version)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if runtime.GOOS == "darwin" {
|
||||||
|
opts := a.NewCMDOpts()
|
||||||
|
opts.Command = "sysctl hw.model"
|
||||||
|
out := a.CmdV2(opts)
|
||||||
|
wmiInfo["make_model"] = strings.ReplaceAll(out.Stdout, "hw.model: ", "")
|
||||||
|
}
|
||||||
|
|
||||||
// gfx cards
|
// gfx cards
|
||||||
|
|
||||||
gpu, err := ghw.GPU(ghw.WithDisableWarnings())
|
gpu, err := ghw.GPU(ghw.WithDisableWarnings())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.Logger.Errorln("ghw.GPU()", err)
|
a.Logger.Debugln("ghw.GPU()", err)
|
||||||
} else {
|
} else {
|
||||||
for _, i := range gpu.GraphicsCards {
|
for _, i := range gpu.GraphicsCards {
|
||||||
if i.DeviceInfo != nil {
|
if i.DeviceInfo != nil {
|
||||||
|
@ -140,34 +140,57 @@ func (a *Agent) Install(i *Installer) {
|
|||||||
installerMeshSystemEXE = a.MeshSystemEXE
|
installerMeshSystemEXE = a.MeshSystemEXE
|
||||||
}
|
}
|
||||||
|
|
||||||
var meshNodeID string
|
var meshNodeID, meshOutput string
|
||||||
|
|
||||||
if runtime.GOOS == "windows" && !i.NoMesh {
|
if !i.NoMesh && runtime.GOOS != "linux" {
|
||||||
mesh := filepath.Join(a.ProgramDir, a.MeshInstaller)
|
switch runtime.GOOS {
|
||||||
if i.LocalMesh == "" {
|
case "windows":
|
||||||
|
meshOutput = filepath.Join(a.ProgramDir, a.MeshInstaller)
|
||||||
|
case "darwin":
|
||||||
|
tmp, err := createTmpFile()
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Fatalln("Failed to create mesh temp file", err)
|
||||||
|
}
|
||||||
|
meshOutput = tmp.Name()
|
||||||
|
os.Chmod(meshOutput, 0755)
|
||||||
|
defer os.Remove(meshOutput)
|
||||||
|
defer os.Remove(meshOutput + ".msh")
|
||||||
|
}
|
||||||
|
|
||||||
|
if runtime.GOOS == "windows" && i.LocalMesh != "" {
|
||||||
|
err := copyFile(i.LocalMesh, meshOutput)
|
||||||
|
if err != nil {
|
||||||
|
a.installerMsg(err.Error(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
a.Logger.Infoln("Downloading mesh agent...")
|
a.Logger.Infoln("Downloading mesh agent...")
|
||||||
payload := map[string]string{"goarch": a.GoArch, "plat": a.Platform}
|
payload := map[string]string{"goarch": a.GoArch, "plat": a.Platform}
|
||||||
r, err := rClient.R().SetBody(payload).SetOutput(mesh).Post(fmt.Sprintf("%s/api/v3/meshexe/", baseURL))
|
r, err := rClient.R().SetBody(payload).SetOutput(meshOutput).Post(fmt.Sprintf("%s/api/v3/meshexe/", baseURL))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.installerMsg(fmt.Sprintf("Failed to download mesh agent: %s", err.Error()), "error", i.Silent)
|
a.installerMsg(fmt.Sprintf("Failed to download mesh agent: %s", err.Error()), "error", i.Silent)
|
||||||
}
|
}
|
||||||
if r.StatusCode() != 200 {
|
if r.StatusCode() != 200 {
|
||||||
a.installerMsg(fmt.Sprintf("Unable to download the mesh agent from the RMM. %s", r.String()), "error", i.Silent)
|
a.installerMsg(fmt.Sprintf("Unable to download the mesh agent from the RMM. %s", r.String()), "error", i.Silent)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
err := copyFile(i.LocalMesh, mesh)
|
|
||||||
if err != nil {
|
|
||||||
a.installerMsg(err.Error(), "error", i.Silent)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a.Logger.Infoln("Installing mesh agent...")
|
a.Logger.Infoln("Installing mesh agent...")
|
||||||
a.Logger.Debugln("Mesh agent:", mesh)
|
a.Logger.Debugln("Mesh agent:", meshOutput)
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
|
|
||||||
meshNodeID, err = a.installMesh(mesh, installerMeshSystemEXE, i.Proxy)
|
if runtime.GOOS == "windows" {
|
||||||
if err != nil {
|
meshNodeID, err = a.installMesh(meshOutput, installerMeshSystemEXE, i.Proxy)
|
||||||
a.installerMsg(fmt.Sprintf("Failed to install mesh agent: %s", err.Error()), "error", i.Silent)
|
if err != nil {
|
||||||
|
a.installerMsg(fmt.Sprintf("Failed to install mesh agent: %s", err.Error()), "error", i.Silent)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
opts := a.NewCMDOpts()
|
||||||
|
opts.Command = fmt.Sprintf("%s -install", meshOutput)
|
||||||
|
out := a.CmdV2(opts)
|
||||||
|
if out.Status.Exit != 0 {
|
||||||
|
a.Logger.Fatalln("Error installing mesh agent:", out.Stderr)
|
||||||
|
}
|
||||||
|
fmt.Println(out.Stdout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,6 +242,47 @@ func (a *Agent) Install(i *Installer) {
|
|||||||
// check in once
|
// check in once
|
||||||
a.DoNatsCheckIn()
|
a.DoNatsCheckIn()
|
||||||
|
|
||||||
|
if runtime.GOOS == "darwin" {
|
||||||
|
os.MkdirAll(nixAgentDir, 0755)
|
||||||
|
self, _ := os.Executable()
|
||||||
|
copyFile(self, nixAgentBin)
|
||||||
|
os.Chmod(nixAgentBin, 0755)
|
||||||
|
svc := fmt.Sprintf(`
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>Label</key>
|
||||||
|
<string>%s</string>
|
||||||
|
|
||||||
|
<key>ServiceDescription</key>
|
||||||
|
<string>TacticalAgent Service</string>
|
||||||
|
|
||||||
|
<key>ProgramArguments</key>
|
||||||
|
<array>
|
||||||
|
<string>%s</string>
|
||||||
|
<string>-m</string>
|
||||||
|
<string>svc</string>
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<key>WorkingDirectory</key>
|
||||||
|
<string>%s/</string>
|
||||||
|
|
||||||
|
<key>RunAtLoad</key>
|
||||||
|
<true/>
|
||||||
|
|
||||||
|
<key>KeepAlive</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
`, macPlistName, nixAgentBin, nixAgentDir)
|
||||||
|
|
||||||
|
os.WriteFile(macPlistPath, []byte(svc), 0644)
|
||||||
|
opts := a.NewCMDOpts()
|
||||||
|
opts.Command = fmt.Sprintf("launchctl bootstrap system %s", macPlistPath)
|
||||||
|
a.CmdV2(opts)
|
||||||
|
}
|
||||||
|
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
// send software api
|
// send software api
|
||||||
a.SendSoftware()
|
a.SendSoftware()
|
||||||
|
@ -15,17 +15,16 @@ https://license.tacticalrmm.com
|
|||||||
package agent
|
package agent
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
trmm "github.com/wh1te909/trmm-shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
etcConfig = "/etc/tacticalagent"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (a *Agent) checkExistingAndRemove(silent bool) {}
|
|
||||||
|
|
||||||
func (a *Agent) installerMsg(msg, alert string, silent bool) {
|
func (a *Agent) installerMsg(msg, alert string, silent bool) {
|
||||||
if alert == "error" {
|
if alert == "error" {
|
||||||
a.Logger.Fatalln(msg)
|
a.Logger.Fatalln(msg)
|
||||||
@ -51,6 +50,31 @@ func createAgentConfig(baseurl, agentid, apiurl, token, agentpk, cert, proxy, me
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Agent) checkExistingAndRemove(silent bool) {
|
||||||
|
if runtime.GOOS == "darwin" {
|
||||||
|
if trmm.FileExists(a.MeshSystemEXE) {
|
||||||
|
a.Logger.Infoln("Existing meshagent found, attempting to remove...")
|
||||||
|
uopts := a.NewCMDOpts()
|
||||||
|
uopts.Command = fmt.Sprintf("%s -fulluninstall", a.MeshSystemEXE)
|
||||||
|
uout := a.CmdV2(uopts)
|
||||||
|
fmt.Println(uout.Stdout)
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
if trmm.FileExists(macPlistPath) {
|
||||||
|
a.Logger.Infoln("Existing tacticalagent plist found, attempting to remove...")
|
||||||
|
opts := a.NewCMDOpts()
|
||||||
|
opts.Command = fmt.Sprintf("launchctl bootout system %s", macPlistPath)
|
||||||
|
a.CmdV2(opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
os.RemoveAll(macMeshSvcDir)
|
||||||
|
os.Remove(etcConfig)
|
||||||
|
os.RemoveAll(nixAgentDir)
|
||||||
|
os.Remove(macPlistPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func DisableSleepHibernate() {}
|
func DisableSleepHibernate() {}
|
||||||
|
|
||||||
func EnablePing() {}
|
func EnablePing() {}
|
||||||
|
17
agent/svc.go
17
agent/svc.go
@ -12,6 +12,7 @@ https://license.tacticalrmm.com
|
|||||||
package agent
|
package agent
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -27,11 +28,13 @@ func (a *Agent) RunAsService() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) AgentSvc() {
|
func (a *Agent) AgentSvc() {
|
||||||
go a.GetPython(false)
|
if runtime.GOOS == "windows" {
|
||||||
|
go a.GetPython(false)
|
||||||
|
|
||||||
err := createWinTempDir()
|
err := createWinTempDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.Logger.Errorln("AgentSvc() createWinTempDir():", err)
|
a.Logger.Errorln("AgentSvc() createWinTempDir():", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
a.RunMigrations()
|
a.RunMigrations()
|
||||||
|
|
||||||
@ -53,8 +56,10 @@ func (a *Agent) AgentSvc() {
|
|||||||
go a.SyncMeshNodeID()
|
go a.SyncMeshNodeID()
|
||||||
|
|
||||||
time.Sleep(time.Duration(randRange(1, 3)) * time.Second)
|
time.Sleep(time.Duration(randRange(1, 3)) * time.Second)
|
||||||
a.AgentStartup()
|
if runtime.GOOS == "windows" {
|
||||||
a.SendSoftware()
|
a.AgentStartup()
|
||||||
|
a.SendSoftware()
|
||||||
|
}
|
||||||
|
|
||||||
checkInHelloTicker := time.NewTicker(time.Duration(randRange(30, 60)) * time.Second)
|
checkInHelloTicker := time.NewTicker(time.Duration(randRange(30, 60)) * time.Second)
|
||||||
checkInAgentInfoTicker := time.NewTicker(time.Duration(randRange(200, 400)) * time.Second)
|
checkInAgentInfoTicker := time.NewTicker(time.Duration(randRange(200, 400)) * time.Second)
|
||||||
|
2
main.go
2
main.go
@ -185,7 +185,7 @@ func setupLogging(level, to *string) {
|
|||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
case "windows":
|
case "windows":
|
||||||
logFile, _ = os.OpenFile(filepath.Join(os.Getenv("ProgramFiles"), "TacticalAgent", "agent.log"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0664)
|
logFile, _ = os.OpenFile(filepath.Join(os.Getenv("ProgramFiles"), "TacticalAgent", "agent.log"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0664)
|
||||||
case "linux":
|
default:
|
||||||
logFile, _ = os.OpenFile(filepath.Join("/var/log/", "tacticalagent.log"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0664)
|
logFile, _ = os.OpenFile(filepath.Join("/var/log/", "tacticalagent.log"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0664)
|
||||||
}
|
}
|
||||||
log.SetOutput(logFile)
|
log.SetOutput(logFile)
|
||||||
|
Loading…
Reference in New Issue
Block a user