merged
This commit is contained in:
commit
e2a1a74599
21 changed files with 338 additions and 579 deletions
|
|
@ -66,6 +66,9 @@ type Agent struct {
|
|||
Platform string
|
||||
GoArch string
|
||||
ServiceConfig *service.Config
|
||||
NatsServer string
|
||||
NatsProxyPath string
|
||||
NatsProxyPort string
|
||||
}
|
||||
|
||||
const (
|
||||
|
|
@ -75,6 +78,8 @@ const (
|
|||
meshSvcName = "mesh agent"
|
||||
)
|
||||
|
||||
var winTempDir = filepath.Join(os.Getenv("PROGRAMDATA"), "TacticalRMM")
|
||||
var winMeshDir = filepath.Join(os.Getenv("PROGRAMFILES"), "Mesh Agent")
|
||||
var natsCheckin = []string{"agent-hello", "agent-agentinfo", "agent-disks", "agent-winsvc", "agent-publicip", "agent-wmi"}
|
||||
|
||||
func New(logger *logrus.Logger, version string) *Agent {
|
||||
|
|
@ -143,9 +148,25 @@ func New(logger *logrus.Logger, version string) *Agent {
|
|||
},
|
||||
}
|
||||
|
||||
var natsProxyPath, natsProxyPort string
|
||||
if ac.NatsProxyPath == "" {
|
||||
natsProxyPath = "natsws"
|
||||
}
|
||||
|
||||
if ac.NatsProxyPort == "" {
|
||||
natsProxyPort = "443"
|
||||
}
|
||||
|
||||
// check if using nats standard tcp, otherwise use nats websockets by default
|
||||
var natsServer string
|
||||
if ac.NatsStandardPort != "" {
|
||||
natsServer = fmt.Sprintf("tls://%s:%s", ac.APIURL, ac.NatsStandardPort)
|
||||
} else {
|
||||
natsServer = fmt.Sprintf("wss://%s:%s", ac.APIURL, natsProxyPort)
|
||||
}
|
||||
|
||||
return &Agent{
|
||||
Hostname: info.Hostname,
|
||||
Arch: info.Architecture,
|
||||
BaseURL: ac.BaseURL,
|
||||
AgentID: ac.AgentID,
|
||||
ApiURL: ac.APIURL,
|
||||
|
|
@ -168,6 +189,9 @@ func New(logger *logrus.Logger, version string) *Agent {
|
|||
Platform: runtime.GOOS,
|
||||
GoArch: runtime.GOARCH,
|
||||
ServiceConfig: svcConf,
|
||||
NatsServer: natsServer,
|
||||
NatsProxyPath: natsProxyPath,
|
||||
NatsProxyPort: natsProxyPort,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -364,6 +388,7 @@ func (a *Agent) setupNatsOptions() []nats.Option {
|
|||
opts = append(opts, nats.RetryOnFailedConnect(true))
|
||||
opts = append(opts, nats.MaxReconnects(-1))
|
||||
opts = append(opts, nats.ReconnectBufSize(-1))
|
||||
opts = append(opts, nats.ProxyPath(a.NatsProxyPath))
|
||||
return opts
|
||||
}
|
||||
|
||||
|
|
@ -383,46 +408,47 @@ func (a *Agent) GetUninstallExe() string {
|
|||
}
|
||||
|
||||
func (a *Agent) CleanupAgentUpdates() {
|
||||
cderr := os.Chdir(a.ProgramDir)
|
||||
if cderr != nil {
|
||||
a.Logger.Errorln(cderr)
|
||||
return
|
||||
}
|
||||
// TODO remove a.ProgramDir, updates are now in winTempDir
|
||||
dirs := [2]string{winTempDir, a.ProgramDir}
|
||||
for _, dir := range dirs {
|
||||
err := os.Chdir(dir)
|
||||
if err != nil {
|
||||
a.Logger.Debugln("CleanupAgentUpdates()", dir, err)
|
||||
continue
|
||||
}
|
||||
|
||||
files, err := filepath.Glob("winagent-v*.exe")
|
||||
if err == nil {
|
||||
for _, f := range files {
|
||||
os.Remove(f)
|
||||
// TODO winagent-v* is deprecated
|
||||
globs := [2]string{"tacticalagent-v*", "winagent-v*"}
|
||||
for _, glob := range globs {
|
||||
files, err := filepath.Glob(glob)
|
||||
if err == nil {
|
||||
for _, f := range files {
|
||||
a.Logger.Debugln("CleanupAgentUpdates() Removing file:", f)
|
||||
os.Remove(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cderr = os.Chdir(os.Getenv("TMP"))
|
||||
if cderr != nil {
|
||||
a.Logger.Errorln(cderr)
|
||||
return
|
||||
}
|
||||
folders, err := filepath.Glob("tacticalrmm*")
|
||||
err := os.Chdir(os.Getenv("TMP"))
|
||||
if err == nil {
|
||||
for _, f := range folders {
|
||||
os.RemoveAll(f)
|
||||
dirs, err := filepath.Glob("tacticalrmm*")
|
||||
if err == nil {
|
||||
for _, f := range dirs {
|
||||
os.RemoveAll(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) RunPythonCode(code string, timeout int, args []string) (string, error) {
|
||||
content := []byte(code)
|
||||
dir, err := ioutil.TempDir("", "tacticalpy")
|
||||
if err != nil {
|
||||
a.Logger.Debugln(err)
|
||||
return "", err
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
tmpfn, _ := ioutil.TempFile(dir, "*.py")
|
||||
tmpfn, _ := ioutil.TempFile(winTempDir, "*.py")
|
||||
if _, err := tmpfn.Write(content); err != nil {
|
||||
a.Logger.Debugln(err)
|
||||
return "", err
|
||||
}
|
||||
defer os.Remove(tmpfn.Name())
|
||||
if err := tmpfn.Close(); err != nil {
|
||||
a.Logger.Debugln(err)
|
||||
return "", err
|
||||
|
|
@ -462,13 +488,12 @@ func (a *Agent) RunPythonCode(code string, timeout int, args []string) (string,
|
|||
|
||||
}
|
||||
|
||||
func (a *Agent) CreateTRMMTempDir() {
|
||||
// create the temp dir for running scripts
|
||||
dir := filepath.Join(os.TempDir(), "trmm")
|
||||
if !trmm.FileExists(dir) {
|
||||
err := os.Mkdir(dir, 0775)
|
||||
func createWinTempDir() error {
|
||||
if !trmm.FileExists(winTempDir) {
|
||||
err := os.Mkdir(winTempDir, 0775)
|
||||
if err != nil {
|
||||
a.Logger.Errorln(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright 2022 AmidaWare LLC.
|
||||
|
||||
|
|
@ -15,6 +18,7 @@ import (
|
|||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
|
@ -142,20 +146,23 @@ func NewAgentConfig() *rmm.AgentConfig {
|
|||
pk, _ := strconv.Atoi(agentpk)
|
||||
|
||||
ret := &rmm.AgentConfig{
|
||||
BaseURL: viper.GetString("baseurl"),
|
||||
AgentID: viper.GetString("agentid"),
|
||||
APIURL: viper.GetString("apiurl"),
|
||||
Token: viper.GetString("token"),
|
||||
AgentPK: agentpk,
|
||||
PK: pk,
|
||||
Cert: viper.GetString("cert"),
|
||||
Proxy: viper.GetString("proxy"),
|
||||
CustomMeshDir: viper.GetString("meshdir"),
|
||||
BaseURL: viper.GetString("baseurl"),
|
||||
AgentID: viper.GetString("agentid"),
|
||||
APIURL: viper.GetString("apiurl"),
|
||||
Token: viper.GetString("token"),
|
||||
AgentPK: agentpk,
|
||||
PK: pk,
|
||||
Cert: viper.GetString("cert"),
|
||||
Proxy: viper.GetString("proxy"),
|
||||
CustomMeshDir: viper.GetString("meshdir"),
|
||||
NatsProxyPath: viper.GetString("natsproxypath"),
|
||||
NatsProxyPort: viper.GetString("natsproxyport"),
|
||||
NatsStandardPort: viper.GetString("natsstandardport"),
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (a *Agent) RunScript(code string, shell string, args []string, timeout int) (stdout, stderr string, exitcode int, e error) {
|
||||
func (a *Agent) RunScript(code string, shell string, args []string, timeout int, runasuser bool) (stdout, stderr string, exitcode int, e error) {
|
||||
code = removeWinNewLines(code)
|
||||
content := []byte(code)
|
||||
|
||||
|
|
@ -202,6 +209,13 @@ func SetDetached() *syscall.SysProcAttr {
|
|||
return &syscall.SysProcAttr{Setpgid: true}
|
||||
}
|
||||
|
||||
func (a *Agent) seEnforcing() bool {
|
||||
opts := a.NewCMDOpts()
|
||||
opts.Command = "getenforce"
|
||||
out := a.CmdV2(opts)
|
||||
return out.Status.Exit == 0 && strings.Contains(out.Stdout, "Enforcing")
|
||||
}
|
||||
|
||||
func (a *Agent) AgentUpdate(url, inno, version string) {
|
||||
|
||||
self, err := os.Executable()
|
||||
|
|
@ -218,7 +232,7 @@ func (a *Agent) AgentUpdate(url, inno, version string) {
|
|||
defer os.Remove(f.Name())
|
||||
|
||||
a.Logger.Infof("Agent updating from %s to %s", a.Version, version)
|
||||
a.Logger.Infoln("Downloading agent update from", url)
|
||||
a.Logger.Debugln("Downloading agent update from", url)
|
||||
|
||||
rClient := resty.New()
|
||||
rClient.SetCloseConnection(true)
|
||||
|
|
@ -244,8 +258,36 @@ func (a *Agent) AgentUpdate(url, inno, version string) {
|
|||
os.Chmod(f.Name(), 0755)
|
||||
err = os.Rename(f.Name(), self)
|
||||
if err != nil {
|
||||
a.Logger.Errorln("AgentUpdate() os.Rename():", err)
|
||||
return
|
||||
a.Logger.Debugln("Detected /tmp on different filesystem")
|
||||
// rename does not work when src and dest are on different filesystems
|
||||
// so we need to manually copy it to the same fs then rename it
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
a.Logger.Errorln("AgentUpdate() os.Getwd():", err)
|
||||
return
|
||||
}
|
||||
// create a tmpfile in same fs as agent
|
||||
tmpfile := filepath.Join(cwd, GenerateAgentID())
|
||||
defer os.Remove(tmpfile)
|
||||
a.Logger.Debugln("Copying tmpfile from", f.Name(), "to", tmpfile)
|
||||
cperr := copyFile(f.Name(), tmpfile)
|
||||
if cperr != nil {
|
||||
a.Logger.Errorln("AgentUpdate() copyFile:", cperr)
|
||||
return
|
||||
}
|
||||
os.Chmod(tmpfile, 0755)
|
||||
rerr := os.Rename(tmpfile, self)
|
||||
if rerr != nil {
|
||||
a.Logger.Errorln("AgentUpdate() os.Rename():", rerr)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if a.seEnforcing() {
|
||||
se := a.NewCMDOpts()
|
||||
se.Command = fmt.Sprintf("restorecon -rv %s", self)
|
||||
out := a.CmdV2(se)
|
||||
a.Logger.Debugln("%+v\n", out)
|
||||
}
|
||||
|
||||
opts := a.NewCMDOpts()
|
||||
|
|
@ -479,7 +521,7 @@ func (a *Agent) installMesh(meshbin, exe, proxy string) (string, error) {
|
|||
return "not implemented", nil
|
||||
}
|
||||
|
||||
func CMDShell(shell string, cmdArgs []string, command string, timeout int, detached bool) (output [2]string, e error) {
|
||||
func CMDShell(shell string, cmdArgs []string, command string, timeout int, detached bool, runasuser bool) (output [2]string, e error) {
|
||||
return [2]string{"", ""}, nil
|
||||
}
|
||||
|
||||
|
|
@ -30,6 +30,7 @@ import (
|
|||
|
||||
rmm "github.com/amidaware/rmmagent/shared"
|
||||
ps "github.com/elastic/go-sysinfo"
|
||||
"github.com/fourcorelabs/wintoken"
|
||||
"github.com/go-ole/go-ole"
|
||||
"github.com/go-ole/go-ole/oleutil"
|
||||
"github.com/go-resty/resty/v2"
|
||||
|
|
@ -61,27 +62,34 @@ func NewAgentConfig() *rmm.AgentConfig {
|
|||
cert, _, _ := k.GetStringValue("Cert")
|
||||
proxy, _, _ := k.GetStringValue("Proxy")
|
||||
customMeshDir, _, _ := k.GetStringValue("MeshDir")
|
||||
natsProxyPath, _, _ := k.GetStringValue("NatsProxyPath")
|
||||
natsProxyPort, _, _ := k.GetStringValue("NatsProxyPort")
|
||||
natsStandardPort, _, _ := k.GetStringValue("NatsStandardPort")
|
||||
|
||||
return &rmm.AgentConfig{
|
||||
BaseURL: baseurl,
|
||||
AgentID: agentid,
|
||||
APIURL: apiurl,
|
||||
Token: token,
|
||||
AgentPK: agentpk,
|
||||
PK: pk,
|
||||
Cert: cert,
|
||||
Proxy: proxy,
|
||||
CustomMeshDir: customMeshDir,
|
||||
BaseURL: baseurl,
|
||||
AgentID: agentid,
|
||||
APIURL: apiurl,
|
||||
Token: token,
|
||||
AgentPK: agentpk,
|
||||
PK: pk,
|
||||
Cert: cert,
|
||||
Proxy: proxy,
|
||||
CustomMeshDir: customMeshDir,
|
||||
NatsProxyPath: natsProxyPath,
|
||||
NatsProxyPort: natsProxyPort,
|
||||
NatsStandardPort: natsStandardPort,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) RunScript(code string, shell string, args []string, timeout int) (stdout, stderr string, exitcode int, e error) {
|
||||
func (a *Agent) RunScript(code string, shell string, args []string, timeout int, runasuser bool) (stdout, stderr string, exitcode int, e error) {
|
||||
|
||||
content := []byte(code)
|
||||
|
||||
dir := filepath.Join(os.TempDir(), "trmm")
|
||||
if !trmm.FileExists(dir) {
|
||||
a.CreateTRMMTempDir()
|
||||
err := createWinTempDir()
|
||||
if err != nil {
|
||||
a.Logger.Errorln(err)
|
||||
return "", err.Error(), 85, err
|
||||
}
|
||||
|
||||
const defaultExitCode = 1
|
||||
|
|
@ -103,7 +111,7 @@ func (a *Agent) RunScript(code string, shell string, args []string, timeout int)
|
|||
ext = "*.bat"
|
||||
}
|
||||
|
||||
tmpfn, err := ioutil.TempFile(dir, ext)
|
||||
tmpfn, err := ioutil.TempFile(winTempDir, ext)
|
||||
if err != nil {
|
||||
a.Logger.Errorln(err)
|
||||
return "", err.Error(), 85, err
|
||||
|
|
@ -137,8 +145,16 @@ func (a *Agent) RunScript(code string, shell string, args []string, timeout int)
|
|||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
|
||||
defer cancel()
|
||||
|
||||
var timedOut bool = false
|
||||
var timedOut = false
|
||||
cmd := exec.Command(exe, cmdArgs...)
|
||||
if runasuser {
|
||||
token, err := wintoken.GetInteractiveToken(wintoken.TokenImpersonation)
|
||||
if err != nil {
|
||||
return "", err.Error(), 66, err
|
||||
}
|
||||
defer token.Close()
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{Token: syscall.Token(token.Token()), HideWindow: true}
|
||||
}
|
||||
cmd.Stdout = &outb
|
||||
cmd.Stderr = &errb
|
||||
|
||||
|
|
@ -224,7 +240,7 @@ func CMD(exe string, args []string, timeout int, detached bool) (output [2]strin
|
|||
return [2]string{CleanString(outb.String()), CleanString(errb.String())}, nil
|
||||
}
|
||||
|
||||
func CMDShell(shell string, cmdArgs []string, command string, timeout int, detached bool) (output [2]string, e error) {
|
||||
func CMDShell(shell string, cmdArgs []string, command string, timeout int, detached bool, runasuser bool) (output [2]string, e error) {
|
||||
var (
|
||||
outb bytes.Buffer
|
||||
errb bytes.Buffer
|
||||
|
|
@ -235,6 +251,8 @@ func CMDShell(shell string, cmdArgs []string, command string, timeout int, detac
|
|||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
|
||||
defer cancel()
|
||||
|
||||
sysProcAttr := &windows.SysProcAttr{}
|
||||
|
||||
if len(cmdArgs) > 0 && command == "" {
|
||||
switch shell {
|
||||
case "cmd":
|
||||
|
|
@ -248,9 +266,7 @@ func CMDShell(shell string, cmdArgs []string, command string, timeout int, detac
|
|||
switch shell {
|
||||
case "cmd":
|
||||
cmd = exec.Command("cmd.exe")
|
||||
cmd.SysProcAttr = &windows.SysProcAttr{
|
||||
CmdLine: fmt.Sprintf("cmd.exe /C %s", command),
|
||||
}
|
||||
sysProcAttr.CmdLine = fmt.Sprintf("cmd.exe /C %s", command)
|
||||
case "powershell":
|
||||
cmd = exec.Command("Powershell", "-NonInteractive", "-NoProfile", command)
|
||||
}
|
||||
|
|
@ -258,10 +274,20 @@ func CMDShell(shell string, cmdArgs []string, command string, timeout int, detac
|
|||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags
|
||||
if detached {
|
||||
cmd.SysProcAttr = &windows.SysProcAttr{
|
||||
CreationFlags: windows.DETACHED_PROCESS | windows.CREATE_NEW_PROCESS_GROUP,
|
||||
}
|
||||
sysProcAttr.CreationFlags = windows.DETACHED_PROCESS | windows.CREATE_NEW_PROCESS_GROUP
|
||||
}
|
||||
|
||||
if runasuser {
|
||||
token, err := wintoken.GetInteractiveToken(wintoken.TokenImpersonation)
|
||||
if err != nil {
|
||||
return [2]string{"", CleanString(err.Error())}, err
|
||||
}
|
||||
defer token.Close()
|
||||
sysProcAttr.Token = syscall.Token(token.Token())
|
||||
sysProcAttr.HideWindow = true
|
||||
}
|
||||
|
||||
cmd.SysProcAttr = sysProcAttr
|
||||
cmd.Stdout = &outb
|
||||
cmd.Stderr = &errb
|
||||
cmd.Start()
|
||||
|
|
@ -443,7 +469,7 @@ func (a *Agent) PlatVer() (string, error) {
|
|||
func EnablePing() {
|
||||
args := make([]string, 0)
|
||||
cmd := `netsh advfirewall firewall add rule name="ICMP Allow incoming V4 echo request" protocol=icmpv4:8,any dir=in action=allow`
|
||||
_, err := CMDShell("cmd", args, cmd, 10, false)
|
||||
_, err := CMDShell("cmd", args, cmd, 10, false, false)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
|
@ -464,7 +490,7 @@ func EnableRDP() {
|
|||
|
||||
args := make([]string, 0)
|
||||
cmd := `netsh advfirewall firewall set rule group="remote desktop" new enable=Yes`
|
||||
_, cerr := CMDShell("cmd", args, cmd, 10, false)
|
||||
_, cerr := CMDShell("cmd", args, cmd, 10, false, false)
|
||||
if cerr != nil {
|
||||
fmt.Println(cerr)
|
||||
}
|
||||
|
|
@ -491,15 +517,15 @@ func DisableSleepHibernate() {
|
|||
wg.Add(1)
|
||||
go func(c string) {
|
||||
defer wg.Done()
|
||||
_, _ = CMDShell("cmd", args, fmt.Sprintf("powercfg /set%svalueindex scheme_current sub_buttons lidaction 0", c), 5, false)
|
||||
_, _ = CMDShell("cmd", args, fmt.Sprintf("powercfg /x -standby-timeout-%s 0", c), 5, false)
|
||||
_, _ = CMDShell("cmd", args, fmt.Sprintf("powercfg /x -hibernate-timeout-%s 0", c), 5, false)
|
||||
_, _ = CMDShell("cmd", args, fmt.Sprintf("powercfg /x -disk-timeout-%s 0", c), 5, false)
|
||||
_, _ = CMDShell("cmd", args, fmt.Sprintf("powercfg /x -monitor-timeout-%s 0", c), 5, false)
|
||||
_, _ = CMDShell("cmd", args, fmt.Sprintf("powercfg /set%svalueindex scheme_current sub_buttons lidaction 0", c), 5, false, false)
|
||||
_, _ = CMDShell("cmd", args, fmt.Sprintf("powercfg /x -standby-timeout-%s 0", c), 5, false, false)
|
||||
_, _ = CMDShell("cmd", args, fmt.Sprintf("powercfg /x -hibernate-timeout-%s 0", c), 5, false, false)
|
||||
_, _ = CMDShell("cmd", args, fmt.Sprintf("powercfg /x -disk-timeout-%s 0", c), 5, false, false)
|
||||
_, _ = CMDShell("cmd", args, fmt.Sprintf("powercfg /x -monitor-timeout-%s 0", c), 5, false, false)
|
||||
}(i)
|
||||
}
|
||||
wg.Wait()
|
||||
_, _ = CMDShell("cmd", args, "powercfg -S SCHEME_CURRENT", 5, false)
|
||||
_, _ = CMDShell("cmd", args, "powercfg -S SCHEME_CURRENT", 5, false, false)
|
||||
}
|
||||
|
||||
// NewCOMObject creates a new COM object for the specifed ProgramID.
|
||||
|
|
@ -551,15 +577,17 @@ func (a *Agent) UninstallCleanup() {
|
|||
a.PatchMgmnt(false)
|
||||
a.CleanupAgentUpdates()
|
||||
CleanupSchedTasks()
|
||||
os.RemoveAll(winTempDir)
|
||||
}
|
||||
|
||||
func (a *Agent) AgentUpdate(url, inno, version string) {
|
||||
time.Sleep(time.Duration(randRange(1, 15)) * time.Second)
|
||||
a.KillHungUpdates()
|
||||
time.Sleep(1 * time.Second)
|
||||
a.CleanupAgentUpdates()
|
||||
updater := filepath.Join(a.ProgramDir, inno)
|
||||
updater := filepath.Join(winTempDir, inno)
|
||||
a.Logger.Infof("Agent updating from %s to %s", a.Version, version)
|
||||
a.Logger.Infoln("Downloading agent update from", url)
|
||||
a.Logger.Debugln("Downloading agent update from", url)
|
||||
|
||||
rClient := resty.New()
|
||||
rClient.SetCloseConnection(true)
|
||||
|
|
@ -580,14 +608,7 @@ func (a *Agent) AgentUpdate(url, inno, version string) {
|
|||
return
|
||||
}
|
||||
|
||||
dir, err := ioutil.TempDir("", "tacticalrmm")
|
||||
if err != nil {
|
||||
a.Logger.Errorln("Agentupdate create tempdir:", err)
|
||||
CMD("net", []string{"start", winSvcName}, 10, false)
|
||||
return
|
||||
}
|
||||
|
||||
innoLogFile := filepath.Join(dir, "tacticalrmm.txt")
|
||||
innoLogFile := filepath.Join(winTempDir, fmt.Sprintf("tacticalagent_update_v%s.txt", version))
|
||||
|
||||
args := []string{"/C", updater, "/VERYSILENT", fmt.Sprintf("/LOG=%s", innoLogFile)}
|
||||
cmd := exec.Command("cmd.exe", args...)
|
||||
|
|
@ -633,13 +654,12 @@ func (a *Agent) AgentUninstall(code string) {
|
|||
}
|
||||
|
||||
func (a *Agent) addDefenderExlusions() {
|
||||
code := `
|
||||
Add-MpPreference -ExclusionPath 'C:\Program Files\TacticalAgent\*'
|
||||
Add-MpPreference -ExclusionPath 'C:\Windows\Temp\winagent-v*.exe'
|
||||
Add-MpPreference -ExclusionPath 'C:\Windows\Temp\trmm\*'
|
||||
Add-MpPreference -ExclusionPath 'C:\Program Files\Mesh Agent\*'
|
||||
`
|
||||
_, _, _, err := a.RunScript(code, "powershell", []string{}, 20)
|
||||
code := fmt.Sprintf(`
|
||||
Add-MpPreference -ExclusionPath '%s\*'
|
||||
Add-MpPreference -ExclusionPath '%s\*'
|
||||
Add-MpPreference -ExclusionPath '%s\*'
|
||||
`, winTempDir, a.ProgramDir, winMeshDir)
|
||||
_, _, _, err := a.RunScript(code, "powershell", []string{}, 20, false)
|
||||
if err != nil {
|
||||
a.Logger.Debugln(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ https://license.tacticalrmm.com
|
|||
package agent
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
|
|
@ -78,8 +77,7 @@ func (a *Agent) NatsMessage(nc *nats.Conn, mode string) {
|
|||
|
||||
func (a *Agent) DoNatsCheckIn() {
|
||||
opts := a.setupNatsOptions()
|
||||
server := fmt.Sprintf("tls://%s:4222", a.ApiURL)
|
||||
nc, err := nats.Connect(server, opts...)
|
||||
nc, err := nats.Connect(a.NatsServer, opts...)
|
||||
if err != nil {
|
||||
a.Logger.Errorln(err)
|
||||
return
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ type ScriptCheckResult struct {
|
|||
// ScriptCheck runs either bat, powershell or python script
|
||||
func (a *Agent) ScriptCheck(data rmm.Check, r *resty.Client) {
|
||||
start := time.Now()
|
||||
stdout, stderr, retcode, _ := a.RunScript(data.Script.Code, data.Script.Shell, data.ScriptArgs, data.Timeout)
|
||||
stdout, stderr, retcode, _ := a.RunScript(data.Script.Code, data.Script.Shell, data.ScriptArgs, data.Timeout, data.Script.RunAsUser)
|
||||
|
||||
payload := ScriptCheckResult{
|
||||
ID: data.CheckPK,
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ func (a *Agent) InstallChoco() {
|
|||
return
|
||||
}
|
||||
|
||||
_, _, exitcode, err := a.RunScript(string(r.Body()), "powershell", []string{}, 900)
|
||||
_, _, exitcode, err := a.RunScript(string(r.Body()), "powershell", []string{}, 900, false)
|
||||
if err != nil {
|
||||
a.Logger.Debugln(err)
|
||||
a.rClient.R().SetBody(result).Post(url)
|
||||
|
|
|
|||
|
|
@ -82,11 +82,6 @@ func (a *Agent) Install(i *Installer) {
|
|||
|
||||
a.Logger.Debugln("API:", i.SaltMaster)
|
||||
|
||||
terr := TestTCP(fmt.Sprintf("%s:4222", i.SaltMaster))
|
||||
if terr != nil {
|
||||
a.installerMsg(fmt.Sprintf("ERROR: Either port 4222 TCP is not open on your RMM, or nats.service is not running.\n\n%s", terr.Error()), "error", i.Silent)
|
||||
}
|
||||
|
||||
baseURL := u.Scheme + "://" + u.Host
|
||||
a.Logger.Debugln("Base URL:", baseURL)
|
||||
|
||||
|
|
@ -138,14 +133,6 @@ func (a *Agent) Install(i *Installer) {
|
|||
rClient.SetProxy(i.Proxy)
|
||||
}
|
||||
|
||||
var arch string
|
||||
switch a.Arch {
|
||||
case "x86_64":
|
||||
arch = "64"
|
||||
case "x86":
|
||||
arch = "32"
|
||||
}
|
||||
|
||||
var installerMeshSystemEXE string
|
||||
if len(i.MeshDir) > 0 {
|
||||
installerMeshSystemEXE = filepath.Join(i.MeshDir, "MeshAgent.exe")
|
||||
|
|
@ -159,7 +146,7 @@ func (a *Agent) Install(i *Installer) {
|
|||
mesh := filepath.Join(a.ProgramDir, a.MeshInstaller)
|
||||
if i.LocalMesh == "" {
|
||||
a.Logger.Infoln("Downloading mesh agent...")
|
||||
payload := map[string]string{"arch": arch, "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))
|
||||
if err != nil {
|
||||
a.installerMsg(fmt.Sprintf("Failed to download mesh agent: %s", err.Error()), "error", i.Silent)
|
||||
|
|
@ -237,13 +224,16 @@ func (a *Agent) Install(i *Installer) {
|
|||
a.SendSoftware()
|
||||
|
||||
a.Logger.Debugln("Creating temp dir")
|
||||
a.CreateTRMMTempDir()
|
||||
err := createWinTempDir()
|
||||
if err != nil {
|
||||
a.Logger.Errorln("Install() createWinTempDir():", err)
|
||||
}
|
||||
|
||||
a.Logger.Debugln("Disabling automatic windows updates")
|
||||
a.PatchMgmnt(true)
|
||||
|
||||
a.Logger.Infoln("Installing service...")
|
||||
err := a.InstallService()
|
||||
err = a.InstallService()
|
||||
if err != nil {
|
||||
a.installerMsg(err.Error(), "error", i.Silent)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright 2022 AmidaWare LLC.
|
||||
|
||||
|
|
@ -64,9 +64,16 @@ func (a *Agent) KillHungUpdates() {
|
|||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// winagent-v* is deprecated
|
||||
if strings.Contains(p.Exe, "winagent-v") {
|
||||
a.Logger.Debugln("killing process", p.Exe)
|
||||
KillProc(int32(p.PID))
|
||||
}
|
||||
|
||||
if strings.Contains(p.Exe, "tacticalagent-v") {
|
||||
a.Logger.Debugln("killing process", p.Exe)
|
||||
KillProc(int32(p.PID))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
10
agent/rpc.go
10
agent/rpc.go
|
|
@ -40,6 +40,7 @@ type NatsMsg struct {
|
|||
PatchMgmt bool `json:"patch_mgmt"`
|
||||
ID int `json:"id"`
|
||||
Code string `json:"code"`
|
||||
RunAsUser bool `json:"run_as_user"`
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
@ -54,8 +55,7 @@ func (a *Agent) RunRPC() {
|
|||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
opts := a.setupNatsOptions()
|
||||
server := fmt.Sprintf("tls://%s:4222", a.ApiURL)
|
||||
nc, err := nats.Connect(server, opts...)
|
||||
nc, err := nats.Connect(a.NatsServer, opts...)
|
||||
if err != nil {
|
||||
a.Logger.Fatalln("RunRPC() nats.Connect()", err)
|
||||
}
|
||||
|
|
@ -178,7 +178,7 @@ func (a *Agent) RunRPC() {
|
|||
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
out, _ := CMDShell(p.Data["shell"], []string{}, p.Data["command"], p.Timeout, false)
|
||||
out, _ := CMDShell(p.Data["shell"], []string{}, p.Data["command"], p.Timeout, false, p.RunAsUser)
|
||||
a.Logger.Debugln(out)
|
||||
if out[1] != "" {
|
||||
ret.Encode(out[1])
|
||||
|
|
@ -258,7 +258,7 @@ func (a *Agent) RunRPC() {
|
|||
var resultData rmm.RunScriptResp
|
||||
ret := codec.NewEncoderBytes(&resp, new(codec.MsgpackHandle))
|
||||
start := time.Now()
|
||||
stdout, stderr, retcode, err := a.RunScript(p.Data["code"], p.Data["shell"], p.ScriptArgs, p.Timeout)
|
||||
stdout, stderr, retcode, err := a.RunScript(p.Data["code"], p.Data["shell"], p.ScriptArgs, p.Timeout, p.RunAsUser)
|
||||
resultData.ExecTime = time.Since(start).Seconds()
|
||||
resultData.ID = p.ID
|
||||
|
||||
|
|
@ -288,7 +288,7 @@ func (a *Agent) RunRPC() {
|
|||
var retData rmm.RunScriptResp
|
||||
ret := codec.NewEncoderBytes(&resp, new(codec.MsgpackHandle))
|
||||
start := time.Now()
|
||||
stdout, stderr, retcode, err := a.RunScript(p.Data["code"], p.Data["shell"], p.ScriptArgs, p.Timeout)
|
||||
stdout, stderr, retcode, err := a.RunScript(p.Data["code"], p.Data["shell"], p.ScriptArgs, p.Timeout, p.RunAsUser)
|
||||
|
||||
retData.ExecTime = time.Since(start).Seconds()
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ https://license.tacticalrmm.com
|
|||
package agent
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
|
@ -30,7 +29,10 @@ func (a *Agent) RunAsService() {
|
|||
func (a *Agent) AgentSvc() {
|
||||
go a.GetPython(false)
|
||||
|
||||
a.CreateTRMMTempDir()
|
||||
err := createWinTempDir()
|
||||
if err != nil {
|
||||
a.Logger.Errorln("AgentSvc() createWinTempDir():", err)
|
||||
}
|
||||
a.RunMigrations()
|
||||
|
||||
sleepDelay := randRange(14, 22)
|
||||
|
|
@ -38,8 +40,7 @@ func (a *Agent) AgentSvc() {
|
|||
time.Sleep(time.Duration(sleepDelay) * time.Second)
|
||||
|
||||
opts := a.setupNatsOptions()
|
||||
server := fmt.Sprintf("tls://%s:4222", a.ApiURL)
|
||||
nc, err := nats.Connect(server, opts...)
|
||||
nc, err := nats.Connect(a.NatsServer, opts...)
|
||||
if err != nil {
|
||||
a.Logger.Fatalln("AgentSvc() nats.Connect()", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ func (a *Agent) RunTask(id int) error {
|
|||
|
||||
action_start := time.Now()
|
||||
if action.ActionType == "script" {
|
||||
stdout, stderr, retcode, err := a.RunScript(action.Code, action.Shell, action.Args, action.Timeout)
|
||||
stdout, stderr, retcode, err := a.RunScript(action.Code, action.Shell, action.Args, action.Timeout, action.RunAsUser)
|
||||
|
||||
if err != nil {
|
||||
a.Logger.Debugln(err)
|
||||
|
|
@ -83,7 +83,7 @@ func (a *Agent) RunTask(id int) error {
|
|||
|
||||
} else if action.ActionType == "cmd" {
|
||||
// out[0] == stdout, out[1] == stderr
|
||||
out, err := CMDShell(action.Shell, []string{}, action.Command, action.Timeout, false)
|
||||
out, err := CMDShell(action.Shell, []string{}, action.Command, action.Timeout, false, action.RunAsUser)
|
||||
|
||||
if err != nil {
|
||||
a.Logger.Debugln(err)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
goDebug "runtime/debug"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
|
@ -138,10 +139,13 @@ func GenerateAgentID() string {
|
|||
func ShowVersionInfo(ver string) {
|
||||
fmt.Println("Tactical RMM Agent:", ver)
|
||||
fmt.Println("Arch:", runtime.GOARCH)
|
||||
fmt.Println("Go version:", runtime.Version())
|
||||
if runtime.GOOS == "windows" {
|
||||
fmt.Println("Program Directory:", filepath.Join(os.Getenv("ProgramFiles"), progFilesName))
|
||||
}
|
||||
bi, ok := goDebug.ReadBuildInfo()
|
||||
if ok {
|
||||
fmt.Println(bi.String())
|
||||
}
|
||||
}
|
||||
|
||||
// TotalRAM returns total RAM in GB
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue