Release 2.4.3

This commit is contained in:
wh1te909 2022-12-04 15:10:28 -08:00
commit e9fd05bd91
16 changed files with 259 additions and 111 deletions

View File

@ -40,35 +40,37 @@ import (
// Agent struct // Agent struct
type Agent struct { type Agent struct {
Hostname string Hostname string
Arch string Arch string
AgentID string AgentID string
BaseURL string BaseURL string
ApiURL string ApiURL string
Token string Token string
AgentPK int AgentPK int
Cert string Cert string
ProgramDir string ProgramDir string
EXE string EXE string
SystemDrive string SystemDrive string
MeshInstaller string MeshInstaller string
MeshSystemEXE string MeshSystemEXE string
MeshSVC string MeshSVC string
PyBin string PyBin string
Headers map[string]string Headers map[string]string
Logger *logrus.Logger Logger *logrus.Logger
Version string Version string
Debug bool Debug bool
rClient *resty.Client rClient *resty.Client
Proxy string Proxy string
LogTo string LogTo string
LogFile *os.File LogFile *os.File
Platform string Platform string
GoArch string GoArch string
ServiceConfig *service.Config ServiceConfig *service.Config
NatsServer string NatsServer string
NatsProxyPath string NatsProxyPath string
NatsProxyPort string NatsProxyPort string
NatsPingInterval int
NatsWSCompression bool
} }
const ( const (
@ -89,6 +91,7 @@ const (
var winTempDir = filepath.Join(os.Getenv("PROGRAMDATA"), "TacticalRMM") var winTempDir = filepath.Join(os.Getenv("PROGRAMDATA"), "TacticalRMM")
var winMeshDir = filepath.Join(os.Getenv("PROGRAMFILES"), "Mesh Agent") var winMeshDir = filepath.Join(os.Getenv("PROGRAMFILES"), "Mesh Agent")
var natsCheckin = []string{"agent-hello", "agent-agentinfo", "agent-disks", "agent-winsvc", "agent-publicip", "agent-wmi"} var natsCheckin = []string{"agent-hello", "agent-agentinfo", "agent-disks", "agent-winsvc", "agent-publicip", "agent-wmi"}
var limitNatsData = []string{"agent-winsvc", "agent-wmi"}
func New(logger *logrus.Logger, version string) *Agent { func New(logger *logrus.Logger, version string) *Agent {
host, _ := ps.Host() host, _ := ps.Host()
@ -170,39 +173,50 @@ func New(logger *logrus.Logger, version string) *Agent {
// check if using nats standard tcp, otherwise use nats websockets by default // check if using nats standard tcp, otherwise use nats websockets by default
var natsServer string var natsServer string
var natsWsCompression bool
if ac.NatsStandardPort != "" { if ac.NatsStandardPort != "" {
natsServer = fmt.Sprintf("tls://%s:%s", ac.APIURL, ac.NatsStandardPort) natsServer = fmt.Sprintf("tls://%s:%s", ac.APIURL, ac.NatsStandardPort)
} else { } else {
natsServer = fmt.Sprintf("wss://%s:%s", ac.APIURL, natsProxyPort) natsServer = fmt.Sprintf("wss://%s:%s", ac.APIURL, natsProxyPort)
natsWsCompression = true
}
var natsPingInterval int
if ac.NatsPingInterval == 0 {
natsPingInterval = randRange(35, 45)
} else {
natsPingInterval = ac.NatsPingInterval
} }
return &Agent{ return &Agent{
Hostname: info.Hostname, Hostname: info.Hostname,
BaseURL: ac.BaseURL, BaseURL: ac.BaseURL,
AgentID: ac.AgentID, AgentID: ac.AgentID,
ApiURL: ac.APIURL, ApiURL: ac.APIURL,
Token: ac.Token, Token: ac.Token,
AgentPK: ac.PK, AgentPK: ac.PK,
Cert: ac.Cert, Cert: ac.Cert,
ProgramDir: pd, ProgramDir: pd,
EXE: exe, EXE: exe,
SystemDrive: sd, SystemDrive: sd,
MeshInstaller: "meshagent.exe", MeshInstaller: "meshagent.exe",
MeshSystemEXE: MeshSysExe, MeshSystemEXE: MeshSysExe,
MeshSVC: meshSvcName, MeshSVC: meshSvcName,
PyBin: pybin, PyBin: pybin,
Headers: headers, Headers: headers,
Logger: logger, Logger: logger,
Version: version, Version: version,
Debug: logger.IsLevelEnabled(logrus.DebugLevel), Debug: logger.IsLevelEnabled(logrus.DebugLevel),
rClient: restyC, rClient: restyC,
Proxy: ac.Proxy, Proxy: ac.Proxy,
Platform: runtime.GOOS, Platform: runtime.GOOS,
GoArch: runtime.GOARCH, GoArch: runtime.GOARCH,
ServiceConfig: svcConf, ServiceConfig: svcConf,
NatsServer: natsServer, NatsServer: natsServer,
NatsProxyPath: natsProxyPath, NatsProxyPath: natsProxyPath,
NatsProxyPort: natsProxyPort, NatsProxyPort: natsProxyPort,
NatsPingInterval: natsPingInterval,
NatsWSCompression: natsWsCompression,
} }
} }
@ -220,7 +234,7 @@ type CmdOptions struct {
IsScript bool IsScript bool
IsExecutable bool IsExecutable bool
Detached bool Detached bool
Env []string EnvVars []string
} }
func (a *Agent) NewCMDOpts() *CmdOptions { func (a *Agent) NewCMDOpts() *CmdOptions {
@ -249,10 +263,10 @@ func (a *Agent) CmdV2(c *CmdOptions) CmdStatus {
}) })
} }
if len(c.Env) > 0 { if len(c.EnvVars) > 0 {
cmdOptions.BeforeExec = append(cmdOptions.BeforeExec, func(cmd *exec.Cmd) { cmdOptions.BeforeExec = append(cmdOptions.BeforeExec, func(cmd *exec.Cmd) {
cmd.Env = os.Environ() cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, c.Env...) cmd.Env = append(cmd.Env, c.EnvVars...)
}) })
} }
@ -398,14 +412,30 @@ func (a *Agent) SyncMeshNodeID() {
} }
func (a *Agent) setupNatsOptions() []nats.Option { func (a *Agent) setupNatsOptions() []nats.Option {
reconnectWait := randRange(2, 8)
opts := make([]nats.Option, 0) opts := make([]nats.Option, 0)
opts = append(opts, nats.Name("TacticalRMM")) opts = append(opts, nats.Name(a.AgentID))
opts = append(opts, nats.UserInfo(a.AgentID, a.Token)) opts = append(opts, nats.UserInfo(a.AgentID, a.Token))
opts = append(opts, nats.ReconnectWait(time.Second*5)) opts = append(opts, nats.ReconnectWait(time.Duration(reconnectWait)*time.Second))
opts = append(opts, nats.RetryOnFailedConnect(true)) opts = append(opts, nats.RetryOnFailedConnect(true))
opts = append(opts, nats.PingInterval(time.Duration(a.NatsPingInterval)*time.Second))
opts = append(opts, nats.Compression(a.NatsWSCompression))
opts = append(opts, nats.MaxReconnects(-1)) opts = append(opts, nats.MaxReconnects(-1))
opts = append(opts, nats.ReconnectBufSize(-1)) opts = append(opts, nats.ReconnectBufSize(-1))
opts = append(opts, nats.ProxyPath(a.NatsProxyPath)) opts = append(opts, nats.ProxyPath(a.NatsProxyPath))
opts = append(opts, nats.ReconnectJitter(500*time.Millisecond, 4*time.Second))
opts = append(opts, nats.DisconnectErrHandler(func(nc *nats.Conn, err error) {
a.Logger.Debugln("NATS disconnected:", err)
a.Logger.Debugf("%+v\n", nc.Statistics)
}))
opts = append(opts, nats.ReconnectHandler(func(nc *nats.Conn) {
a.Logger.Debugln("NATS reconnected")
a.Logger.Debugf("%+v\n", nc.Statistics)
}))
opts = append(opts, nats.ErrorHandler(func(nc *nats.Conn, sub *nats.Subscription, err error) {
a.Logger.Errorln("NATS error:", err)
a.Logger.Errorf("%+v\n", sub)
}))
return opts return opts
} }

View File

@ -158,11 +158,12 @@ func NewAgentConfig() *rmm.AgentConfig {
NatsProxyPath: viper.GetString("natsproxypath"), NatsProxyPath: viper.GetString("natsproxypath"),
NatsProxyPort: viper.GetString("natsproxyport"), NatsProxyPort: viper.GetString("natsproxyport"),
NatsStandardPort: viper.GetString("natsstandardport"), NatsStandardPort: viper.GetString("natsstandardport"),
NatsPingInterval: viper.GetInt("natspinginterval"),
} }
return ret return ret
} }
func (a *Agent) RunScript(code string, shell string, args []string, timeout int, runasuser bool) (stdout, stderr string, exitcode int, e error) { func (a *Agent) RunScript(code string, shell string, args []string, timeout int, runasuser bool, envVars []string) (stdout, stderr string, exitcode int, e error) {
code = removeWinNewLines(code) code = removeWinNewLines(code)
content := []byte(code) content := []byte(code)
@ -192,6 +193,7 @@ func (a *Agent) RunScript(code string, shell string, args []string, timeout int,
opts.IsScript = true opts.IsScript = true
opts.Shell = f.Name() opts.Shell = f.Name()
opts.Args = args opts.Args = args
opts.EnvVars = envVars
opts.Timeout = time.Duration(timeout) opts.Timeout = time.Duration(timeout)
out := a.CmdV2(opts) out := a.CmdV2(opts)
retError := "" retError := ""
@ -491,6 +493,9 @@ func (a *Agent) GetWMIInfo() map[string]interface{} {
} }
// windows only below TODO add into stub file // windows only below TODO add into stub file
func (a *Agent) GetAgentCheckInConfig(ret AgentCheckInConfig) AgentCheckInConfig {
return ret
}
func (a *Agent) PlatVer() (string, error) { return "", nil } func (a *Agent) PlatVer() (string, error) { return "", nil }

View File

@ -65,6 +65,8 @@ func NewAgentConfig() *rmm.AgentConfig {
natsProxyPath, _, _ := k.GetStringValue("NatsProxyPath") natsProxyPath, _, _ := k.GetStringValue("NatsProxyPath")
natsProxyPort, _, _ := k.GetStringValue("NatsProxyPort") natsProxyPort, _, _ := k.GetStringValue("NatsProxyPort")
natsStandardPort, _, _ := k.GetStringValue("NatsStandardPort") natsStandardPort, _, _ := k.GetStringValue("NatsStandardPort")
natsPingInterval, _, _ := k.GetStringValue("NatsPingInterval")
npi, _ := strconv.Atoi(natsPingInterval)
return &rmm.AgentConfig{ return &rmm.AgentConfig{
BaseURL: baseurl, BaseURL: baseurl,
@ -79,10 +81,11 @@ func NewAgentConfig() *rmm.AgentConfig {
NatsProxyPath: natsProxyPath, NatsProxyPath: natsProxyPath,
NatsProxyPort: natsProxyPort, NatsProxyPort: natsProxyPort,
NatsStandardPort: natsStandardPort, NatsStandardPort: natsStandardPort,
NatsPingInterval: npi,
} }
} }
func (a *Agent) RunScript(code string, shell string, args []string, timeout int, runasuser bool) (stdout, stderr string, exitcode int, e error) { func (a *Agent) RunScript(code string, shell string, args []string, timeout int, runasuser bool, envVars []string) (stdout, stderr string, exitcode int, e error) {
content := []byte(code) content := []byte(code)
@ -158,6 +161,11 @@ func (a *Agent) RunScript(code string, shell string, args []string, timeout int,
cmd.Stdout = &outb cmd.Stdout = &outb
cmd.Stderr = &errb cmd.Stderr = &errb
if len(envVars) > 0 {
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, envVars...)
}
if cmdErr := cmd.Start(); cmdErr != nil { if cmdErr := cmd.Start(); cmdErr != nil {
a.Logger.Debugln(cmdErr) a.Logger.Debugln(cmdErr)
return "", cmdErr.Error(), 65, cmdErr return "", cmdErr.Error(), 65, cmdErr
@ -855,6 +863,43 @@ func (a *Agent) InstallService() error {
return service.Control(s, "install") return service.Control(s, "install")
} }
func (a *Agent) GetAgentCheckInConfig(ret AgentCheckInConfig) AgentCheckInConfig {
// if local config present, overwrite
k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\TacticalRMM`, registry.ALL_ACCESS)
if err == nil {
if checkInHello, _, err := k.GetStringValue("CheckInHello"); err == nil {
ret.Hello = regRangeToInt(checkInHello)
}
if checkInAgentInfo, _, err := k.GetStringValue("CheckInAgentInfo"); err == nil {
ret.AgentInfo = regRangeToInt(checkInAgentInfo)
}
if checkInWinSvc, _, err := k.GetStringValue("CheckInWinSvc"); err == nil {
ret.WinSvc = regRangeToInt(checkInWinSvc)
}
if checkInPubIP, _, err := k.GetStringValue("CheckInPubIP"); err == nil {
ret.PubIP = regRangeToInt(checkInPubIP)
}
if checkInDisks, _, err := k.GetStringValue("CheckInDisks"); err == nil {
ret.Disks = regRangeToInt(checkInDisks)
}
if checkInSW, _, err := k.GetStringValue("CheckInSW"); err == nil {
ret.SW = regRangeToInt(checkInSW)
}
if checkInWMI, _, err := k.GetStringValue("CheckInWMI"); err == nil {
ret.WMI = regRangeToInt(checkInWMI)
}
if checkInSyncMesh, _, err := k.GetStringValue("CheckInSyncMesh"); err == nil {
ret.SyncMesh = regRangeToInt(checkInSyncMesh)
}
if checkInLimitData, _, err := k.GetStringValue("CheckInLimitData"); err == nil {
if checkInLimitData == "true" {
ret.LimitData = true
}
}
}
return ret
}
// TODO add to stub // TODO add to stub
func (a *Agent) NixMeshNodeID() string { func (a *Agent) NixMeshNodeID() string {
return "not implemented" return "not implemented"

View File

@ -169,7 +169,7 @@ type ScriptCheckResult struct {
// ScriptCheck runs either bat, powershell or python script // ScriptCheck runs either bat, powershell or python script
func (a *Agent) ScriptCheck(data rmm.Check, r *resty.Client) { func (a *Agent) ScriptCheck(data rmm.Check, r *resty.Client) {
start := time.Now() start := time.Now()
stdout, stderr, retcode, _ := a.RunScript(data.Script.Code, data.Script.Shell, data.ScriptArgs, data.Timeout, data.Script.RunAsUser) stdout, stderr, retcode, _ := a.RunScript(data.Script.Code, data.Script.Shell, data.ScriptArgs, data.Timeout, data.Script.RunAsUser, data.EnvVars)
payload := ScriptCheckResult{ payload := ScriptCheckResult{
ID: data.CheckPK, ID: data.CheckPK,

View File

@ -42,7 +42,7 @@ func (a *Agent) InstallChoco() {
return return
} }
_, _, exitcode, err := a.RunScript(string(r.Body()), "powershell", []string{}, 900, false) _, _, exitcode, err := a.RunScript(string(r.Body()), "powershell", []string{}, 900, false, []string{})
if err != nil { if err != nil {
a.Logger.Debugln(err) a.Logger.Debugln(err)
a.rClient.R().SetBody(result).Post(url) a.rClient.R().SetBody(result).Post(url)

View File

@ -41,6 +41,7 @@ type NatsMsg struct {
ID int `json:"id"` ID int `json:"id"`
Code string `json:"code"` Code string `json:"code"`
RunAsUser bool `json:"run_as_user"` RunAsUser bool `json:"run_as_user"`
EnvVars []string `json:"env_vars"`
} }
var ( var (
@ -51,15 +52,20 @@ var (
func (a *Agent) RunRPC() { func (a *Agent) RunRPC() {
a.Logger.Infoln("Agent service started") a.Logger.Infoln("Agent service started")
go a.RunAsService()
var wg sync.WaitGroup
wg.Add(1)
opts := a.setupNatsOptions() opts := a.setupNatsOptions()
nc, err := nats.Connect(a.NatsServer, opts...) nc, err := nats.Connect(a.NatsServer, opts...)
a.Logger.Debugf("%+v\n", nc)
a.Logger.Debugf("%+v\n", nc.Opts)
if err != nil { if err != nil {
a.Logger.Fatalln("RunRPC() nats.Connect()", err) a.Logger.Fatalln("RunRPC() nats.Connect()", err)
} }
go a.RunAsService(nc)
var wg sync.WaitGroup
wg.Add(1)
nc.Subscribe(a.AgentID, func(msg *nats.Msg) { nc.Subscribe(a.AgentID, func(msg *nats.Msg) {
var payload *NatsMsg var payload *NatsMsg
var mh codec.MsgpackHandle var mh codec.MsgpackHandle
@ -258,7 +264,7 @@ func (a *Agent) RunRPC() {
var resultData rmm.RunScriptResp var resultData rmm.RunScriptResp
ret := codec.NewEncoderBytes(&resp, new(codec.MsgpackHandle)) ret := codec.NewEncoderBytes(&resp, new(codec.MsgpackHandle))
start := time.Now() start := time.Now()
stdout, stderr, retcode, err := a.RunScript(p.Data["code"], p.Data["shell"], p.ScriptArgs, p.Timeout, p.RunAsUser) stdout, stderr, retcode, err := a.RunScript(p.Data["code"], p.Data["shell"], p.ScriptArgs, p.Timeout, p.RunAsUser, p.EnvVars)
resultData.ExecTime = time.Since(start).Seconds() resultData.ExecTime = time.Since(start).Seconds()
resultData.ID = p.ID resultData.ID = p.ID
@ -288,7 +294,7 @@ func (a *Agent) RunRPC() {
var retData rmm.RunScriptResp var retData rmm.RunScriptResp
ret := codec.NewEncoderBytes(&resp, new(codec.MsgpackHandle)) ret := codec.NewEncoderBytes(&resp, new(codec.MsgpackHandle))
start := time.Now() start := time.Now()
stdout, stderr, retcode, err := a.RunScript(p.Data["code"], p.Data["shell"], p.ScriptArgs, p.Timeout, p.RunAsUser) stdout, stderr, retcode, err := a.RunScript(p.Data["code"], p.Data["shell"], p.ScriptArgs, p.Timeout, p.RunAsUser, p.EnvVars)
retData.ExecTime = time.Since(start).Seconds() retData.ExecTime = time.Since(start).Seconds()
if err != nil { if err != nil {

View File

@ -12,6 +12,7 @@ https://license.tacticalrmm.com
package agent package agent
import ( import (
"fmt"
"runtime" "runtime"
"sync" "sync"
"time" "time"
@ -19,15 +20,27 @@ import (
nats "github.com/nats-io/nats.go" nats "github.com/nats-io/nats.go"
) )
func (a *Agent) RunAsService() { func (a *Agent) RunAsService(nc *nats.Conn) {
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(1) wg.Add(1)
go a.AgentSvc() go a.AgentSvc(nc)
go a.CheckRunner() go a.CheckRunner()
wg.Wait() wg.Wait()
} }
func (a *Agent) AgentSvc() { type AgentCheckInConfig struct {
Hello int `json:"checkin_hello"`
AgentInfo int `json:"checkin_agentinfo"`
WinSvc int `json:"checkin_winsvc"`
PubIP int `json:"checkin_pubip"`
Disks int `json:"checkin_disks"`
SW int `json:"checkin_sw"`
WMI int `json:"checkin_wmi"`
SyncMesh int `json:"checkin_syncmesh"`
LimitData bool `json:"limit_data"`
}
func (a *Agent) AgentSvc(nc *nats.Conn) {
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
go a.GetPython(false) go a.GetPython(false)
@ -38,37 +51,37 @@ func (a *Agent) AgentSvc() {
} }
a.RunMigrations() a.RunMigrations()
sleepDelay := randRange(14, 22) sleepDelay := randRange(7, 25)
a.Logger.Debugf("AgentSvc() sleeping for %v seconds", sleepDelay) a.Logger.Debugf("AgentSvc() sleeping for %v seconds", sleepDelay)
time.Sleep(time.Duration(sleepDelay) * time.Second) time.Sleep(time.Duration(sleepDelay) * time.Second)
opts := a.setupNatsOptions() conf := a.GetAgentCheckInConfig(a.GetCheckInConfFromAPI())
nc, err := nats.Connect(a.NatsServer, opts...) a.Logger.Debugf("+%v\n", conf)
if err != nil {
a.Logger.Fatalln("AgentSvc() nats.Connect()", err)
}
for _, s := range natsCheckin { for _, s := range natsCheckin {
a.NatsMessage(nc, s) if conf.LimitData && stringInSlice(s, limitNatsData) {
time.Sleep(time.Duration(randRange(100, 400)) * time.Millisecond) continue
} else {
a.NatsMessage(nc, s)
time.Sleep(time.Duration(randRange(100, 400)) * time.Millisecond)
}
} }
go a.SyncMeshNodeID() go a.SyncMeshNodeID()
time.Sleep(time.Duration(randRange(1, 3)) * time.Second) time.Sleep(time.Duration(randRange(1, 3)) * time.Second)
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" && !conf.LimitData {
a.AgentStartup() a.AgentStartup()
a.SendSoftware() a.SendSoftware()
} }
checkInHelloTicker := time.NewTicker(time.Duration(randRange(30, 60)) * time.Second) checkInHelloTicker := time.NewTicker(time.Duration(conf.Hello) * time.Second)
checkInAgentInfoTicker := time.NewTicker(time.Duration(randRange(200, 400)) * time.Second) checkInAgentInfoTicker := time.NewTicker(time.Duration(conf.AgentInfo) * time.Second)
checkInWinSvcTicker := time.NewTicker(time.Duration(randRange(2400, 3000)) * time.Second) checkInWinSvcTicker := time.NewTicker(time.Duration(conf.WinSvc) * time.Second)
checkInPubIPTicker := time.NewTicker(time.Duration(randRange(300, 500)) * time.Second) checkInPubIPTicker := time.NewTicker(time.Duration(conf.PubIP) * time.Second)
checkInDisksTicker := time.NewTicker(time.Duration(randRange(1000, 2000)) * time.Second) checkInDisksTicker := time.NewTicker(time.Duration(conf.Disks) * time.Second)
checkInSWTicker := time.NewTicker(time.Duration(randRange(2800, 3500)) * time.Second) checkInSWTicker := time.NewTicker(time.Duration(conf.SW) * time.Second)
checkInWMITicker := time.NewTicker(time.Duration(randRange(3000, 4000)) * time.Second) checkInWMITicker := time.NewTicker(time.Duration(conf.WMI) * time.Second)
syncMeshTicker := time.NewTicker(time.Duration(randRange(800, 1200)) * time.Second) syncMeshTicker := time.NewTicker(time.Duration(conf.SyncMesh) * time.Second)
for { for {
select { select {
@ -100,3 +113,32 @@ func (a *Agent) AgentStartup() {
a.Logger.Debugln("AgentStartup()", err) a.Logger.Debugln("AgentStartup()", err)
} }
} }
func (a *Agent) GetCheckInConfFromAPI() AgentCheckInConfig {
ret := AgentCheckInConfig{}
url := fmt.Sprintf("/api/v3/%s/config/", a.AgentID)
r, err := a.rClient.R().SetResult(&AgentCheckInConfig{}).Get(url)
if err != nil {
a.Logger.Debugln("GetAgentCheckInConfig()", err)
ret.Hello = randRange(30, 60)
ret.AgentInfo = randRange(200, 400)
ret.WinSvc = randRange(2400, 3000)
ret.PubIP = randRange(300, 500)
ret.Disks = randRange(1000, 2000)
ret.SW = randRange(2800, 3500)
ret.WMI = randRange(3000, 4000)
ret.SyncMesh = randRange(800, 1200)
ret.LimitData = false
} else {
ret.Hello = r.Result().(*AgentCheckInConfig).Hello
ret.AgentInfo = r.Result().(*AgentCheckInConfig).AgentInfo
ret.WinSvc = r.Result().(*AgentCheckInConfig).WinSvc
ret.PubIP = r.Result().(*AgentCheckInConfig).PubIP
ret.Disks = r.Result().(*AgentCheckInConfig).Disks
ret.SW = r.Result().(*AgentCheckInConfig).SW
ret.WMI = r.Result().(*AgentCheckInConfig).WMI
ret.SyncMesh = r.Result().(*AgentCheckInConfig).SyncMesh
ret.LimitData = r.Result().(*AgentCheckInConfig).LimitData
}
return ret
}

View File

@ -59,7 +59,7 @@ func (a *Agent) RunTask(id int) error {
action_start := time.Now() action_start := time.Now()
if action.ActionType == "script" { if action.ActionType == "script" {
stdout, stderr, retcode, err := a.RunScript(action.Code, action.Shell, action.Args, action.Timeout, action.RunAsUser) stdout, stderr, retcode, err := a.RunScript(action.Code, action.Shell, action.Args, action.Timeout, action.RunAsUser, action.EnvVars)
if err != nil { if err != nil {
a.Logger.Debugln(err) a.Logger.Debugln(err)

View File

@ -23,6 +23,7 @@ import (
"path/filepath" "path/filepath"
"runtime" "runtime"
goDebug "runtime/debug" goDebug "runtime/debug"
"strconv"
"strings" "strings"
"time" "time"
@ -322,3 +323,19 @@ func createTmpFile() (*os.File, error) {
} }
return f, nil return f, nil
} }
func stringInSlice(a string, list []string) bool {
for _, b := range list {
if b == a {
return true
}
}
return false
}
func regRangeToInt(s string) int {
split := strings.Split(s, ",")
min, _ := strconv.Atoi(split[0])
max, _ := strconv.Atoi(split[1])
return randRange(min, max)
}

View File

@ -3,7 +3,7 @@
<assemblyIdentity <assemblyIdentity
type="win32" type="win32"
name="TacticalRMM" name="TacticalRMM"
version="2.4.2.0" version="2.4.3.0"
processorArchitecture="*"/> processorArchitecture="*"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security> <security>

View File

@ -1,5 +1,5 @@
#define MyAppName "Tactical RMM Agent" #define MyAppName "Tactical RMM Agent"
#define MyAppVersion "2.4.2" #define MyAppVersion "2.4.3"
#define MyAppPublisher "AmidaWare LLC" #define MyAppPublisher "AmidaWare LLC"
#define MyAppURL "https://github.com/amidaware" #define MyAppURL "https://github.com/amidaware"
#define MyAppExeName "tacticalrmm.exe" #define MyAppExeName "tacticalrmm.exe"

6
go.mod
View File

@ -4,13 +4,13 @@ go 1.19
require ( require (
github.com/StackExchange/wmi v1.2.1 github.com/StackExchange/wmi v1.2.1
github.com/elastic/go-sysinfo v1.8.1 github.com/elastic/go-sysinfo v1.9.0
github.com/go-ole/go-ole v1.2.6 github.com/go-ole/go-ole v1.2.6
github.com/go-ping/ping v1.1.0 github.com/go-ping/ping v1.1.0
github.com/go-resty/resty/v2 v2.7.0 github.com/go-resty/resty/v2 v2.7.0
github.com/gonutz/w32/v2 v2.4.0 github.com/gonutz/w32/v2 v2.4.0
github.com/iamacarpet/go-win64api v0.0.0-20220531131246-e84054eb584d github.com/iamacarpet/go-win64api v0.0.0-20220531131246-e84054eb584d
github.com/nats-io/nats-server/v2 v2.9.6 // indirect github.com/nats-io/nats-server/v2 v2.9.8 // indirect
github.com/nats-io/nats.go v1.20.0 github.com/nats-io/nats.go v1.20.0
github.com/rickb777/date v1.19.1 github.com/rickb777/date v1.19.1
github.com/shirou/gopsutil/v3 v3.22.10 github.com/shirou/gopsutil/v3 v3.22.10
@ -55,7 +55,7 @@ require (
github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c // indirect github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c // indirect
github.com/prometheus/procfs v0.7.3 // indirect github.com/prometheus/procfs v0.8.0 // indirect
github.com/rickb777/plural v1.4.1 // indirect github.com/rickb777/plural v1.4.1 // indirect
github.com/rogpeppe/go-internal v1.8.1 // indirect github.com/rogpeppe/go-internal v1.8.1 // indirect
github.com/scjalliance/comshim v0.0.0-20190308082608-cf06d2532c4e // indirect github.com/scjalliance/comshim v0.0.0-20190308082608-cf06d2532c4e // indirect

13
go.sum
View File

@ -57,8 +57,8 @@ github.com/creachadair/staticfile v0.1.3/go.mod h1:a3qySzCIXEprDGxk6tSxSI+dBBdLz
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/elastic/go-sysinfo v1.8.1 h1:4Yhj+HdV6WjbCRgGdZpPJ8lZQlXZLKDAeIkmQ/VRvi4= github.com/elastic/go-sysinfo v1.9.0 h1:usICqY/Nw4Mpn9f4LdtpFrKxXroJDe81GaxxUlCckIo=
github.com/elastic/go-sysinfo v1.8.1/go.mod h1:JfllUnzoQV/JRYymbH3dO1yggI3mV2oTKSXsDHM+uIM= github.com/elastic/go-sysinfo v1.9.0/go.mod h1:eBD1wEGVaRnRLGecc9iG1z8eOv5HnEdz9+nWd8UAxcE=
github.com/elastic/go-windows v1.0.1 h1:AlYZOldA+UJ0/2nBuqWdo90GFCgG9xuyw9SYzGUtJm0= github.com/elastic/go-windows v1.0.1 h1:AlYZOldA+UJ0/2nBuqWdo90GFCgG9xuyw9SYzGUtJm0=
github.com/elastic/go-windows v1.0.1/go.mod h1:FoVvqWSun28vaDQPbj2Elfc0JahhPB7WQEGa3c814Ss= github.com/elastic/go-windows v1.0.1/go.mod h1:FoVvqWSun28vaDQPbj2Elfc0JahhPB7WQEGa3c814Ss=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@ -212,8 +212,8 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/nats-io/jwt/v2 v2.3.0 h1:z2mA1a7tIf5ShggOFlR1oBPgd6hGqcDYsISxZByUzdI= github.com/nats-io/jwt/v2 v2.3.0 h1:z2mA1a7tIf5ShggOFlR1oBPgd6hGqcDYsISxZByUzdI=
github.com/nats-io/nats-server/v2 v2.9.6 h1:RTtK+rv/4CcliOuqGsy58g7MuWkBaWmF5TUNwuUo9Uw= github.com/nats-io/nats-server/v2 v2.9.8 h1:jgxZsv+A3Reb3MgwxaINcNq/za8xZInKhDg9Q0cGN1o=
github.com/nats-io/nats-server/v2 v2.9.6/go.mod h1:AB6hAnGZDlYfqb7CTAm66ZKMZy9DpfierY1/PbpvI2g= github.com/nats-io/nats-server/v2 v2.9.8/go.mod h1:AB6hAnGZDlYfqb7CTAm66ZKMZy9DpfierY1/PbpvI2g=
github.com/nats-io/nats.go v1.20.0 h1:T8JJnQfVSdh1CzGiwAOv5hEobYCBho/0EupGznYw0oM= github.com/nats-io/nats.go v1.20.0 h1:T8JJnQfVSdh1CzGiwAOv5hEobYCBho/0EupGznYw0oM=
github.com/nats-io/nats.go v1.20.0/go.mod h1:tLqubohF7t4z3du1QDPYJIQQyhb4wl6DhjxEajSI7UA= github.com/nats-io/nats.go v1.20.0/go.mod h1:tLqubohF7t4z3du1QDPYJIQQyhb4wl6DhjxEajSI7UA=
github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8= github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=
@ -243,8 +243,8 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:Om
github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c h1:NRoLoZvkBTKvR5gQLgA3e0hqjkY9u1wm+iOL45VN/qI= github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c h1:NRoLoZvkBTKvR5gQLgA3e0hqjkY9u1wm+iOL45VN/qI=
github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/rickb777/date v1.14.2/go.mod h1:swmf05C+hN+m8/Xh7gEq3uB6QJDNc5pQBWojKdHetOs= github.com/rickb777/date v1.14.2/go.mod h1:swmf05C+hN+m8/Xh7gEq3uB6QJDNc5pQBWojKdHetOs=
github.com/rickb777/date v1.19.1 h1:IMcFlWY3PagAcc274tJAag84+dh4ihusPxhu4jaHMwY= github.com/rickb777/date v1.19.1 h1:IMcFlWY3PagAcc274tJAag84+dh4ihusPxhu4jaHMwY=
github.com/rickb777/date v1.19.1/go.mod h1:NxzFOW9ZWNeOWWE2kUXLDN59GSuGMsu3E4YVVk+GcVU= github.com/rickb777/date v1.19.1/go.mod h1:NxzFOW9ZWNeOWWE2kUXLDN59GSuGMsu3E4YVVk+GcVU=
@ -455,7 +455,6 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -25,7 +25,7 @@ import (
) )
var ( var (
version = "2.4.2" version = "2.4.3"
log = logrus.New() log = logrus.New()
logFile *os.File logFile *os.File
) )

View File

@ -45,6 +45,7 @@ type AgentConfig struct {
NatsProxyPath string NatsProxyPath string
NatsProxyPort string NatsProxyPort string
NatsStandardPort string NatsStandardPort string
NatsPingInterval int
} }
type RunScriptResp struct { type RunScriptResp struct {
@ -141,9 +142,10 @@ type AssignedTask struct {
} }
type Script struct { type Script struct {
Shell string `json:"shell"` Shell string `json:"shell"`
Code string `json:"code"` Code string `json:"code"`
RunAsUser bool `json:"run_as_user"` RunAsUser bool `json:"run_as_user"`
EnvVars []string `json:"env_vars"`
} }
type CheckInfo struct { type CheckInfo struct {
@ -161,6 +163,7 @@ type Check struct {
Disk string `json:"disk"` Disk string `json:"disk"`
IP string `json:"ip"` IP string `json:"ip"`
ScriptArgs []string `json:"script_args"` ScriptArgs []string `json:"script_args"`
EnvVars []string `json:"env_vars"`
Timeout int `json:"timeout"` Timeout int `json:"timeout"`
ServiceName string `json:"svc_name"` ServiceName string `json:"svc_name"`
PassStartPending bool `json:"pass_if_start_pending"` PassStartPending bool `json:"pass_if_start_pending"`
@ -190,6 +193,7 @@ type TaskAction struct {
Args []string `json:"script_args"` Args []string `json:"script_args"`
Timeout int `json:"timeout"` Timeout int `json:"timeout"`
RunAsUser bool `json:"run_as_user"` RunAsUser bool `json:"run_as_user"`
EnvVars []string `json:"env_vars"`
} }
type AutomatedTask struct { type AutomatedTask struct {

View File

@ -3,13 +3,13 @@
"FileVersion": { "FileVersion": {
"Major": 2, "Major": 2,
"Minor": 4, "Minor": 4,
"Patch": 2, "Patch": 3,
"Build": 0 "Build": 0
}, },
"ProductVersion": { "ProductVersion": {
"Major": 2, "Major": 2,
"Minor": 4, "Minor": 4,
"Patch": 2, "Patch": 3,
"Build": 0 "Build": 0
}, },
"FileFlagsMask": "3f", "FileFlagsMask": "3f",
@ -22,14 +22,14 @@
"Comments": "", "Comments": "",
"CompanyName": "AmidaWare LLC", "CompanyName": "AmidaWare LLC",
"FileDescription": "Tactical RMM Agent", "FileDescription": "Tactical RMM Agent",
"FileVersion": "v2.4.2.0", "FileVersion": "v2.4.3.0",
"InternalName": "tacticalrmm.exe", "InternalName": "tacticalrmm.exe",
"LegalCopyright": "Copyright (c) 2022 AmidaWare LLC", "LegalCopyright": "Copyright (c) 2022 AmidaWare LLC",
"LegalTrademarks": "", "LegalTrademarks": "",
"OriginalFilename": "tacticalrmm.exe", "OriginalFilename": "tacticalrmm.exe",
"PrivateBuild": "", "PrivateBuild": "",
"ProductName": "Tactical RMM Agent", "ProductName": "Tactical RMM Agent",
"ProductVersion": "v2.4.2.0", "ProductVersion": "v2.4.3.0",
"SpecialBuild": "" "SpecialBuild": ""
}, },
"VarFileInfo": { "VarFileInfo": {