Skip to content

Commit

Permalink
Release 2.4.3
Browse files Browse the repository at this point in the history
  • Loading branch information
wh1te909 committed Dec 4, 2022
2 parents b3e0c3e + 63fe3bc commit e9fd05b
Show file tree
Hide file tree
Showing 16 changed files with 259 additions and 111 deletions.
150 changes: 90 additions & 60 deletions agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,35 +40,37 @@ import (

// Agent struct
type Agent struct {
Hostname string
Arch string
AgentID string
BaseURL string
ApiURL string
Token string
AgentPK int
Cert string
ProgramDir string
EXE string
SystemDrive string
MeshInstaller string
MeshSystemEXE string
MeshSVC string
PyBin string
Headers map[string]string
Logger *logrus.Logger
Version string
Debug bool
rClient *resty.Client
Proxy string
LogTo string
LogFile *os.File
Platform string
GoArch string
ServiceConfig *service.Config
NatsServer string
NatsProxyPath string
NatsProxyPort string
Hostname string
Arch string
AgentID string
BaseURL string
ApiURL string
Token string
AgentPK int
Cert string
ProgramDir string
EXE string
SystemDrive string
MeshInstaller string
MeshSystemEXE string
MeshSVC string
PyBin string
Headers map[string]string
Logger *logrus.Logger
Version string
Debug bool
rClient *resty.Client
Proxy string
LogTo string
LogFile *os.File
Platform string
GoArch string
ServiceConfig *service.Config
NatsServer string
NatsProxyPath string
NatsProxyPort string
NatsPingInterval int
NatsWSCompression bool
}

const (
Expand All @@ -89,6 +91,7 @@ const (
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"}
var limitNatsData = []string{"agent-winsvc", "agent-wmi"}

func New(logger *logrus.Logger, version string) *Agent {
host, _ := ps.Host()
Expand Down Expand Up @@ -170,39 +173,50 @@ func New(logger *logrus.Logger, version string) *Agent {

// check if using nats standard tcp, otherwise use nats websockets by default
var natsServer string
var natsWsCompression bool
if ac.NatsStandardPort != "" {
natsServer = fmt.Sprintf("tls://%s:%s", ac.APIURL, ac.NatsStandardPort)
} else {
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{
Hostname: info.Hostname,
BaseURL: ac.BaseURL,
AgentID: ac.AgentID,
ApiURL: ac.APIURL,
Token: ac.Token,
AgentPK: ac.PK,
Cert: ac.Cert,
ProgramDir: pd,
EXE: exe,
SystemDrive: sd,
MeshInstaller: "meshagent.exe",
MeshSystemEXE: MeshSysExe,
MeshSVC: meshSvcName,
PyBin: pybin,
Headers: headers,
Logger: logger,
Version: version,
Debug: logger.IsLevelEnabled(logrus.DebugLevel),
rClient: restyC,
Proxy: ac.Proxy,
Platform: runtime.GOOS,
GoArch: runtime.GOARCH,
ServiceConfig: svcConf,
NatsServer: natsServer,
NatsProxyPath: natsProxyPath,
NatsProxyPort: natsProxyPort,
Hostname: info.Hostname,
BaseURL: ac.BaseURL,
AgentID: ac.AgentID,
ApiURL: ac.APIURL,
Token: ac.Token,
AgentPK: ac.PK,
Cert: ac.Cert,
ProgramDir: pd,
EXE: exe,
SystemDrive: sd,
MeshInstaller: "meshagent.exe",
MeshSystemEXE: MeshSysExe,
MeshSVC: meshSvcName,
PyBin: pybin,
Headers: headers,
Logger: logger,
Version: version,
Debug: logger.IsLevelEnabled(logrus.DebugLevel),
rClient: restyC,
Proxy: ac.Proxy,
Platform: runtime.GOOS,
GoArch: runtime.GOARCH,
ServiceConfig: svcConf,
NatsServer: natsServer,
NatsProxyPath: natsProxyPath,
NatsProxyPort: natsProxyPort,
NatsPingInterval: natsPingInterval,
NatsWSCompression: natsWsCompression,
}
}

Expand All @@ -220,7 +234,7 @@ type CmdOptions struct {
IsScript bool
IsExecutable bool
Detached bool
Env []string
EnvVars []string
}

func (a *Agent) NewCMDOpts() *CmdOptions {
Expand Down Expand Up @@ -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) {
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, c.Env...)
cmd.Env = append(cmd.Env, c.EnvVars...)
})
}

Expand Down Expand Up @@ -398,14 +412,30 @@ func (a *Agent) SyncMeshNodeID() {
}

func (a *Agent) setupNatsOptions() []nats.Option {
reconnectWait := randRange(2, 8)
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.ReconnectWait(time.Second*5))
opts = append(opts, nats.ReconnectWait(time.Duration(reconnectWait)*time.Second))
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.ReconnectBufSize(-1))
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
}

Expand Down
7 changes: 6 additions & 1 deletion agent/agent_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,12 @@ func NewAgentConfig() *rmm.AgentConfig {
NatsProxyPath: viper.GetString("natsproxypath"),
NatsProxyPort: viper.GetString("natsproxyport"),
NatsStandardPort: viper.GetString("natsstandardport"),
NatsPingInterval: viper.GetInt("natspinginterval"),
}
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)
content := []byte(code)

Expand Down Expand Up @@ -192,6 +193,7 @@ func (a *Agent) RunScript(code string, shell string, args []string, timeout int,
opts.IsScript = true
opts.Shell = f.Name()
opts.Args = args
opts.EnvVars = envVars
opts.Timeout = time.Duration(timeout)
out := a.CmdV2(opts)
retError := ""
Expand Down Expand Up @@ -491,6 +493,9 @@ func (a *Agent) GetWMIInfo() map[string]interface{} {
}

// 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 }

Expand Down
47 changes: 46 additions & 1 deletion agent/agent_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ func NewAgentConfig() *rmm.AgentConfig {
natsProxyPath, _, _ := k.GetStringValue("NatsProxyPath")
natsProxyPort, _, _ := k.GetStringValue("NatsProxyPort")
natsStandardPort, _, _ := k.GetStringValue("NatsStandardPort")
natsPingInterval, _, _ := k.GetStringValue("NatsPingInterval")
npi, _ := strconv.Atoi(natsPingInterval)

return &rmm.AgentConfig{
BaseURL: baseurl,
Expand All @@ -79,10 +81,11 @@ func NewAgentConfig() *rmm.AgentConfig {
NatsProxyPath: natsProxyPath,
NatsProxyPort: natsProxyPort,
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)

Expand Down Expand Up @@ -158,6 +161,11 @@ func (a *Agent) RunScript(code string, shell string, args []string, timeout int,
cmd.Stdout = &outb
cmd.Stderr = &errb

if len(envVars) > 0 {
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, envVars...)
}

if cmdErr := cmd.Start(); cmdErr != nil {
a.Logger.Debugln(cmdErr)
return "", cmdErr.Error(), 65, cmdErr
Expand Down Expand Up @@ -855,6 +863,43 @@ func (a *Agent) InstallService() error {
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
func (a *Agent) NixMeshNodeID() string {
return "not implemented"
Expand Down
2 changes: 1 addition & 1 deletion agent/checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -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, 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{
ID: data.CheckPK,
Expand Down
2 changes: 1 addition & 1 deletion agent/choco_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (a *Agent) InstallChoco() {
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 {
a.Logger.Debugln(err)
a.rClient.R().SetBody(result).Post(url)
Expand Down
16 changes: 11 additions & 5 deletions agent/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type NatsMsg struct {
ID int `json:"id"`
Code string `json:"code"`
RunAsUser bool `json:"run_as_user"`
EnvVars []string `json:"env_vars"`
}

var (
Expand All @@ -51,15 +52,20 @@ var (

func (a *Agent) RunRPC() {
a.Logger.Infoln("Agent service started")
go a.RunAsService()
var wg sync.WaitGroup
wg.Add(1)

opts := a.setupNatsOptions()
nc, err := nats.Connect(a.NatsServer, opts...)
a.Logger.Debugf("%+v\n", nc)
a.Logger.Debugf("%+v\n", nc.Opts)
if err != nil {
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) {
var payload *NatsMsg
var mh codec.MsgpackHandle
Expand Down Expand Up @@ -258,7 +264,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, 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.ID = p.ID

Expand Down Expand Up @@ -288,7 +294,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, 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()
if err != nil {
Expand Down
Loading

0 comments on commit e9fd05b

Please sign in to comment.