diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c4f05a..8ad7e95 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,9 +16,9 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: - go-version: '1.18.3' + go-version: '1.20.11' - name: Ensure linux agent compiles run: | @@ -40,10 +40,3 @@ jobs: for i in ${ARCHS}; do env CGO_ENABLED=0 GOOS=darwin GOARCH=${i} go build -ldflags "-s -w" done - - - name: Ensure freebsd agent compiles - run: | - ARCHS='amd64 386 arm64 arm' - for i in ${ARCHS}; do - env CGO_ENABLED=0 GOOS=freebsd GOARCH=${i} go build -ldflags "-s -w" - done diff --git a/LICENSE.md b/LICENSE.md index 530804b..8783c2a 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,11 +1,11 @@ ### Tactical RMM License Version 1.0 -Text of license:   Copyright © 2022 AmidaWare LLC. All rights reserved.
+Text of license:   Copyright © 2023 AmidaWare Inc. All rights reserved.
          Amending the text of this license is not permitted. -Trade Mark:    "Tactical RMM" is a trade mark of AmidaWare LLC. +Trade Mark:    "Tactical RMM" is a trade mark of AmidaWare Inc. -Licensor:       AmidaWare LLC of 1968 S Coast Hwy PMB 3847 Laguna Beach, CA, USA. +Licensor:       AmidaWare Inc. of 1968 S Coast Hwy PMB 3847 Laguna Beach, CA, USA. Licensed Software:  The software known as Tactical RMM Version v0.12.0 (and all subsequent releases and versions) and the Tactical RMM Agent v2.0.0 (and all subsequent releases and versions). @@ -26,7 +26,7 @@ This license does not allow the functionality of the Licensed Software (whether * the offering of installation and/or configuration services; * the offer for sale, distribution or sale of any service or product (whether or not branded as Tactical RMM). -The prior written approval of AmidaWare LLC must be obtained for all commercial use and/or for-profit service use of the (i) Licensed Software (whether in whole or in part), (ii) a modified version of the Licensed Software and/or (iii) a derivative work. +The prior written approval of AmidaWare Inc. must be obtained for all commercial use and/or for-profit service use of the (i) Licensed Software (whether in whole or in part), (ii) a modified version of the Licensed Software and/or (iii) a derivative work. The terms of this license apply to all copies of the Licensed Software (including modified versions) and derivative works. @@ -38,7 +38,7 @@ If a derivative work is created which is based on or otherwise incorporates all ### 4. Copyright Notice The following copyright notice shall be included in all copies of the Licensed Software: -   Copyright © 2022 AmidaWare LLC. +   Copyright © 2023 AmidaWare Inc.    Licensed under the Tactical RMM License Version 1.0 (the “License”).
   You may only use the Licensed Software in accordance with the License.
@@ -54,13 +54,13 @@ THE FOLLOWING EXCLUSIONS SHALL APPLY TO THE FULLEST EXTENT PERMISSIBLE AT LAW. This license shall terminate with immediate effect if there is a material breach of any of its terms. ### 8. No partnership, agency or joint venture -Nothing in this license agreement is intended to, or shall be deemed to, establish any partnership or joint venture or any relationship of agency between AmidaWare LLC and any other person. +Nothing in this license agreement is intended to, or shall be deemed to, establish any partnership or joint venture or any relationship of agency between AmidaWare Inc. and any other person. ### 9. No endorsement The names of the authors and/or the copyright holders must not be used to promote or endorse any products or services which are in any way derived from the Licensed Software without prior written consent. ### 10. Trademarks -No permission is granted to use the trademark “Tactical RMM” or any other trade name, trademark, service mark or product name of AmidaWare LLC except to the extent necessary to comply with the notice requirements in Section 4 (Copyright Notice). +No permission is granted to use the trademark “Tactical RMM” or any other trade name, trademark, service mark or product name of AmidaWare Inc. except to the extent necessary to comply with the notice requirements in Section 4 (Copyright Notice). ### 11. Entire agreement This license contains the whole agreement relating to its subject matter. diff --git a/agent/agent.go b/agent/agent.go index 84f1889..67afef2 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. @@ -14,9 +14,9 @@ package agent import ( "bytes" "context" + "crypto/tls" "errors" "fmt" - "io/ioutil" "math" "os" "os/exec" @@ -24,6 +24,7 @@ import ( "runtime" "strconv" "strings" + "syscall" "time" @@ -40,47 +41,61 @@ 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 + WinTmpDir string + WinRunAsUserTmpDir 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 + Insecure bool } const ( - progFilesName = "TacticalAgent" - winExeName = "tacticalrmm.exe" - winSvcName = "tacticalrmm" - meshSvcName = "mesh agent" + progFilesName = "TacticalAgent" + winExeName = "tacticalrmm.exe" + winSvcName = "tacticalrmm" + meshSvcName = "mesh agent" + etcConfig = "/etc/tacticalagent" + nixAgentDir = "/opt/tacticalagent" + nixMeshDir = "/opt/tacticalmesh" + nixAgentBin = nixAgentDir + "/tacticalagent" + nixMeshAgentBin = nixMeshDir + "/meshagent" + macPlistPath = "/Library/LaunchDaemons/tacticalagent.plist" + macPlistName = "tacticalagent" + defaultMacMeshSvcDir = "/usr/local/mesh_services" ) -var winTempDir = filepath.Join(os.Getenv("PROGRAMDATA"), "TacticalRMM") +var defaultWinTmpDir = 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() @@ -88,6 +103,13 @@ func New(logger *logrus.Logger, version string) *Agent { pd := filepath.Join(os.Getenv("ProgramFiles"), progFilesName) exe := filepath.Join(pd, winExeName) sd := os.Getenv("SystemDrive") + winTempDir := defaultWinTmpDir + winRunAsUserTmpDir := defaultWinTmpDir + + hostname, err := os.Hostname() + if err != nil { + hostname = info.Hostname + } var pybin string switch runtime.GOARCH { @@ -105,12 +127,20 @@ func New(logger *logrus.Logger, version string) *Agent { headers["Authorization"] = fmt.Sprintf("Token %s", ac.Token) } + insecure := ac.Insecure == "true" + restyC := resty.New() restyC.SetBaseURL(ac.BaseURL) restyC.SetCloseConnection(true) restyC.SetHeaders(headers) restyC.SetTimeout(15 * time.Second) restyC.SetDebug(logger.IsLevelEnabled(logrus.DebugLevel)) + if insecure { + insecureConf := &tls.Config{ + InsecureSkipVerify: true, + } + restyC.SetTLSClientConfig(insecureConf) + } if len(ac.Proxy) > 0 { restyC.SetProxy(ac.Proxy) @@ -119,15 +149,30 @@ func New(logger *logrus.Logger, version string) *Agent { restyC.SetRootCertificate(ac.Cert) } - var MeshSysExe string - if len(ac.CustomMeshDir) > 0 { - MeshSysExe = filepath.Join(ac.CustomMeshDir, "MeshAgent.exe") - } else { - MeshSysExe = filepath.Join(os.Getenv("ProgramFiles"), "Mesh Agent", "MeshAgent.exe") + if len(ac.WinTmpDir) > 0 { + winTempDir = ac.WinTmpDir } - if runtime.GOOS == "linux" { - MeshSysExe = "/opt/tacticalmesh/meshagent" + if len(ac.WinRunAsUserTmpDir) > 0 { + winRunAsUserTmpDir = ac.WinRunAsUserTmpDir + } + + var MeshSysExe string + switch runtime.GOOS { + case "windows": + if len(ac.CustomMeshDir) > 0 { + MeshSysExe = filepath.Join(ac.CustomMeshDir, "MeshAgent.exe") + } else { + MeshSysExe = filepath.Join(os.Getenv("ProgramFiles"), "Mesh Agent", "MeshAgent.exe") + } + case "darwin": + if trmm.FileExists(nixMeshAgentBin) { + MeshSysExe = nixMeshAgentBin + } else { + MeshSysExe = "/usr/local/mesh_services/meshagent/meshagent" + } + default: + MeshSysExe = nixMeshAgentBin } svcConf := &service.Config{ @@ -139,7 +184,7 @@ func New(logger *logrus.Logger, version string) *Agent { Option: service.KeyValue{ "StartType": "automatic", "OnFailure": "restart", - "OnFailureDelayDuration": "5s", + "OnFailureDelayDuration": "12s", "OnFailureResetPeriod": 10, }, } @@ -155,39 +200,53 @@ 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: 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, + WinTmpDir: winTempDir, + WinRunAsUserTmpDir: winRunAsUserTmpDir, + 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, + Insecure: insecure, } } @@ -205,12 +264,13 @@ type CmdOptions struct { IsScript bool IsExecutable bool Detached bool + EnvVars []string } func (a *Agent) NewCMDOpts() *CmdOptions { return &CmdOptions{ Shell: "/bin/bash", - Timeout: 30, + Timeout: 60, } } @@ -228,11 +288,16 @@ func (a *Agent) CmdV2(c *CmdOptions) CmdStatus { // have a child process that is in a different process group so that // parent terminating doesn't kill child if c.Detached { - cmdOptions.BeforeExec = []func(cmd *exec.Cmd){ - func(cmd *exec.Cmd) { - cmd.SysProcAttr = SetDetached() - }, - } + cmdOptions.BeforeExec = append(cmdOptions.BeforeExec, func(cmd *exec.Cmd) { + cmd.SysProcAttr = SetDetached() + }) + } + + if len(c.EnvVars) > 0 { + cmdOptions.BeforeExec = append(cmdOptions.BeforeExec, func(cmd *exec.Cmd) { + cmd.Env = os.Environ() + cmd.Env = append(cmd.Env, c.EnvVars...) + }) } var envCmd *gocmd.Cmd @@ -241,7 +306,8 @@ func (a *Agent) CmdV2(c *CmdOptions) CmdStatus { } else if c.IsExecutable { envCmd = gocmd.NewCmdOptions(cmdOptions, c.Shell, c.Command) // c.Shell: bin + c.Command: args as one string } else { - envCmd = gocmd.NewCmdOptions(cmdOptions, c.Shell, "-c", c.Command) // /bin/bash -c 'ls -l /var/log/...' + commandArray := append(strings.Fields(c.Shell), "-c", c.Command) + envCmd = gocmd.NewCmdOptions(cmdOptions, commandArray[0], commandArray[1:]...) // /bin/bash -c 'ls -l /var/log/...' } var stdoutBuf bytes.Buffer @@ -273,25 +339,46 @@ func (a *Agent) CmdV2(c *CmdOptions) CmdStatus { } }() - // Run and wait for Cmd to return, discard Status - envCmd.Start() - + statusChan := make(chan gocmd.Status, 1) + // workaround for https://github.com/golang/go/issues/22315 go func() { - select { - case <-doneChan: + for i := 0; i < 5; i++ { + finalStatus := <-envCmd.Start() + if errors.Is(finalStatus.Error, syscall.ETXTBSY) { + a.Logger.Errorln("CmdV2 syscall.ETXTBSY, retrying...") + time.Sleep(500 * time.Millisecond) + continue + } + statusChan <- finalStatus return - case <-ctx.Done(): - a.Logger.Debugf("Command timed out after %d seconds\n", c.Timeout) - pid := envCmd.Status().PID - a.Logger.Debugln("Killing process with PID", pid) - KillProc(int32(pid)) } }() + var finalStatus gocmd.Status + + select { + case <-ctx.Done(): + a.Logger.Debugf("Command timed out after %d seconds\n", c.Timeout) + pid := envCmd.Status().PID + a.Logger.Debugln("Killing process with PID", pid) + KillProc(int32(pid)) + finalStatus.Exit = 98 + ret := CmdStatus{ + Status: finalStatus, + Stdout: CleanString(stdoutBuf.String()), + Stderr: fmt.Sprintf("%s\nTimed out after %d seconds", CleanString(stderrBuf.String()), c.Timeout), + } + a.Logger.Debugf("%+v\n", ret) + return ret + case finalStatus = <-statusChan: + // done + } + // Wait for goroutine to print everything <-doneChan + ret := CmdStatus{ - Status: envCmd.Status(), + Status: finalStatus, Stdout: CleanString(stdoutBuf.String()), Stderr: CleanString(stderrBuf.String()), } @@ -377,14 +464,37 @@ 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.IgnoreAuthErrorAbort()) + 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) + })) + if a.Insecure { + insecureConf := &tls.Config{ + InsecureSkipVerify: true, + } + opts = append(opts, nats.Secure(insecureConf)) + } return opts } @@ -405,7 +515,7 @@ func (a *Agent) GetUninstallExe() string { func (a *Agent) CleanupAgentUpdates() { // TODO remove a.ProgramDir, updates are now in winTempDir - dirs := [2]string{winTempDir, a.ProgramDir} + dirs := [3]string{a.WinTmpDir, os.Getenv("TMP"), a.ProgramDir} for _, dir := range dirs { err := os.Chdir(dir) if err != nil { @@ -414,7 +524,7 @@ func (a *Agent) CleanupAgentUpdates() { } // TODO winagent-v* is deprecated - globs := [2]string{"tacticalagent-v*", "winagent-v*"} + globs := [3]string{"tacticalagent-v*", "is-*.tmp", "winagent-v*"} for _, glob := range globs { files, err := filepath.Glob(glob) if err == nil { @@ -439,7 +549,7 @@ func (a *Agent) CleanupAgentUpdates() { func (a *Agent) RunPythonCode(code string, timeout int, args []string) (string, error) { content := []byte(code) - tmpfn, _ := ioutil.TempFile(winTempDir, "*.py") + tmpfn, _ := os.CreateTemp(a.WinTmpDir, "*.py") if _, err := tmpfn.Write(content); err != nil { a.Logger.Debugln(err) return "", err @@ -485,8 +595,8 @@ func (a *Agent) RunPythonCode(code string, timeout int, args []string) (string, } func createWinTempDir() error { - if !trmm.FileExists(winTempDir) { - err := os.Mkdir(winTempDir, 0775) + if !trmm.FileExists(defaultWinTmpDir) { + err := os.Mkdir(defaultWinTmpDir, 0775) if err != nil { return err } diff --git a/agent/agent_unix.go b/agent/agent_unix.go index 9d23590..80d81c1 100644 --- a/agent/agent_unix.go +++ b/agent/agent_unix.go @@ -2,7 +2,7 @@ // +build !windows /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. @@ -16,6 +16,8 @@ package agent import ( "bufio" + "crypto/tls" + "errors" "fmt" "os" "path/filepath" @@ -50,7 +52,7 @@ func (a *Agent) GetDisks() []trmm.Disk { } for _, p := range partitions { - if strings.Contains(p.Device, "dev/loop") { + if strings.Contains(p.Device, "dev/loop") || strings.Contains(p.Device, "devfs") { continue } usage, err := disk.Usage(p.Mountpoint) @@ -158,17 +160,19 @@ func NewAgentConfig() *rmm.AgentConfig { NatsProxyPath: viper.GetString("natsproxypath"), NatsProxyPort: viper.GetString("natsproxyport"), NatsStandardPort: viper.GetString("natsstandardport"), + NatsPingInterval: viper.GetInt("natspinginterval"), + Insecure: viper.GetString("insecure"), } 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) - f, err := createTmpFile() + f, err := createNixTmpFile() if err != nil { - a.Logger.Errorln("RunScript createTmpFile()", err) + a.Logger.Errorln("RunScript createNixTmpFile()", err) return "", err.Error(), 85, err } defer os.Remove(f.Name()) @@ -192,6 +196,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 := "" @@ -216,18 +221,22 @@ func (a *Agent) seEnforcing() bool { return out.Status.Exit == 0 && strings.Contains(out.Stdout, "Enforcing") } -func (a *Agent) AgentUpdate(url, inno, version string) { +func (a *Agent) AgentUpdate(url, inno, version string) error { self, err := os.Executable() if err != nil { a.Logger.Errorln("AgentUpdate() os.Executable():", err) - return + return err } - f, err := createTmpFile() + // more reliable method to get current working directory than os.Getwd() + cwd := filepath.Dir(self) + // create a tmpfile in same location as current binary + // avoids issues with /tmp dir and other fs mount issues + f, err := os.CreateTemp(cwd, "trmm") if err != nil { - a.Logger.Errorln("AgentUpdate createTmpFile()", err) - return + a.Logger.Errorln("AgentUpdate() os.CreateTemp:", err) + return err } defer os.Remove(f.Name()) @@ -241,65 +250,59 @@ func (a *Agent) AgentUpdate(url, inno, version string) { if len(a.Proxy) > 0 { rClient.SetProxy(a.Proxy) } + if a.Insecure { + insecureConf := &tls.Config{ + InsecureSkipVerify: true, + } + rClient.SetTLSClientConfig(insecureConf) + } r, err := rClient.R().SetOutput(f.Name()).Get(url) if err != nil { a.Logger.Errorln("AgentUpdate() download:", err) f.Close() - return + return err } if r.IsError() { a.Logger.Errorln("AgentUpdate() status code:", r.StatusCode()) f.Close() - return + return errors.New("err") } f.Close() os.Chmod(f.Name(), 0755) err = os.Rename(f.Name(), self) if err != nil { - 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 - } + a.Logger.Errorln("AgentUpdate() os.Rename():", err) + return err } - if a.seEnforcing() { + if runtime.GOOS == "linux" && a.seEnforcing() { se := a.NewCMDOpts() se.Command = fmt.Sprintf("restorecon -rv %s", self) out := a.CmdV2(se) - a.Logger.Debugln("%+v\n", out) + a.Logger.Debugf("%+v\n", out) } opts := a.NewCMDOpts() 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 nil + } + a.CmdV2(opts) + return nil } func (a *Agent) AgentUninstall(code string) { - f, err := createTmpFile() + f, err := createNixTmpFile() if err != nil { - a.Logger.Errorln("AgentUninstall createTmpFile():", err) + a.Logger.Errorln("AgentUninstall createNixTmpFile():", err) return } @@ -310,7 +313,9 @@ func (a *Agent) AgentUninstall(code string) { opts := a.NewCMDOpts() opts.IsScript = true opts.Shell = f.Name() - opts.Args = []string{"uninstall"} + if runtime.GOOS == "linux" { + opts.Args = []string{"uninstall"} + } opts.Detached = true a.CmdV2(opts) } @@ -354,7 +359,15 @@ func (a *Agent) getMeshNodeID() (string, error) { func (a *Agent) RecoverMesh() { a.Logger.Infoln("Attempting mesh recovery") 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.SyncMeshNodeID() } @@ -413,18 +426,25 @@ func (a *Agent) GetWMIInfo() map[string]interface{} { wmiInfo["make_model"] = "" chassis, err := ghw.Chassis(ghw.WithDisableWarnings()) if err != nil { - a.Logger.Errorln("ghw.Chassis()", err) + a.Logger.Debugln("ghw.Chassis()", err) } else { if 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 gpu, err := ghw.GPU(ghw.WithDisableWarnings()) if err != nil { - a.Logger.Errorln("ghw.GPU()", err) + a.Logger.Debugln("ghw.GPU()", err) } else { for _, i := range gpu.GraphicsCards { if i.DeviceInfo != nil { @@ -466,6 +486,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 } diff --git a/agent/agent_windows.go b/agent/agent_windows.go index 00e489c..140c403 100644 --- a/agent/agent_windows.go +++ b/agent/agent_windows.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. @@ -14,9 +14,9 @@ package agent import ( "bytes" "context" + "crypto/tls" "errors" "fmt" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -62,27 +62,36 @@ func NewAgentConfig() *rmm.AgentConfig { cert, _, _ := k.GetStringValue("Cert") proxy, _, _ := k.GetStringValue("Proxy") customMeshDir, _, _ := k.GetStringValue("MeshDir") + winTmpDir, _, _ := k.GetStringValue("WinTmpDir") + winRunAsUserTmpDir, _, _ := k.GetStringValue("WinRunAsUserTmpDir") natsProxyPath, _, _ := k.GetStringValue("NatsProxyPath") natsProxyPort, _, _ := k.GetStringValue("NatsProxyPort") natsStandardPort, _, _ := k.GetStringValue("NatsStandardPort") + natsPingInterval, _, _ := k.GetStringValue("NatsPingInterval") + npi, _ := strconv.Atoi(natsPingInterval) + insecure, _, _ := k.GetStringValue("Insecure") return &rmm.AgentConfig{ - BaseURL: baseurl, - AgentID: agentid, - APIURL: apiurl, - Token: token, - AgentPK: agentpk, - PK: pk, - Cert: cert, - Proxy: proxy, - CustomMeshDir: customMeshDir, - NatsProxyPath: natsProxyPath, - NatsProxyPort: natsProxyPort, - NatsStandardPort: natsStandardPort, + BaseURL: baseurl, + AgentID: agentid, + APIURL: apiurl, + Token: token, + AgentPK: agentpk, + PK: pk, + Cert: cert, + Proxy: proxy, + CustomMeshDir: customMeshDir, + WinTmpDir: winTmpDir, + WinRunAsUserTmpDir: winRunAsUserTmpDir, + NatsProxyPath: natsProxyPath, + NatsProxyPort: natsProxyPort, + NatsStandardPort: natsStandardPort, + NatsPingInterval: npi, + Insecure: insecure, } } -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) @@ -111,7 +120,13 @@ func (a *Agent) RunScript(code string, shell string, args []string, timeout int, ext = "*.bat" } - tmpfn, err := ioutil.TempFile(winTempDir, ext) + tmpDir := a.WinTmpDir + + if runasuser { + tmpDir = a.WinRunAsUserTmpDir + } + + tmpfn, err := os.CreateTemp(tmpDir, ext) if err != nil { a.Logger.Errorln(err) return "", err.Error(), 85, err @@ -129,7 +144,7 @@ func (a *Agent) RunScript(code string, shell string, args []string, timeout int, switch shell { case "powershell": - exe = "Powershell" + exe = getPowershellExe() cmdArgs = []string{"-NonInteractive", "-NoProfile", "-ExecutionPolicy", "Bypass", tmpfn.Name()} case "python": exe = a.PyBin @@ -146,14 +161,33 @@ func (a *Agent) RunScript(code string, shell string, args []string, timeout int, defer cancel() var timedOut = false + var token *wintoken.Token + var envBlock *uint16 + usingEnvVars := len(envVars) > 0 cmd := exec.Command(exe, cmdArgs...) if runasuser { - token, err := wintoken.GetInteractiveToken(wintoken.TokenImpersonation) - if err != nil { - return "", err.Error(), 66, err + token, err = wintoken.GetInteractiveToken(wintoken.TokenImpersonation) + if err == nil { + defer token.Close() + cmd.SysProcAttr = &syscall.SysProcAttr{Token: syscall.Token(token.Token()), HideWindow: true} + + if usingEnvVars { + envBlock, err = CreateEnvironmentBlock(syscall.Token(token.Token())) + if err == nil { + defer DestroyEnvironmentBlock(envBlock) + userEnv := EnvironmentBlockToSlice(envBlock) + cmd.Env = userEnv + } else { + cmd.Env = os.Environ() + } + } } - defer token.Close() - cmd.SysProcAttr = &syscall.SysProcAttr{Token: syscall.Token(token.Token()), HideWindow: true} + } else if usingEnvVars { + cmd.Env = os.Environ() + } + + if usingEnvVars { + cmd.Env = append(cmd.Env, envVars...) } cmd.Stdout = &outb cmd.Stderr = &errb @@ -252,23 +286,25 @@ func CMDShell(shell string, cmdArgs []string, command string, timeout int, detac defer cancel() sysProcAttr := &windows.SysProcAttr{} + cmdExe := getCMDExe() + powershell := getPowershellExe() if len(cmdArgs) > 0 && command == "" { switch shell { case "cmd": cmdArgs = append([]string{"/C"}, cmdArgs...) - cmd = exec.Command("cmd.exe", cmdArgs...) + cmd = exec.Command(cmdExe, cmdArgs...) case "powershell": cmdArgs = append([]string{"-NonInteractive", "-NoProfile"}, cmdArgs...) - cmd = exec.Command("powershell.exe", cmdArgs...) + cmd = exec.Command(powershell, cmdArgs...) } } else { switch shell { case "cmd": - cmd = exec.Command("cmd.exe") - sysProcAttr.CmdLine = fmt.Sprintf("cmd.exe /C %s", command) + cmd = exec.Command(cmdExe) + sysProcAttr.CmdLine = fmt.Sprintf("%s /C %s", cmdExe, command) case "powershell": - cmd = exec.Command("Powershell", "-NonInteractive", "-NoProfile", command) + cmd = exec.Command(powershell, "-NonInteractive", "-NoProfile", command) } } @@ -577,15 +613,16 @@ func (a *Agent) UninstallCleanup() { a.PatchMgmnt(false) a.CleanupAgentUpdates() CleanupSchedTasks() - os.RemoveAll(winTempDir) + os.RemoveAll(a.WinTmpDir) + os.RemoveAll(a.WinRunAsUserTmpDir) } -func (a *Agent) AgentUpdate(url, inno, version string) { +func (a *Agent) AgentUpdate(url, inno, version string) error { time.Sleep(time.Duration(randRange(1, 15)) * time.Second) a.KillHungUpdates() time.Sleep(1 * time.Second) a.CleanupAgentUpdates() - updater := filepath.Join(winTempDir, inno) + updater := filepath.Join(a.WinTmpDir, inno) a.Logger.Infof("Agent updating from %s to %s", a.Version, version) a.Logger.Debugln("Downloading agent update from", url) @@ -596,19 +633,24 @@ func (a *Agent) AgentUpdate(url, inno, version string) { if len(a.Proxy) > 0 { rClient.SetProxy(a.Proxy) } + if a.Insecure { + insecureConf := &tls.Config{ + InsecureSkipVerify: true, + } + rClient.SetTLSClientConfig(insecureConf) + } r, err := rClient.R().SetOutput(updater).Get(url) if err != nil { a.Logger.Errorln(err) - CMD("net", []string{"start", winSvcName}, 10, false) - return + return err } if r.IsError() { - a.Logger.Errorln("Download failed with status code", r.StatusCode()) - CMD("net", []string{"start", winSvcName}, 10, false) - return + ret := fmt.Sprintf("Download failed with status code %d", r.StatusCode()) + a.Logger.Errorln(ret) + return errors.New(ret) } - innoLogFile := filepath.Join(winTempDir, fmt.Sprintf("tacticalagent_update_v%s.txt", version)) + innoLogFile := filepath.Join(a.WinTmpDir, fmt.Sprintf("tacticalagent_update_v%s.txt", version)) args := []string{"/C", updater, "/VERYSILENT", fmt.Sprintf("/LOG=%s", innoLogFile)} cmd := exec.Command("cmd.exe", args...) @@ -617,6 +659,7 @@ func (a *Agent) AgentUpdate(url, inno, version string) { } cmd.Start() time.Sleep(1 * time.Second) + return nil } func (a *Agent) osString() string { @@ -653,18 +696,6 @@ func (a *Agent) AgentUninstall(code string) { cmd.Start() } -func (a *Agent) addDefenderExlusions() { - 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) - } -} - // RunMigrations cleans up unused stuff from older agents func (a *Agent) RunMigrations() { for _, i := range []string{"nssm.exe", "nssm-x86.exe"} { @@ -867,6 +898,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" diff --git a/agent/checkin.go b/agent/checkin.go index 9990198..6c9923a 100644 --- a/agent/checkin.go +++ b/agent/checkin.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. diff --git a/agent/checks.go b/agent/checks.go index 531bf74..930e947 100644 --- a/agent/checks.go +++ b/agent/checks.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. @@ -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, diff --git a/agent/choco_windows.go b/agent/choco_windows.go index c37f025..f75b15f 100644 --- a/agent/choco_windows.go +++ b/agent/choco_windows.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. @@ -12,6 +12,9 @@ https://license.tacticalrmm.com package agent import ( + "os" + "os/exec" + "path/filepath" "time" rmm "github.com/amidaware/rmmagent/shared" @@ -42,7 +45,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) @@ -59,7 +62,14 @@ func (a *Agent) InstallChoco() { } func (a *Agent) InstallWithChoco(name string) (string, error) { - out, err := CMD("choco.exe", []string{"install", name, "--yes", "--force", "--force-dependencies", "--no-progress"}, 1200, false) + var exe string + choco, err := exec.LookPath("choco.exe") + if err != nil || choco == "" { + exe = filepath.Join(os.Getenv("PROGRAMDATA"), `chocolatey\bin\choco.exe`) + } else { + exe = choco + } + out, err := CMD(exe, []string{"install", name, "--yes", "--force", "--force-dependencies", "--no-progress"}, 1200, false) if err != nil { a.Logger.Errorln(err) return err.Error(), err diff --git a/agent/embed_darwin.go b/agent/embed_darwin.go new file mode 100644 index 0000000..6a42a6d --- /dev/null +++ b/agent/embed_darwin.go @@ -0,0 +1,24 @@ +//go:build darwin +// +build darwin + +/* +Copyright 2023 Amidaware Inc. + +Licensed under the Tactical RMM License Version 1.0 (the “License”). +You may only use the Licensed Software in accordance with the License. +A copy of the License is available at: + +https://license.tacticalrmm.com + +*/ + +package agent + +import _ "embed" + +//go:embed scripts/macos_fix_mesh_install.sh +var ventura_mesh_fix string + +func (a *Agent) FixVenturaMesh() { + a.RunScript(ventura_mesh_fix, "foo", []string{}, 45, false, []string{}) +} diff --git a/agent/embed_stub.go b/agent/embed_stub.go new file mode 100644 index 0000000..68f799f --- /dev/null +++ b/agent/embed_stub.go @@ -0,0 +1,17 @@ +//go:build !darwin +// +build !darwin + +/* +Copyright 2023 Amidaware Inc. + +Licensed under the Tactical RMM License Version 1.0 (the “License”). +You may only use the Licensed Software in accordance with the License. +A copy of the License is available at: + +https://license.tacticalrmm.com + +*/ + +package agent + +func (a *Agent) FixVenturaMesh() {} diff --git a/agent/eventlog_windows.go b/agent/eventlog_windows.go index c1313ef..f4c9fec 100644 --- a/agent/eventlog_windows.go +++ b/agent/eventlog_windows.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. diff --git a/agent/install.go b/agent/install.go index b03518c..1d6c75a 100644 --- a/agent/install.go +++ b/agent/install.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. @@ -12,6 +12,7 @@ https://license.tacticalrmm.com package agent import ( + "crypto/tls" "fmt" "io" "net/url" @@ -28,25 +29,27 @@ import ( ) type Installer struct { - Headers map[string]string - RMM string - ClientID int - SiteID int - Description string - AgentType string - Power bool - RDP bool - Ping bool - Token string - LocalMesh string - Cert string - Proxy string - Timeout time.Duration - SaltMaster string - Silent bool - NoMesh bool - MeshDir string - MeshNodeID string + Headers map[string]string + RMM string + ClientID int + SiteID int + Description string + AgentType string + Power bool + RDP bool + Ping bool + Token string + LocalMesh string + Cert string + Proxy string + Timeout time.Duration + SaltMaster string + Silent bool + NoMesh bool + MeshDir string + MeshNodeID string + Insecure bool + NatsStandardPort string } func (a *Agent) Install(i *Installer) { @@ -97,6 +100,14 @@ func (a *Agent) Install(i *Installer) { iClient.SetProxy(i.Proxy) } + insecureConf := &tls.Config{ + InsecureSkipVerify: true, + } + + if i.Insecure { + iClient.SetTLSClientConfig(insecureConf) + } + creds, cerr := iClient.R().Get(fmt.Sprintf("%s/api/v3/installer/", baseURL)) if cerr != nil { a.installerMsg(cerr.Error(), "error", i.Silent) @@ -133,6 +144,10 @@ func (a *Agent) Install(i *Installer) { rClient.SetProxy(i.Proxy) } + if i.Insecure { + rClient.SetTLSClientConfig(insecureConf) + } + var installerMeshSystemEXE string if len(i.MeshDir) > 0 { installerMeshSystemEXE = filepath.Join(i.MeshDir, "MeshAgent.exe") @@ -140,34 +155,58 @@ func (a *Agent) Install(i *Installer) { installerMeshSystemEXE = a.MeshSystemEXE } - var meshNodeID string + var meshNodeID, meshOutput string - if runtime.GOOS == "windows" && !i.NoMesh { - mesh := filepath.Join(a.ProgramDir, a.MeshInstaller) - if i.LocalMesh == "" { + if !i.NoMesh && runtime.GOOS != "linux" { + switch runtime.GOOS { + case "windows": + meshOutput = filepath.Join(a.ProgramDir, a.MeshInstaller) + case "darwin": + tmp, err := createNixTmpFile() + 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...") 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 { a.installerMsg(fmt.Sprintf("Failed to download mesh agent: %s", err.Error()), "error", i.Silent) } if r.StatusCode() != 200 { 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.Debugln("Mesh agent:", mesh) + a.Logger.Debugln("Mesh agent:", meshOutput) time.Sleep(1 * time.Second) - meshNodeID, err = a.installMesh(mesh, installerMeshSystemEXE, i.Proxy) - if err != nil { - a.installerMsg(fmt.Sprintf("Failed to install mesh agent: %s", err.Error()), "error", i.Silent) + if runtime.GOOS == "windows" { + meshNodeID, err = a.installMesh(meshOutput, installerMeshSystemEXE, i.Proxy) + 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 --installPath=%s", meshOutput, nixMeshDir) + opts.Timeout = i.Timeout + out := a.CmdV2(opts) + if out.Status.Exit != 0 { + a.Logger.Fatalln("Error installing mesh agent:", out.Stderr) + } + fmt.Println(out.Stdout) } } @@ -206,7 +245,7 @@ func (a *Agent) Install(i *Installer) { a.Logger.Debugln("Agent token:", agentToken) a.Logger.Debugln("Agent PK:", agentPK) - createAgentConfig(baseURL, a.AgentID, i.SaltMaster, agentToken, strconv.Itoa(agentPK), i.Cert, i.Proxy, i.MeshDir) + createAgentConfig(baseURL, a.AgentID, i.SaltMaster, agentToken, strconv.Itoa(agentPK), i.Cert, i.Proxy, i.MeshDir, i.NatsStandardPort, i.Insecure) time.Sleep(1 * time.Second) // refresh our agent with new values a = New(a.Logger, a.Version) @@ -219,6 +258,47 @@ func (a *Agent) Install(i *Installer) { // check in once a.DoNatsCheckIn() + if runtime.GOOS == "darwin" { + os.MkdirAll(nixAgentDir, 0755) + self, _ := os.Executable() + copyFile(self, nixAgentBin) + os.Chmod(nixAgentBin, 0755) + svc := fmt.Sprintf(` + + + + + Label + %s + + ServiceDescription + TacticalAgent Service + + ProgramArguments + + %s + -m + svc + + + WorkingDirectory + %s/ + + RunAtLoad + + + KeepAlive + + + +`, 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" { // send software api a.SendSoftware() @@ -245,9 +325,6 @@ func (a *Agent) Install(i *Installer) { a.installerMsg(out.ErrorMsg, "error", i.Silent) } - a.Logger.Infoln("Adding windows defender exclusions") - a.addDefenderExlusions() - if i.Power { a.Logger.Infoln("Disabling sleep/hibernate...") DisableSleepHibernate() diff --git a/agent/install_unix.go b/agent/install_unix.go index cf6a068..b1e76b0 100644 --- a/agent/install_unix.go +++ b/agent/install_unix.go @@ -2,7 +2,7 @@ // +build !windows /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. @@ -15,17 +15,16 @@ https://license.tacticalrmm.com package agent import ( + "fmt" "log" + "os" + "runtime" + "time" "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) { if alert == "error" { a.Logger.Fatalln(msg) @@ -34,7 +33,7 @@ func (a *Agent) installerMsg(msg, alert string, silent bool) { } } -func createAgentConfig(baseurl, agentid, apiurl, token, agentpk, cert, proxy, meshdir string) { +func createAgentConfig(baseurl, agentid, apiurl, token, agentpk, cert, proxy, meshdir, natsport string, insecure bool) { viper.SetConfigType("json") viper.Set("baseurl", baseurl) viper.Set("agentid", agentid) @@ -44,6 +43,10 @@ func createAgentConfig(baseurl, agentid, apiurl, token, agentpk, cert, proxy, me viper.Set("cert", cert) viper.Set("proxy", proxy) viper.Set("meshdir", meshdir) + viper.Set("natsstandardport", natsport) + if insecure { + viper.Set("insecure", "true") + } viper.SetConfigPermissions(0660) err := viper.SafeWriteConfigAs(etcConfig) if err != nil { @@ -51,7 +54,31 @@ func createAgentConfig(baseurl, agentid, apiurl, token, agentpk, cert, proxy, me } } -func (a *Agent) addDefenderExlusions() {} +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(defaultMacMeshSvcDir) + os.RemoveAll(nixMeshDir) + os.Remove(etcConfig) + os.RemoveAll(nixAgentDir) + os.Remove(macPlistPath) + } +} func DisableSleepHibernate() {} diff --git a/agent/install_windows.go b/agent/install_windows.go index 3f8b630..aa2c434 100644 --- a/agent/install_windows.go +++ b/agent/install_windows.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. @@ -21,7 +21,7 @@ import ( "golang.org/x/sys/windows/registry" ) -func createAgentConfig(baseurl, agentid, apiurl, token, agentpk, cert, proxy, meshdir string) { +func createAgentConfig(baseurl, agentid, apiurl, token, agentpk, cert, proxy, meshdir, natsport string, insecure bool) { k, _, err := registry.CreateKey(registry.LOCAL_MACHINE, `SOFTWARE\TacticalRMM`, registry.ALL_ACCESS) if err != nil { log.Fatalln("Error creating registry key:", err) @@ -73,6 +73,20 @@ func createAgentConfig(baseurl, agentid, apiurl, token, agentpk, cert, proxy, me log.Fatalln("Error creating MeshDir registry key:", err) } } + + if len(natsport) > 0 { + err = k.SetStringValue("NatsStandardPort", natsport) + if err != nil { + log.Fatalln("Error creating NatsStandardPort registry key:", err) + } + } + + if insecure { + err = k.SetStringValue("Insecure", "true") + if err != nil { + log.Fatalln("Error creating Insecure registry key:", err) + } + } } func (a *Agent) checkExistingAndRemove(silent bool) { diff --git a/agent/patches_windows.go b/agent/patches_windows.go index 7d41baf..81c71cd 100644 --- a/agent/patches_windows.go +++ b/agent/patches_windows.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. diff --git a/agent/process.go b/agent/process.go index ae7c392..b4d5f5a 100644 --- a/agent/process.go +++ b/agent/process.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. diff --git a/agent/rpc.go b/agent/rpc.go index ce2a89c..8ecae5c 100644 --- a/agent/rpc.go +++ b/agent/rpc.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. @@ -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 ( @@ -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 @@ -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 @@ -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 { @@ -475,10 +481,15 @@ func (a *Agent) RunRPC() { } else { ret.Encode("ok") msg.Respond(resp) - a.AgentUpdate(p.Data["url"], p.Data["inno"], p.Data["version"]) + err := a.AgentUpdate(p.Data["url"], p.Data["inno"], p.Data["version"]) + if err != nil { + atomic.StoreUint32(&agentUpdateLocker, 0) + return + } atomic.StoreUint32(&agentUpdateLocker, 0) nc.Flush() nc.Close() + a.ControlService(winSvcName, "stop") os.Exit(0) } }(payload) diff --git a/agent/scripts/macos_fix_mesh_install.sh b/agent/scripts/macos_fix_mesh_install.sh new file mode 100644 index 0000000..b6e9c0b --- /dev/null +++ b/agent/scripts/macos_fix_mesh_install.sh @@ -0,0 +1,90 @@ +#!/usr/bin/env bash + +# source: https://github.com/amidaware/community-scripts/blob/main/scripts_staging/macos_fix_mesh_install.sh +# author: https://github.com/NiceGuyIT + +# This script fixes MeshAgent issue #161: MacOS Ventura - Not starting meshagent on boot (Maybe Solved) +# https://github.com/Ylianst/MeshAgent/issues/161 +# +# The following actions are taken: +# 1) Add the eXecute bit for directory traversal for the installation directory. This allows regular users +# access to run the binary inside the directory, fixing the "meshagent" LaunchAgent integration with the +# user. +# 2) Rename the LaunchAgent "meshagent.plist" to prevent conflicts with the LaunchDaemon "meshagent.plist". +# This may not be needed but is done for good measure. +# 3) Rename the service Label inside the plist. Using "defaults" causes the plist to be rewritten in plist +# format, not ascii. +# +# Here's the original plist from my install. +# +# +# +# +# Label +# meshagent +# ProgramArguments +# +# /opt/tacticalmesh/meshagent +# -kvm1 +# +# +# WorkingDirectory +# /opt/tacticalmesh +# +# RunAtLoad +# +# LimitLoadToSessionType +# +# LoginWindow +# +# KeepAlive +# +# Crashed +# +# +# +# + + +mesh_install_dir="/opt/tacticalmesh/" +mesh_agent_plist_old="/Library/LaunchAgents/meshagent.plist" +mesh_agent_plist="/Library/LaunchAgents/meshagent-agent.plist" +mesh_daemon_plist="/Library/LaunchDaemons/meshagent.plist" + +if [ ! -f "${mesh_daemon_plist}" ] +then + echo "meshagent LaunchDaemon does not exist to cause the duplicate service name issue. Exiting." + exit 0 +fi + +if /usr/bin/stat -f "%Sp" "${mesh_install_dir}" | grep -v 'x$' >/dev/null +then + echo "Fixing permissions on meshagent installation directory: ${mesh_install_dir}" + chmod o+X "${mesh_install_dir}" +else + echo "No action taken. Permissions on meshagent installation directory have already been fixed." +fi +echo + +if [ -f "${mesh_agent_plist_old}" ] +then + echo "Renaming agent plist: ${mesh_agent_plist_old}" + mv "${mesh_agent_plist_old}" "${mesh_agent_plist}" +else + echo "No action taken. meshagent.plist was already renamed: ${mesh_agent_plist}" +fi +echo + +# New file has to exist before renaming the label. +if [ -f "${mesh_agent_plist}" ] +then + label=$(defaults read "${mesh_agent_plist}" Label) + if [ "${label}" != "meshagent-agent" ] + then + echo "Renaming meshagent label in plist: ${mesh_agent_plist}" + echo "Warning: This will convert the plist from a text file to a binary plist file." + defaults write "${mesh_agent_plist}" Label "meshagent-agent" + else + echo "No action taken. meshagent label was already renamed: ${label}" + fi +fi diff --git a/agent/services_windows.go b/agent/services_windows.go index 75624f5..e782021 100644 --- a/agent/services_windows.go +++ b/agent/services_windows.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. diff --git a/agent/software_windows_386.go b/agent/software_windows_386.go index 1be5cd0..b747268 100644 --- a/agent/software_windows_386.go +++ b/agent/software_windows_386.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. diff --git a/agent/software_windows_amd64.go b/agent/software_windows_amd64.go index ce84005..bb5dc50 100644 --- a/agent/software_windows_amd64.go +++ b/agent/software_windows_amd64.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. diff --git a/agent/svc.go b/agent/svc.go index 4ca85c2..e7f03ea 100644 --- a/agent/svc.go +++ b/agent/svc.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. @@ -12,58 +12,86 @@ https://license.tacticalrmm.com package agent import ( + "fmt" + "runtime" "sync" "time" nats "github.com/nats-io/nats.go" ) -func (a *Agent) RunAsService() { +func (a *Agent) RunAsService(nc *nats.Conn) { var wg sync.WaitGroup wg.Add(1) - go a.AgentSvc() + go a.AgentSvc(nc) go a.CheckRunner() wg.Wait() } -func (a *Agent) AgentSvc() { - go a.GetPython(false) +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"` +} - err := createWinTempDir() - if err != nil { - a.Logger.Errorln("AgentSvc() createWinTempDir():", err) +func (a *Agent) AgentSvc(nc *nats.Conn) { + if runtime.GOOS == "windows" { + go a.GetPython(false) + + err := createWinTempDir() + if err != nil { + a.Logger.Errorln("AgentSvc() createWinTempDir():", err) + } } a.RunMigrations() - sleepDelay := randRange(14, 22) + sleepDelay := randRange(7, 25) a.Logger.Debugf("AgentSvc() sleeping for %v seconds", sleepDelay) time.Sleep(time.Duration(sleepDelay) * time.Second) - opts := a.setupNatsOptions() - nc, err := nats.Connect(a.NatsServer, opts...) - if err != nil { - a.Logger.Fatalln("AgentSvc() nats.Connect()", err) + if runtime.GOOS == "windows" { + a.KillHungUpdates() + time.Sleep(1 * time.Second) + a.CleanupAgentUpdates() } + conf := a.GetAgentCheckInConfig(a.GetCheckInConfFromAPI()) + a.Logger.Debugf("+%v\n", conf) for _, s := range natsCheckin { - a.NatsMessage(nc, s) - time.Sleep(time.Duration(randRange(100, 400)) * time.Millisecond) + if conf.LimitData && stringInSlice(s, limitNatsData) { + continue + } else { + a.NatsMessage(nc, s) + time.Sleep(time.Duration(randRange(100, 400)) * time.Millisecond) + } } go a.SyncMeshNodeID() time.Sleep(time.Duration(randRange(1, 3)) * time.Second) - a.AgentStartup() - a.SendSoftware() + if runtime.GOOS == "windows" && !conf.LimitData { + a.AgentStartup() + a.SendSoftware() + } - checkInHelloTicker := time.NewTicker(time.Duration(randRange(30, 60)) * time.Second) - checkInAgentInfoTicker := time.NewTicker(time.Duration(randRange(200, 400)) * time.Second) - checkInWinSvcTicker := time.NewTicker(time.Duration(randRange(2400, 3000)) * time.Second) - checkInPubIPTicker := time.NewTicker(time.Duration(randRange(300, 500)) * time.Second) - checkInDisksTicker := time.NewTicker(time.Duration(randRange(1000, 2000)) * time.Second) - checkInSWTicker := time.NewTicker(time.Duration(randRange(2800, 3500)) * time.Second) - checkInWMITicker := time.NewTicker(time.Duration(randRange(3000, 4000)) * time.Second) - syncMeshTicker := time.NewTicker(time.Duration(randRange(800, 1200)) * time.Second) + if runtime.GOOS == "darwin" { + go a.FixVenturaMesh() + } + + checkInHelloTicker := time.NewTicker(time.Duration(conf.Hello) * time.Second) + checkInAgentInfoTicker := time.NewTicker(time.Duration(conf.AgentInfo) * time.Second) + checkInWinSvcTicker := time.NewTicker(time.Duration(conf.WinSvc) * time.Second) + checkInPubIPTicker := time.NewTicker(time.Duration(conf.PubIP) * time.Second) + checkInDisksTicker := time.NewTicker(time.Duration(conf.Disks) * time.Second) + checkInSWTicker := time.NewTicker(time.Duration(conf.SW) * time.Second) + checkInWMITicker := time.NewTicker(time.Duration(conf.WMI) * time.Second) + syncMeshTicker := time.NewTicker(time.Duration(conf.SyncMesh) * time.Second) for { select { @@ -95,3 +123,32 @@ func (a *Agent) AgentStartup() { 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 +} diff --git a/agent/syscall_windows.go b/agent/syscall_windows.go index 26173ef..2d8b8c8 100644 --- a/agent/syscall_windows.go +++ b/agent/syscall_windows.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. @@ -24,11 +24,14 @@ var _ unsafe.Pointer var ( modadvapi32 = windows.NewLazySystemDLL("advapi32.dll") modkernel32 = windows.NewLazySystemDLL("kernel32.dll") + userenv = windows.NewLazyDLL("userenv.dll") procFormatMessageW = modkernel32.NewProc("FormatMessageW") procGetOldestEventLogRecord = modadvapi32.NewProc("GetOldestEventLogRecord") procLoadLibraryExW = modkernel32.NewProc("LoadLibraryExW") procReadEventLogW = modadvapi32.NewProc("ReadEventLogW") + procCreateEnvironmentBlock = userenv.NewProc("CreateEnvironmentBlock") + procDestroyEnvironmentBlock = userenv.NewProc("DestroyEnvironmentBlock") ) // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-eventlogrecord @@ -114,3 +117,47 @@ func ReadEventLog(eventLog w32.HANDLE, readFlags ReadFlag, recordOffset uint32, } return } + +func CreateEnvironmentBlock(token syscall.Token) (*uint16, error) { + var envBlock *uint16 + + ret, _, err := procCreateEnvironmentBlock.Call( + uintptr(unsafe.Pointer(&envBlock)), + uintptr(token), + 0, + ) + if ret == 0 { + return nil, err + } + + return envBlock, nil +} + +func DestroyEnvironmentBlock(envBlock *uint16) error { + ret, _, err := procDestroyEnvironmentBlock.Call(uintptr(unsafe.Pointer(envBlock))) + if ret == 0 { + return err + } + return nil +} + +func EnvironmentBlockToSlice(envBlock *uint16) []string { + var envs []string + + for { + len := 0 + for *(*uint16)(unsafe.Pointer(uintptr(unsafe.Pointer(envBlock)) + uintptr(len*2))) != 0 { + len++ + } + + if len == 0 { + break + } + + env := syscall.UTF16ToString((*[1 << 29]uint16)(unsafe.Pointer(envBlock))[:len]) + envs = append(envs, env) + envBlock = (*uint16)(unsafe.Pointer(uintptr(unsafe.Pointer(envBlock)) + uintptr((len+1)*2))) + } + + return envs +} diff --git a/agent/tasks_windows.go b/agent/tasks_windows.go index da3d7a2..e475a57 100644 --- a/agent/tasks_windows.go +++ b/agent/tasks_windows.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. @@ -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, action.RunAsUser) + stdout, stderr, retcode, err := a.RunScript(action.Code, action.Shell, action.Args, action.Timeout, action.RunAsUser, action.EnvVars) if err != nil { a.Logger.Debugln(err) @@ -175,12 +175,17 @@ func (a *Agent) CreateSchedTask(st SchedTask) (bool, error) { var tasktrigger taskmaster.TaskTrigger var now = time.Now() - if st.Trigger == "manual" { + switch st.Trigger { + case "manual": tasktrigger = taskmaster.TaskTrigger{ Enabled: st.Enabled, StartBoundary: now, } - } else { + case "onboarding": + tasktrigger = taskmaster.TaskTrigger{ + Enabled: st.Enabled, + } + default: tasktrigger = taskmaster.TaskTrigger{ Enabled: st.Enabled, StartBoundary: time.Date(st.StartYear, st.StartMonth, st.StartDay, st.StartHour, st.StartMinute, 0, 0, now.Location()), @@ -205,6 +210,11 @@ func (a *Agent) CreateSchedTask(st SchedTask) (bool, error) { TaskTrigger: tasktrigger, RandomDelay: st.RandomDelay, } + case "onboarding": + trigger = taskmaster.RegistrationTrigger{ + TaskTrigger: tasktrigger, + Delay: st.RandomDelay, + } case "daily": trigger = taskmaster.DailyTrigger{ diff --git a/agent/utils.go b/agent/utils.go index f5916f8..6eacaca 100644 --- a/agent/utils.go +++ b/agent/utils.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. @@ -20,9 +20,11 @@ import ( "math/rand" "net" "os" + "os/exec" "path/filepath" "runtime" goDebug "runtime/debug" + "strconv" "strings" "time" @@ -59,7 +61,7 @@ func DoPing(host string) (PingResponse, error) { } pinger.Count = 3 - pinger.Size = 24 + pinger.Size = 548 pinger.Interval = time.Second pinger.Timeout = 5 * time.Second pinger.SetPrivileged(true) @@ -126,7 +128,6 @@ func (a *Agent) PublicIP() string { // GenerateAgentID creates and returns a unique agent id func GenerateAgentID() string { - rand.Seed(time.Now().UnixNano()) letters := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") b := make([]rune, 40) for i := range b { @@ -295,7 +296,6 @@ func ByteCountSI(b uint64) string { } func randRange(min, max int) int { - rand.Seed(time.Now().UnixNano()) return rand.Intn(max-min) + min } @@ -307,18 +307,59 @@ func removeWinNewLines(s string) string { return strings.ReplaceAll(s, "\r\n", "\n") } -func createTmpFile() (*os.File, error) { - var f *os.File - f, err := os.CreateTemp("", "trmm") - if err != nil { - cwd, err := os.Getwd() - if err != nil { - return f, err - } - f, err = os.CreateTemp(cwd, "trmm") - if err != nil { - return f, err +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) +} + +func getPowershellExe() string { + powershell, err := exec.LookPath("powershell.exe") + if err != nil || powershell == "" { + return filepath.Join(os.Getenv("WINDIR"), `System32\WindowsPowerShell\v1.0\powershell.exe`) + } + return powershell +} + +func getCMDExe() string { + cmdExe, err := exec.LookPath("cmd.exe") + if err != nil || cmdExe == "" { + return filepath.Join(os.Getenv("WINDIR"), `System32\cmd.exe`) + } + return cmdExe +} + +// more accurate than os.Getwd() +func getCwd() (string, error) { + self, err := os.Executable() + if err != nil { + return "", err + } + + return filepath.Dir(self), nil +} + +func createNixTmpFile() (*os.File, error) { + var f *os.File + cwd, err := getCwd() + if err != nil { + return f, err + } + + f, err = os.CreateTemp(cwd, "trmm") + if err != nil { + return f, err + } + return f, nil } diff --git a/agent/wmi_windows.go b/agent/wmi_windows.go index 194ecb0..13ca8ef 100644 --- a/agent/wmi_windows.go +++ b/agent/wmi_windows.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. diff --git a/agent/wua_windows.go b/agent/wua_windows.go index bc76230..913bcd4 100644 --- a/agent/wua_windows.go +++ b/agent/wua_windows.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. diff --git a/build/rmm.exe.manifest b/build/rmm.exe.manifest index df6fc51..126fa9d 100644 --- a/build/rmm.exe.manifest +++ b/build/rmm.exe.manifest @@ -3,7 +3,7 @@ diff --git a/build/setup.iss b/build/setup.iss index cae5a3e..8c58b27 100644 --- a/build/setup.iss +++ b/build/setup.iss @@ -1,6 +1,6 @@ #define MyAppName "Tactical RMM Agent" -#define MyAppVersion "2.3.0" -#define MyAppPublisher "AmidaWare LLC" +#define MyAppVersion "2.6.1" +#define MyAppPublisher "AmidaWare Inc" #define MyAppURL "https://github.com/amidaware" #define MyAppExeName "tacticalrmm.exe" #define MESHEXE "meshagent.exe" diff --git a/go.mod b/go.mod index 1b3f190..9cf4082 100644 --- a/go.mod +++ b/go.mod @@ -1,42 +1,41 @@ module github.com/amidaware/rmmagent -go 1.18 +go 1.20 require ( github.com/StackExchange/wmi v1.2.1 - github.com/elastic/go-sysinfo v1.8.1 - github.com/go-ole/go-ole v1.2.6 + github.com/elastic/go-sysinfo v1.11.1 + github.com/go-ole/go-ole v1.3.0 github.com/go-ping/ping v1.1.0 - github.com/go-resty/resty/v2 v2.7.0 - github.com/gonutz/w32/v2 v2.4.0 - github.com/iamacarpet/go-win64api v0.0.0-20220531131246-e84054eb584d - github.com/nats-io/nats-server/v2 v2.8.4 // indirect - github.com/nats-io/nats.go v1.16.0 + github.com/go-resty/resty/v2 v2.10.0 + github.com/gonutz/w32/v2 v2.11.1 + github.com/iamacarpet/go-win64api v0.0.0-20230324134531-ef6dbdd6db97 + github.com/nats-io/nats.go v1.31.0 github.com/rickb777/date v1.19.1 - github.com/shirou/gopsutil/v3 v3.22.6 - github.com/sirupsen/logrus v1.9.0 - github.com/ugorji/go/codec v1.2.7 - github.com/wh1te909/go-win64api v0.0.0-20210906074314-ab23795a6ae5 + github.com/shirou/gopsutil/v3 v3.23.10 + github.com/sirupsen/logrus v1.9.3 + github.com/ugorji/go/codec v1.2.11 + github.com/wh1te909/go-win64api v0.0.0-20230802051600-21b24f62e846 github.com/wh1te909/trmm-shared v0.0.0-20220227075846-f9f757361139 - golang.org/x/net v0.0.0-20220706163947-c90051bbdb60 // indirect - golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 + golang.org/x/net v0.17.0 // indirect + golang.org/x/sys v0.14.0 ) require ( github.com/amidaware/taskmaster v0.0.0-20220111015025-c9cd178bbbf2 - github.com/go-cmd/cmd v1.4.1 + github.com/go-cmd/cmd v1.4.2 ) require ( github.com/fourcorelabs/wintoken v1.0.0 - github.com/jaypipes/ghw v0.9.0 - github.com/kardianos/service v1.2.1 - github.com/spf13/viper v1.12.0 + github.com/jaypipes/ghw v0.12.0 + github.com/kardianos/service v1.2.2 + github.com/spf13/viper v1.17.0 ) require ( github.com/elastic/go-windows v1.0.1 // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/google/cabbie v1.0.3 // indirect github.com/google/glazier v0.0.0-20220520121753-83447cca4ea7 // indirect @@ -44,36 +43,39 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/jaypipes/pcidb v1.0.0 // indirect github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 // indirect - github.com/klauspost/compress v1.15.6 // indirect + github.com/klauspost/compress v1.17.2 // indirect github.com/lufia/plan9stats v0.0.0-20220517141722-cf486979b281 // indirect - github.com/magiconair/properties v1.8.6 // indirect + github.com/magiconair/properties v1.8.7 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/nats-io/nkeys v0.3.0 // indirect + github.com/nats-io/nkeys v0.4.6 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect - github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.0.1 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/pkg/errors v0.9.1 // 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/rogpeppe/go-internal v1.8.1 // indirect + github.com/sagikazarmark/locafero v0.3.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/scjalliance/comshim v0.0.0-20190308082608-cf06d2532c4e // indirect - github.com/spf13/afero v1.8.2 // indirect - github.com/spf13/cast v1.5.0 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.10.0 // indirect + github.com/spf13/cast v1.5.1 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/subosito/gotenv v1.4.0 // indirect - github.com/tklauser/go-sysconf v0.3.10 // indirect - github.com/tklauser/numcpus v0.5.0 // indirect - github.com/yusufpapurcu/wmi v1.2.2 // indirect - golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect - golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect - golang.org/x/text v0.3.7 // indirect - golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/crypto v0.15.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/sync v0.3.0 // indirect + golang.org/x/text v0.14.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect - gopkg.in/ini.v1 v1.66.6 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index a59b705..c475d0e 100644 --- a/go.sum +++ b/go.sum @@ -39,6 +39,7 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= github.com/StackExchange/wmi v1.2.0/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= @@ -55,10 +56,14 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/creachadair/staticfile v0.1.3/go.mod h1:a3qySzCIXEprDGxk6tSxSI+dBBdLzqeBOMhZ+o2d3pM= 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/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.8.1/go.mod h1:JfllUnzoQV/JRYymbH3dO1yggI3mV2oTKSXsDHM+uIM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= +github.com/docker/docker v23.0.3+incompatible h1:9GhVsShNWz1hO//9BNg/dpMnZW25KydO4wtVxWAIbho= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/elastic/go-sysinfo v1.11.1 h1:g9mwl05njS4r69TisC+vwHWTSKywZFYYUu3so3T/Lao= +github.com/elastic/go-sysinfo v1.11.1/go.mod h1:6KQb31j0QeWBDF88jIdWSxE8cwoOB9tO4Y4osN7Q70E= 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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -69,28 +74,30 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fourcorelabs/wintoken v1.0.0 h1:dskUYLAFHNy1cbS5MXsNFXauQzxieTrZlffQZ0Yu19I= github.com/fourcorelabs/wintoken v1.0.0/go.mod h1:jKyXHt079W09KwEMbUC9g+R2KDs5kVvSKPUiF5p0ejs= -github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-cmd/cmd v1.4.1 h1:JUcEIE84v8DSy02XTZpUDeGKExk2oW3DA10hTjbQwmc= -github.com/go-cmd/cmd v1.4.1/go.mod h1:tbBenttXtZU4c5djS1o7PWL5pd2xAr5sIqH1kGdNiRc= +github.com/go-cmd/cmd v1.4.2 h1:pnX38iIJHh4huzBSqfkAZkfXrVwM/5EccAJmrVqMnbg= +github.com/go-cmd/cmd v1.4.2/go.mod h1:u3hxg/ry+D5kwh8WvUkHLAMe2zQCaXd00t35WfQaOFk= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-ping/ping v1.1.0 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw= github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk= -github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= -github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= -github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M= +github.com/go-resty/resty/v2 v2.10.0 h1:Qla4W/+TMmv0fOeeRqzEpXPLfTUnR5HZ1+lGs+CkiCo= +github.com/go-resty/resty/v2 v2.10.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A= +github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20210429001901-424d2337a529/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -117,9 +124,8 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/gonutz/w32/v2 v2.4.0 h1:k+R8/ddsnb9dwVDsTDWvkJGFmYJDI3ZMgcKgdpLuMpw= -github.com/gonutz/w32/v2 v2.4.0/go.mod h1:MgtHx0AScDVNKyB+kjyPder4xIi3XAcHS6LDDU2DmdE= +github.com/gonutz/w32/v2 v2.11.1 h1:plG738ZY7VIkPGf3adZ6lFeAf2evCKrULKyZT5GrPoc= +github.com/gonutz/w32/v2 v2.11.1/go.mod h1:MgtHx0AScDVNKyB+kjyPder4xIi3XAcHS6LDDU2DmdE= github.com/google/aukera v0.0.0-20201117230544-d145c8357fea/go.mod h1:oXqTZORBzdwQ6L32YjJmaPajqIV/hoGEouwpFMf4cJE= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -140,8 +146,10 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/logger v1.1.0/go.mod h1:w7O8nrRr0xufejBlQMI83MXqRusvREoJdaAxV+CoAB4= github.com/google/logger v1.1.1/go.mod h1:BkeJZ+1FhQ+/d087r4dzojEg1u2ZX+ZqG1jTUrLM+zQ= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -174,13 +182,12 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/iamacarpet/go-win64api v0.0.0-20210311141720-fe38760bed28/go.mod h1:oGJx9dz0Ny7HC7U55RZ0Smd6N9p3hXP/+hOFtuYrAxM= -github.com/iamacarpet/go-win64api v0.0.0-20220531131246-e84054eb584d h1:oEqcxSYuVSzQiXfTdp1BTJoowIUTPLCA3fOnfyZO50w= -github.com/iamacarpet/go-win64api v0.0.0-20220531131246-e84054eb584d/go.mod h1:B7zFQPAznj+ujXel5X+LUoK3LgY6VboCdVYHZNn7gpg= +github.com/iamacarpet/go-win64api v0.0.0-20230324134531-ef6dbdd6db97 h1:VjwKCN2PMLlMKM2k9AW8QQsfmEH43ldlX+JGeWW9cEE= +github.com/iamacarpet/go-win64api v0.0.0-20230324134531-ef6dbdd6db97/go.mod h1:B7zFQPAznj+ujXel5X+LUoK3LgY6VboCdVYHZNn7gpg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jaypipes/ghw v0.9.0 h1:TWF4wNIGtZcgDJaiNcFgby5BR8s2ixcUe0ydxNO2McY= -github.com/jaypipes/ghw v0.9.0/go.mod h1:dXMo19735vXOjpIBDyDYSp31sB2u4hrtRCMxInqQ64k= +github.com/jaypipes/ghw v0.12.0 h1:xU2/MDJfWmBhJnujHY9qwXQLs3DBsf0/Xa9vECY0Tho= +github.com/jaypipes/ghw v0.12.0/go.mod h1:jeJGbkRB2lL3/gxYzNYzEDETV1ZJ56OKr+CSeSEym+g= github.com/jaypipes/pcidb v1.0.0 h1:vtZIfkiCUE42oYbJS0TAq9XSfSmcsgo9IdxSm9qzYU8= github.com/jaypipes/pcidb v1.0.0/go.mod h1:TnYUvqhPBzCKnH34KrIX22kAeEbDCSRJ9cqLRCuNDfk= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -188,36 +195,31 @@ github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8 github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/kardianos/service v1.2.1 h1:AYndMsehS+ywIS6RB9KOlcXzteWUzxgMgBymJD7+BYk= -github.com/kardianos/service v1.2.1/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM= +github.com/kardianos/service v1.2.2 h1:ZvePhAHfvo0A7Mftk/tEzqEZ7Q4lgnR8sGz4xu1YX60= +github.com/kardianos/service v1.2.2/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.15.6 h1:6D9PcO8QWu0JyaQ2zUMmu16T1T+zjjEpP91guRsvDfY= -github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= +github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lufia/plan9stats v0.0.0-20220517141722-cf486979b281 h1:aczX6NMOtt6L4YT0fQvKkDK6LZEtdOso9sUH89V1+P0= github.com/lufia/plan9stats v0.0.0-20220517141722-cf486979b281/go.mod h1:lc+czkgO/8F7puNki5jk8QyujbfK1LOT7Wl0ON2hxyk= -github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= -github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 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/nats-io/jwt/v2 v2.2.1-0.20220330180145-442af02fd36a h1:lem6QCvxR0Y28gth9P+wV2K/zYUUAkJ+55U8cpS0p5I= -github.com/nats-io/nats-server/v2 v2.8.4 h1:0jQzze1T9mECg8YZEl8+WYUXb9JKluJfCBriPUtluB4= -github.com/nats-io/nats-server/v2 v2.8.4/go.mod h1:8zZa+Al3WsESfmgSs98Fi06dRWLH5Bnq90m5bKD/eT4= -github.com/nats-io/nats.go v1.16.0 h1:zvLE7fGBQYW6MWaFaRdsgm9qT39PJDQoju+DS8KsO1g= -github.com/nats-io/nats.go v1.16.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= -github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8= -github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4= +github.com/nats-io/nats.go v1.31.0 h1:/WFBHEc/dOKBF6qf1TZhrdEfTmOZ5JzdJ+Y3m6Y/p7E= +github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8= +github.com/nats-io/nkeys v0.4.6 h1:IzVe95ru2CT6ta874rt9saQRkWfe2nFj1NtvYSLqMzY= +github.com/nats-io/nkeys v0.4.6/go.mod h1:4DxZNzenSVd1cYQoAa8948QY3QDjrHfcfVADymtkpts= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ= @@ -228,23 +230,22 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= -github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= -github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU= -github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= 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/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.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= +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.19.1 h1:IMcFlWY3PagAcc274tJAag84+dh4ihusPxhu4jaHMwY= github.com/rickb777/date v1.19.1/go.mod h1:NxzFOW9ZWNeOWWE2kUXLDN59GSuGMsu3E4YVVk+GcVU= @@ -253,72 +254,82 @@ github.com/rickb777/plural v1.4.1 h1:5MMLcbIaapLFmvDGRT5iPk8877hpTPt8Y9cdSKRw9sU github.com/rickb777/plural v1.4.1/go.mod h1:kdmXUpmKBJTS0FtG/TFumd//VBWsNTD7zOw7x4umxNw= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= -github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ= +github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/scjalliance/comshim v0.0.0-20190308082608-cf06d2532c4e h1:+/AzLkOdIXEPrAQtwAeWOBnPQ0BnYlBW0aCZmSb47u4= github.com/scjalliance/comshim v0.0.0-20190308082608-cf06d2532c4e/go.mod h1:9Tc1SKnfACJb9N7cw2eyuI6xzy845G7uZONBsi5uPEA= -github.com/shirou/gopsutil/v3 v3.22.6 h1:FnHOFOh+cYAM0C30P+zysPISzlknLC5Z1G4EAElznfQ= -github.com/shirou/gopsutil/v3 v3.22.6/go.mod h1:EdIubSnZhbAvBS1yJ7Xi+AShB/hxwLHOMz4MCYz7yMs= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= -github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= -github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= -github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/shirou/gopsutil/v3 v3.23.10 h1:/N42opWlYzegYaVkWejXWJpbzKv2JDy3mrgGzKsh9hM= +github.com/shirou/gopsutil/v3 v3.23.10/go.mod h1:JIE26kpucQi+innVlAUnIEOSBhBUkirr5b44yr55+WE= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= +github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= +github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= -github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= +github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= +github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.5 h1:s5PTfem8p8EbKQOctVV53k6jCJt3UX4IEJzwh+C324Q= -github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/subosito/gotenv v1.4.0 h1:yAzM1+SmVcz5R4tXGsNMu1jUl2aOJXoiWUCEwwnGrvs= -github.com/subosito/gotenv v1.4.0/go.mod h1:mZd6rFysKEcUhUHXJk0C/08wAgyDBFuwEYL7vWWGaGo= -github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= -github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= -github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= -github.com/tklauser/numcpus v0.5.0 h1:ooe7gN0fg6myJ0EKoTAf5hebTZrH52px3New/D9iJ+A= -github.com/tklauser/numcpus v0.5.0/go.mod h1:OGzpTxpcIMNGYQdit2BYL1pvk/dSOaJWjKoflh+RQjo= -github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= -github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= -github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= -github.com/wh1te909/go-win64api v0.0.0-20210906074314-ab23795a6ae5 h1:8tp/+fGR+qjDQ00vm0ZorHzskquo76MY9/ChmFFunEA= -github.com/wh1te909/go-win64api v0.0.0-20210906074314-ab23795a6ae5/go.mod h1:qypF+Tf23flzLX5IXuodDb1314BrDrsbwK/OhTh6HBM= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/wh1te909/go-win64api v0.0.0-20230802051600-21b24f62e846 h1:w/2L2xArf30zPrE/8IsqbKrU1FecRtR68Kbw/jj6ep4= +github.com/wh1te909/go-win64api v0.0.0-20230802051600-21b24f62e846/go.mod h1:qypF+Tf23flzLX5IXuodDb1314BrDrsbwK/OhTh6HBM= github.com/wh1te909/trmm-shared v0.0.0-20220227075846-f9f757361139 h1:PfOl03o+Y+svWrfXAAu1QWUDePu1yqTq0pf4rpnN8eA= github.com/wh1te909/trmm-shared v0.0.0-20220227075846-f9f757361139/go.mod h1:ILUz1utl5KgwrxmNHv0RpgMtKeh8gPAABvK2MiXBqv8= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= -github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -329,6 +340,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -352,6 +365,9 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -388,9 +404,12 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220706163947-c90051bbdb60 h1:8NSylCMxLW4JvserAndSgFL7aPli6A68yf0bYFTcWCM= -golang.org/x/net v0.0.0-20220706163947-c90051bbdb60/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -411,8 +430,10 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -453,7 +474,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-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-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-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -463,15 +483,22 @@ golang.org/x/sys v0.0.0-20210601080250-7ecdf8ef093b/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211107104306-e0b2ad06fe42/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -479,13 +506,17 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220411224347-583f2d630306 h1:+gHMid33q6pen7kv9xvT+JRinntgeXO2AeZVd0AWD3w= -golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -533,6 +564,9 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -625,15 +659,14 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI= -gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2 h1:MZF6J7CV6s/h0HBkfqebrYfKCVEo5iN+wzE4QhV3Evo= gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2/go.mod h1:s1Sn2yZos05Qfs7NKt867Xe18emOmtsO3eAKbDaon0o= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= diff --git a/main.go b/main.go index 21f4d6e..382fd5c 100644 --- a/main.go +++ b/main.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. @@ -25,7 +25,7 @@ import ( ) var ( - version = "2.3.0" + version = "2.6.1" log = logrus.New() logFile *os.File ) @@ -51,11 +51,10 @@ func main() { meshDir := flag.String("meshdir", "", "Path to custom meshcentral dir") meshNodeID := flag.String("meshnodeid", "", "Mesh Node ID") cert := flag.String("cert", "", "Path to domain CA .pem") - updateurl := flag.String("updateurl", "", "Download link to updater") - inno := flag.String("inno", "", "Inno setup file") - updatever := flag.String("updatever", "", "Update version") silent := flag.Bool("silent", false, "Do not popup any message boxes during installation") proxy := flag.String("proxy", "", "Use a http proxy") + insecure := flag.Bool("insecure", false, "Insecure for testing only") + natsport := flag.String("natsport", "", "nats standard port") flag.Parse() if *ver { @@ -122,17 +121,13 @@ func main() { a.RunMigrations() case "recovermesh": a.RecoverMesh() + case "macventurafix": + a.FixVenturaMesh() case "taskrunner": if len(os.Args) < 5 || *taskPK == 0 { return } a.RunTask(*taskPK) - case "update": - if *updateurl == "" || *inno == "" || *updatever == "" { - updateUsage() - return - } - a.AgentUpdate(*updateurl, *inno, *updatever) case "install": if runtime.GOOS != "windows" { u, err := user.Current() @@ -145,27 +140,28 @@ func main() { } if *api == "" || *clientID == 0 || *siteID == 0 || *token == "" { - installUsage() return } a.Install(&agent.Installer{ - RMM: *api, - ClientID: *clientID, - SiteID: *siteID, - Description: *desc, - AgentType: *atype, - Power: *power, - RDP: *rdp, - Ping: *ping, - Token: *token, - LocalMesh: *localMesh, - Cert: *cert, - Proxy: *proxy, - Timeout: *timeout, - Silent: *silent, - NoMesh: *noMesh, - MeshDir: *meshDir, - MeshNodeID: *meshNodeID, + RMM: *api, + ClientID: *clientID, + SiteID: *siteID, + Description: *desc, + AgentType: *atype, + Power: *power, + RDP: *rdp, + Ping: *ping, + Token: *token, + LocalMesh: *localMesh, + Cert: *cert, + Proxy: *proxy, + Timeout: *timeout, + Silent: *silent, + NoMesh: *noMesh, + MeshDir: *meshDir, + MeshNodeID: *meshNodeID, + Insecure: *insecure, + NatsStandardPort: *natsport, }) default: agent.ShowStatus(version) @@ -185,20 +181,9 @@ func setupLogging(level, to *string) { switch runtime.GOOS { case "windows": 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) } log.SetOutput(logFile) } } - -func installUsage() { - exe, _ := os.Executable() - u := fmt.Sprintf(`Usage: %s -m install -api -client-id X -site-id X -auth `, exe) - fmt.Println(u) -} - -func updateUsage() { - u := `Usage: tacticalrmm.exe -m update -updateurl https://example.com/tacticalagent-vX.X.X.exe -inno tacticalagent-vX.X.X.exe -updatever 1.1.1` - fmt.Println(u) -} diff --git a/shared/types.go b/shared/types.go index b2cb258..d7a6f24 100644 --- a/shared/types.go +++ b/shared/types.go @@ -1,5 +1,5 @@ /* -Copyright 2022 AmidaWare LLC. +Copyright 2023 AmidaWare Inc. Licensed under the Tactical RMM License Version 1.0 (the “License”). You may only use the Licensed Software in accordance with the License. @@ -33,18 +33,22 @@ type ProcessMsg struct { } type AgentConfig struct { - BaseURL string - AgentID string - APIURL string - Token string - AgentPK string - PK int - Cert string - Proxy string - CustomMeshDir string - NatsProxyPath string - NatsProxyPort string - NatsStandardPort string + BaseURL string + AgentID string + APIURL string + Token string + AgentPK string + PK int + Cert string + Proxy string + CustomMeshDir string + WinTmpDir string + WinRunAsUserTmpDir string + NatsProxyPath string + NatsProxyPort string + NatsStandardPort string + NatsPingInterval int + Insecure string } type RunScriptResp struct { @@ -141,9 +145,10 @@ type AssignedTask struct { } type Script struct { - Shell string `json:"shell"` - Code string `json:"code"` - RunAsUser bool `json:"run_as_user"` + Shell string `json:"shell"` + Code string `json:"code"` + RunAsUser bool `json:"run_as_user"` + EnvVars []string `json:"env_vars"` } type CheckInfo struct { @@ -161,6 +166,7 @@ type Check struct { Disk string `json:"disk"` IP string `json:"ip"` ScriptArgs []string `json:"script_args"` + EnvVars []string `json:"env_vars"` Timeout int `json:"timeout"` ServiceName string `json:"svc_name"` PassStartPending bool `json:"pass_if_start_pending"` @@ -190,6 +196,7 @@ type TaskAction struct { Args []string `json:"script_args"` Timeout int `json:"timeout"` RunAsUser bool `json:"run_as_user"` + EnvVars []string `json:"env_vars"` } type AutomatedTask struct { diff --git a/versioninfo.json b/versioninfo.json index b7064a2..08967a6 100644 --- a/versioninfo.json +++ b/versioninfo.json @@ -2,14 +2,14 @@ "FixedFileInfo": { "FileVersion": { "Major": 2, - "Minor": 3, - "Patch": 0, + "Minor": 6, + "Patch": 1, "Build": 0 }, "ProductVersion": { "Major": 2, - "Minor": 3, - "Patch": 0, + "Minor": 6, + "Patch": 1, "Build": 0 }, "FileFlagsMask": "3f", @@ -20,16 +20,16 @@ }, "StringFileInfo": { "Comments": "", - "CompanyName": "AmidaWare LLC", + "CompanyName": "AmidaWare Inc", "FileDescription": "Tactical RMM Agent", - "FileVersion": "v2.3.0.0", + "FileVersion": "v2.6.1.0", "InternalName": "tacticalrmm.exe", - "LegalCopyright": "Copyright (c) 2022 AmidaWare LLC", + "LegalCopyright": "Copyright (c) 2023 AmidaWare Inc", "LegalTrademarks": "", "OriginalFilename": "tacticalrmm.exe", "PrivateBuild": "", "ProductName": "Tactical RMM Agent", - "ProductVersion": "v2.3.0.0", + "ProductVersion": "v2.6.1.0", "SpecialBuild": "" }, "VarFileInfo": {