Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
697e112536 | ||
|
|
687e890a10 | ||
|
|
c64fc857c9 | ||
|
|
5fef58f764 | ||
|
|
ecad4d02d9 | ||
|
|
b09eaf84de | ||
|
|
12f1b6dc02 | ||
|
|
38bb9e4edd | ||
|
|
c91cfcff43 | ||
|
|
3e1546e08b | ||
|
|
51f6e93a35 | ||
|
|
57fb99996c | ||
|
|
964c31e119 | ||
|
|
eca05c3e76 | ||
|
|
98cae02ec6 | ||
|
|
996631e108 | ||
|
|
47b482419a | ||
|
|
67abc85168 | ||
|
|
a29709c599 | ||
|
|
e40dcf6079 | ||
|
|
dc10c33be8 | ||
|
|
d3eb6e041b | ||
|
|
055f11b0e3 | ||
|
|
2afdfd7ab8 | ||
|
|
87e1b29ef6 | ||
|
|
6ba3272dc0 |
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@@ -3,14 +3,14 @@
|
|||||||
"[go]": {
|
"[go]": {
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.organizeImports": false,
|
"source.organizeImports": "always"
|
||||||
},
|
},
|
||||||
"editor.snippetSuggestions": "none",
|
"editor.snippetSuggestions": "none",
|
||||||
},
|
},
|
||||||
"[go.mod]": {
|
"[go.mod]": {
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.organizeImports": true,
|
"source.organizeImports": "explicit"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"gopls": {
|
"gopls": {
|
||||||
|
|||||||
177
agent/agent.go
177
agent/agent.go
@@ -15,6 +15,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
@@ -58,6 +59,12 @@ type Agent struct {
|
|||||||
MeshSystemEXE string
|
MeshSystemEXE string
|
||||||
MeshSVC string
|
MeshSVC string
|
||||||
PyBin string
|
PyBin string
|
||||||
|
PyVer string
|
||||||
|
PyBaseDir string
|
||||||
|
PyDir string
|
||||||
|
NuBin string
|
||||||
|
DenoBin string
|
||||||
|
AgentHeader string
|
||||||
Headers map[string]string
|
Headers map[string]string
|
||||||
Logger *logrus.Logger
|
Logger *logrus.Logger
|
||||||
Version string
|
Version string
|
||||||
@@ -86,6 +93,8 @@ const (
|
|||||||
nixAgentDir = "/opt/tacticalagent"
|
nixAgentDir = "/opt/tacticalagent"
|
||||||
nixMeshDir = "/opt/tacticalmesh"
|
nixMeshDir = "/opt/tacticalmesh"
|
||||||
nixAgentBin = nixAgentDir + "/tacticalagent"
|
nixAgentBin = nixAgentDir + "/tacticalagent"
|
||||||
|
nixAgentBinDir = nixAgentDir + "/bin"
|
||||||
|
nixAgentEtcDir = nixAgentDir + "/etc"
|
||||||
nixMeshAgentBin = nixMeshDir + "/meshagent"
|
nixMeshAgentBin = nixMeshDir + "/meshagent"
|
||||||
macPlistPath = "/Library/LaunchDaemons/tacticalagent.plist"
|
macPlistPath = "/Library/LaunchDaemons/tacticalagent.plist"
|
||||||
macPlistName = "tacticalagent"
|
macPlistName = "tacticalagent"
|
||||||
@@ -111,16 +120,45 @@ func New(logger *logrus.Logger, version string) *Agent {
|
|||||||
hostname = info.Hostname
|
hostname = info.Hostname
|
||||||
}
|
}
|
||||||
|
|
||||||
var pybin string
|
pyver := "n/a"
|
||||||
switch runtime.GOARCH {
|
pybin := "n/a"
|
||||||
case "amd64":
|
pyBaseDir := "n/a"
|
||||||
pybin = filepath.Join(pd, "py38-x64", "python.exe")
|
pydir := "n/a"
|
||||||
case "386":
|
|
||||||
pybin = filepath.Join(pd, "py38-x32", "python.exe")
|
if runtime.GOOS == "windows" {
|
||||||
|
major := info.OS.Major
|
||||||
|
minor := info.OS.Minor
|
||||||
|
if major > 6 || (major == 6 && minor >= 3) {
|
||||||
|
// Windows 8.1 or higher
|
||||||
|
pyver = "3.11.9"
|
||||||
|
} else {
|
||||||
|
pyver = "3.8.7"
|
||||||
|
}
|
||||||
|
|
||||||
|
pydir = "py" + pyver + "_" + runtime.GOARCH
|
||||||
|
pyBaseDir = filepath.Join(pd, "python")
|
||||||
|
pybin = filepath.Join(pyBaseDir, pydir, "python.exe")
|
||||||
|
}
|
||||||
|
|
||||||
|
var nuBin string
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "windows":
|
||||||
|
nuBin = filepath.Join(pd, "bin", "nu.exe")
|
||||||
|
default:
|
||||||
|
nuBin = filepath.Join(nixAgentBinDir, "nu")
|
||||||
|
}
|
||||||
|
|
||||||
|
var denoBin string
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "windows":
|
||||||
|
denoBin = filepath.Join(pd, "bin", "deno.exe")
|
||||||
|
default:
|
||||||
|
denoBin = filepath.Join(nixAgentBinDir, "deno")
|
||||||
}
|
}
|
||||||
|
|
||||||
ac := NewAgentConfig()
|
ac := NewAgentConfig()
|
||||||
|
|
||||||
|
agentHeader := fmt.Sprintf("trmm/%s/%s/%s", version, runtime.GOOS, runtime.GOARCH)
|
||||||
headers := make(map[string]string)
|
headers := make(map[string]string)
|
||||||
if len(ac.Token) > 0 {
|
if len(ac.Token) > 0 {
|
||||||
headers["Content-Type"] = "application/json"
|
headers["Content-Type"] = "application/json"
|
||||||
@@ -232,7 +270,13 @@ func New(logger *logrus.Logger, version string) *Agent {
|
|||||||
MeshSystemEXE: MeshSysExe,
|
MeshSystemEXE: MeshSysExe,
|
||||||
MeshSVC: meshSvcName,
|
MeshSVC: meshSvcName,
|
||||||
PyBin: pybin,
|
PyBin: pybin,
|
||||||
|
PyVer: pyver,
|
||||||
|
PyBaseDir: pyBaseDir,
|
||||||
|
PyDir: pydir,
|
||||||
|
NuBin: nuBin,
|
||||||
|
DenoBin: denoBin,
|
||||||
Headers: headers,
|
Headers: headers,
|
||||||
|
AgentHeader: agentHeader,
|
||||||
Logger: logger,
|
Logger: logger,
|
||||||
Version: version,
|
Version: version,
|
||||||
Debug: logger.IsLevelEnabled(logrus.DebugLevel),
|
Debug: logger.IsLevelEnabled(logrus.DebugLevel),
|
||||||
@@ -603,3 +647,124 @@ func createWinTempDir() error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Agent) RunTask(id int) error {
|
||||||
|
data := rmm.AutomatedTask{}
|
||||||
|
url := fmt.Sprintf("/api/v3/%d/%s/taskrunner/", id, a.AgentID)
|
||||||
|
r1, gerr := a.rClient.R().Get(url)
|
||||||
|
if gerr != nil {
|
||||||
|
a.Logger.Debugln(gerr)
|
||||||
|
return gerr
|
||||||
|
}
|
||||||
|
|
||||||
|
if r1.IsError() {
|
||||||
|
a.Logger.Debugln("Run Task:", r1.String())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(r1.Body(), &data); err != nil {
|
||||||
|
a.Logger.Debugln(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
type TaskResult struct {
|
||||||
|
Stdout string `json:"stdout"`
|
||||||
|
Stderr string `json:"stderr"`
|
||||||
|
RetCode int `json:"retcode"`
|
||||||
|
ExecTime float64 `json:"execution_time"`
|
||||||
|
}
|
||||||
|
|
||||||
|
payload := TaskResult{}
|
||||||
|
|
||||||
|
// loop through all task actions
|
||||||
|
for _, action := range data.TaskActions {
|
||||||
|
|
||||||
|
action_start := time.Now()
|
||||||
|
if action.ActionType == "script" {
|
||||||
|
stdout, stderr, retcode, err := a.RunScript(action.Code, action.Shell, action.Args, action.Timeout, action.RunAsUser, action.EnvVars, action.NushellEnableConfig, action.DenoDefaultPermissions)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Debugln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// add text to stdout showing which script ran if more than 1 script
|
||||||
|
action_exec_time := time.Since(action_start).Seconds()
|
||||||
|
|
||||||
|
if len(data.TaskActions) > 1 {
|
||||||
|
payload.Stdout += fmt.Sprintf("\n------------\nRunning Script: %s. Execution Time: %f\n------------\n\n", action.ScriptName, action_exec_time)
|
||||||
|
}
|
||||||
|
|
||||||
|
// save results
|
||||||
|
payload.Stdout += stdout
|
||||||
|
payload.Stderr += stderr
|
||||||
|
payload.RetCode = retcode
|
||||||
|
|
||||||
|
if !data.ContinueOnError && stderr != "" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if action.ActionType == "cmd" {
|
||||||
|
var stdout, stderr string
|
||||||
|
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "windows":
|
||||||
|
out, err := CMDShell(action.Shell, []string{}, action.Command, action.Timeout, false, action.RunAsUser)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Debugln(err)
|
||||||
|
}
|
||||||
|
stdout = out[0]
|
||||||
|
stderr = out[1]
|
||||||
|
|
||||||
|
if stderr == "" {
|
||||||
|
payload.RetCode = 0
|
||||||
|
} else {
|
||||||
|
payload.RetCode = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
opts := a.NewCMDOpts()
|
||||||
|
opts.Shell = action.Shell
|
||||||
|
opts.Command = action.Command
|
||||||
|
opts.Timeout = time.Duration(action.Timeout)
|
||||||
|
out := a.CmdV2(opts)
|
||||||
|
|
||||||
|
if out.Status.Error != nil {
|
||||||
|
a.Logger.Debugln("RunTask() cmd: ", out.Status.Error.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
stdout = out.Stdout
|
||||||
|
stderr = out.Stderr
|
||||||
|
payload.RetCode = out.Status.Exit
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(data.TaskActions) > 1 {
|
||||||
|
action_exec_time := time.Since(action_start).Seconds()
|
||||||
|
|
||||||
|
// add text to stdout showing which script ran
|
||||||
|
payload.Stdout += fmt.Sprintf("\n------------\nRunning Command: %s. Execution Time: %f\n------------\n\n", action.Command, action_exec_time)
|
||||||
|
}
|
||||||
|
// save results
|
||||||
|
payload.Stdout += stdout
|
||||||
|
payload.Stderr += stderr
|
||||||
|
|
||||||
|
if payload.RetCode != 0 {
|
||||||
|
if !data.ContinueOnError {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
a.Logger.Debugln("Invalid Action", action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
payload.ExecTime = time.Since(start).Seconds()
|
||||||
|
|
||||||
|
_, perr := a.rClient.R().SetBody(payload).Patch(url)
|
||||||
|
if perr != nil {
|
||||||
|
a.Logger.Debugln(perr)
|
||||||
|
return perr
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ import (
|
|||||||
psHost "github.com/shirou/gopsutil/v3/host"
|
psHost "github.com/shirou/gopsutil/v3/host"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
trmm "github.com/wh1te909/trmm-shared"
|
trmm "github.com/wh1te909/trmm-shared"
|
||||||
|
"golang.org/x/text/cases"
|
||||||
|
"golang.org/x/text/language"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ShowStatus(version string) {
|
func ShowStatus(version string) {
|
||||||
@@ -130,7 +132,8 @@ func (a *Agent) osString() string {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "error getting host info"
|
return "error getting host info"
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s %s %s %s", strings.Title(h.Platform), h.PlatformVersion, h.KernelArch, h.KernelVersion)
|
plat := cases.Title(language.AmericanEnglish).String(h.Platform)
|
||||||
|
return fmt.Sprintf("%s %s %s %s", plat, h.PlatformVersion, h.KernelArch, h.KernelVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAgentConfig() *rmm.AgentConfig {
|
func NewAgentConfig() *rmm.AgentConfig {
|
||||||
@@ -166,11 +169,11 @@ func NewAgentConfig() *rmm.AgentConfig {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) RunScript(code string, shell string, args []string, timeout int, runasuser bool, envVars []string) (stdout, stderr string, exitcode int, e error) {
|
func (a *Agent) RunScript(code string, shell string, args []string, timeout int, runasuser bool, envVars []string, nushellEnableConfig bool, denoDefaultPermissions string) (stdout, stderr string, exitcode int, e error) {
|
||||||
code = removeWinNewLines(code)
|
code = removeWinNewLines(code)
|
||||||
content := []byte(code)
|
content := []byte(code)
|
||||||
|
|
||||||
f, err := createNixTmpFile()
|
f, err := createNixTmpFile(shell)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.Logger.Errorln("RunScript createNixTmpFile()", err)
|
a.Logger.Errorln("RunScript createNixTmpFile()", err)
|
||||||
return "", err.Error(), 85, err
|
return "", err.Error(), 85, err
|
||||||
@@ -194,10 +197,75 @@ func (a *Agent) RunScript(code string, shell string, args []string, timeout int,
|
|||||||
|
|
||||||
opts := a.NewCMDOpts()
|
opts := a.NewCMDOpts()
|
||||||
opts.IsScript = true
|
opts.IsScript = true
|
||||||
|
switch shell {
|
||||||
|
case "nushell":
|
||||||
|
var nushellArgs []string
|
||||||
|
if nushellEnableConfig {
|
||||||
|
nushellArgs = []string{
|
||||||
|
"--config",
|
||||||
|
filepath.Join(nixAgentEtcDir, "nushell", "config.nu"),
|
||||||
|
"--env-config",
|
||||||
|
filepath.Join(nixAgentEtcDir, "nushell", "env.nu"),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nushellArgs = []string{"--no-config-file"}
|
||||||
|
}
|
||||||
|
opts.Shell = a.NuBin
|
||||||
|
opts.Args = nushellArgs
|
||||||
|
opts.Args = append(opts.Args, f.Name())
|
||||||
|
opts.Args = append(opts.Args, args...)
|
||||||
|
if !trmm.FileExists(a.NuBin) {
|
||||||
|
a.Logger.Errorln("RunScript(): Executable does not exist. Install Nu and try again:", a.NuBin)
|
||||||
|
err := errors.New("File Not Found: " + a.NuBin)
|
||||||
|
return "", err.Error(), 85, err
|
||||||
|
}
|
||||||
|
|
||||||
|
case "deno":
|
||||||
|
opts.Shell = a.DenoBin
|
||||||
|
opts.Args = []string{
|
||||||
|
"run",
|
||||||
|
"--no-prompt",
|
||||||
|
}
|
||||||
|
if !trmm.FileExists(a.DenoBin) {
|
||||||
|
a.Logger.Errorln("RunScript(): Executable does not exist. Install deno and try again:", a.DenoBin)
|
||||||
|
err := errors.New("File Not Found: " + a.DenoBin)
|
||||||
|
return "", err.Error(), 85, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search the environment variables for DENO_PERMISSIONS and use that to set permissions for the script.
|
||||||
|
// https://docs.deno.com/runtime/manual/basics/permissions#permissions-list
|
||||||
|
// DENO_PERMISSIONS is not an official environment variable.
|
||||||
|
// https://docs.deno.com/runtime/manual/basics/env_variables
|
||||||
|
// DENO_DEFAULT_PERMISSIONS is used if not found in the environment variables.
|
||||||
|
found := false
|
||||||
|
for i, v := range envVars {
|
||||||
|
if strings.HasPrefix(v, "DENO_PERMISSIONS=") {
|
||||||
|
permissions := strings.Split(v, "=")[1]
|
||||||
|
opts.Args = append(opts.Args, strings.Split(permissions, " ")...)
|
||||||
|
// Remove the DENO_PERMISSIONS variable from the environment variables slice.
|
||||||
|
// It's possible more variables may exist with the same prefix.
|
||||||
|
envVars = append(envVars[:i], envVars[i+1:]...)
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found && denoDefaultPermissions != "" {
|
||||||
|
opts.Args = append(opts.Args, strings.Split(denoDefaultPermissions, " ")...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can't append a variadic slice after a string arg.
|
||||||
|
// https://pkg.go.dev/builtin#append
|
||||||
|
opts.Args = append(opts.Args, f.Name())
|
||||||
|
opts.Args = append(opts.Args, args...)
|
||||||
|
|
||||||
|
default:
|
||||||
opts.Shell = f.Name()
|
opts.Shell = f.Name()
|
||||||
opts.Args = args
|
opts.Args = args
|
||||||
|
}
|
||||||
|
|
||||||
opts.EnvVars = envVars
|
opts.EnvVars = envVars
|
||||||
opts.Timeout = time.Duration(timeout)
|
opts.Timeout = time.Duration(timeout)
|
||||||
|
a.Logger.Debugln("RunScript():", opts.Shell, opts.Args)
|
||||||
out := a.CmdV2(opts)
|
out := a.CmdV2(opts)
|
||||||
retError := ""
|
retError := ""
|
||||||
if out.Status.Error != nil {
|
if out.Status.Error != nil {
|
||||||
@@ -510,11 +578,329 @@ func (a *Agent) GetWMIInfo() map[string]interface{} {
|
|||||||
return wmiInfo
|
return wmiInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
// windows only below TODO add into stub file
|
// InstallNushell will download nushell from GitHub and install (copy) it to nixAgentBinDir
|
||||||
|
func (a *Agent) InstallNushell(force bool) {
|
||||||
|
sleepDelay := randRange(1, 10)
|
||||||
|
a.Logger.Debugf("InstallNushell() sleeping for %v seconds", sleepDelay)
|
||||||
|
time.Sleep(time.Duration(sleepDelay) * time.Second)
|
||||||
|
|
||||||
|
conf := a.GetAgentCheckInConfig(a.GetCheckInConfFromAPI())
|
||||||
|
if !conf.InstallNushell {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if trmm.FileExists(a.NuBin) {
|
||||||
|
if force {
|
||||||
|
a.Logger.Debugln(a.NuBin, "InstallNushell(): Forced install. Removing nu binary.")
|
||||||
|
err := os.Remove(a.NuBin)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Error removing nu binary:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !trmm.FileExists(nixAgentBinDir) {
|
||||||
|
err := os.MkdirAll(nixAgentBinDir, 0755)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Error creating nixAgentBinDir:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.NushellEnableConfig {
|
||||||
|
// Create 0-byte config files for Nushell
|
||||||
|
nushellPath := filepath.Join(nixAgentEtcDir, "nushell")
|
||||||
|
nushellConfig := filepath.Join(nushellPath, "config.nu")
|
||||||
|
nushellEnv := filepath.Join(nushellPath, "env.nu")
|
||||||
|
if !trmm.FileExists(nushellPath) {
|
||||||
|
err := os.MkdirAll(nushellPath, 0755)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Error creating nixAgentEtcDir/nushell:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !trmm.FileExists(nushellConfig) {
|
||||||
|
_, err := os.Create(nushellConfig)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Error creating nushell config.nu:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = os.Chmod(nushellConfig, 0744)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Error changing permissions for nushell config.nu:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !trmm.FileExists(nushellEnv) {
|
||||||
|
_, err := os.Create(nushellEnv)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Error creating nushell env.nu:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = os.Chmod(nushellEnv, 0744)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Error changing permissions for nushell env.nu:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
assetName string
|
||||||
|
url string
|
||||||
|
targzDirName string
|
||||||
|
)
|
||||||
|
|
||||||
|
if conf.InstallNushellUrl != "" {
|
||||||
|
url = conf.InstallNushellUrl
|
||||||
|
url = strings.ReplaceAll(url, "{OS}", runtime.GOOS)
|
||||||
|
url = strings.ReplaceAll(url, "{ARCH}", runtime.GOARCH)
|
||||||
|
url = strings.ReplaceAll(url, "{VERSION}", conf.InstallNushellVersion)
|
||||||
|
} else {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin":
|
||||||
|
switch runtime.GOARCH {
|
||||||
|
case "arm64":
|
||||||
|
// https://github.com/nushell/nushell/releases/download/0.87.0/nu-0.87.0-aarch64-darwin-full.tar.gz
|
||||||
|
assetName = fmt.Sprintf("nu-%s-aarch64-darwin-full.tar.gz", conf.InstallNushellVersion)
|
||||||
|
default:
|
||||||
|
a.Logger.Debugln("InstallNushell(): Unsupported architecture and OS:", runtime.GOARCH, runtime.GOOS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "linux":
|
||||||
|
switch runtime.GOARCH {
|
||||||
|
case "amd64":
|
||||||
|
// https://github.com/nushell/nushell/releases/download/0.87.0/nu-0.87.0-x86_64-linux-musl-full.tar.gz
|
||||||
|
assetName = fmt.Sprintf("nu-%s-x86_64-linux-musl-full.tar.gz", conf.InstallNushellVersion)
|
||||||
|
case "arm64":
|
||||||
|
// https://github.com/nushell/nushell/releases/download/0.87.0/nu-0.87.0-aarch64-linux-gnu-full.tar.gz
|
||||||
|
assetName = fmt.Sprintf("nu-%s-aarch64-linux-gnu-full.tar.gz", conf.InstallNushellVersion)
|
||||||
|
default:
|
||||||
|
a.Logger.Debugln("InstallNushell(): Unsupported architecture and OS:", runtime.GOARCH, runtime.GOOS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
a.Logger.Debugln("InstallNushell(): Unsupported OS:", runtime.GOOS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
url = fmt.Sprintf("https://github.com/nushell/nushell/releases/download/%s/%s", conf.InstallNushellVersion, assetName)
|
||||||
|
}
|
||||||
|
a.Logger.Debugln("InstallNushell(): Nu download url:", url)
|
||||||
|
|
||||||
|
tmpDir, err := os.MkdirTemp("", "nutemp")
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Error creating nushell temp directory:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func(path string) {
|
||||||
|
err := os.RemoveAll(path)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Error removing nushell temp directory:", err)
|
||||||
|
}
|
||||||
|
}(tmpDir)
|
||||||
|
|
||||||
|
tmpAssetName := filepath.Join(tmpDir, assetName)
|
||||||
|
a.Logger.Debugln("InstallNushell(): tmpAssetName:", tmpAssetName)
|
||||||
|
|
||||||
|
rClient := resty.New()
|
||||||
|
rClient.SetTimeout(20 * time.Minute)
|
||||||
|
rClient.SetRetryCount(10)
|
||||||
|
rClient.SetRetryWaitTime(1 * time.Minute)
|
||||||
|
rClient.SetRetryMaxWaitTime(15 * time.Minute)
|
||||||
|
if len(a.Proxy) > 0 {
|
||||||
|
rClient.SetProxy(a.Proxy)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := rClient.R().SetOutput(tmpAssetName).Get(url)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Unable to download nu:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if r.IsError() {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Unable to download nu. Status code:", r.StatusCode())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.InstallNushellUrl != "" {
|
||||||
|
// InstallNushellUrl is not compressed.
|
||||||
|
err = copyFile(filepath.Join(tmpDir, tmpAssetName), a.NuBin)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Failed to copy nu file to install dir:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// GitHub asset is tar.gz compressed.
|
||||||
|
targzDirName, err = a.ExtractTarGz(tmpAssetName, tmpDir)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Failed to extract downloaded tar.gz file:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = copyFile(filepath.Join(tmpDir, targzDirName, "nu"), a.NuBin)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Failed to copy nu file to install dir:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.Chmod(a.NuBin, 0755)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Failed to chmod nu binary:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// InstallDeno will download deno from GitHub and install (copy) it to nixAgentBinDir
|
||||||
|
func (a *Agent) InstallDeno(force bool) {
|
||||||
|
sleepDelay := randRange(1, 10)
|
||||||
|
a.Logger.Debugf("InstallDeno() sleeping for %v seconds", sleepDelay)
|
||||||
|
time.Sleep(time.Duration(sleepDelay) * time.Second)
|
||||||
|
|
||||||
|
conf := a.GetAgentCheckInConfig(a.GetCheckInConfFromAPI())
|
||||||
|
if !conf.InstallDeno {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if trmm.FileExists(a.DenoBin) {
|
||||||
|
if force {
|
||||||
|
a.Logger.Debugln(a.NuBin, "InstallDeno(): Forced install. Removing deno binary.")
|
||||||
|
err := os.Remove(a.DenoBin)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallDeno(): Error removing deno binary:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !trmm.FileExists(nixAgentBinDir) {
|
||||||
|
err := os.MkdirAll(nixAgentBinDir, 0755)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallDeno(): Error creating nixAgentBinDir:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
assetName string
|
||||||
|
url string
|
||||||
|
)
|
||||||
|
|
||||||
|
if conf.InstallDenoUrl != "" {
|
||||||
|
url = conf.InstallDenoUrl
|
||||||
|
url = strings.ReplaceAll(url, "{OS}", runtime.GOOS)
|
||||||
|
url = strings.ReplaceAll(url, "{ARCH}", runtime.GOARCH)
|
||||||
|
url = strings.ReplaceAll(url, "{VERSION}", conf.InstallDenoVersion)
|
||||||
|
} else {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin":
|
||||||
|
switch runtime.GOARCH {
|
||||||
|
case "arm64":
|
||||||
|
// https://github.com/denoland/deno/releases/download/v1.38.2/deno-aarch64-apple-darwin.zip
|
||||||
|
assetName = "deno-aarch64-apple-darwin.zip"
|
||||||
|
case "amd64":
|
||||||
|
// https://github.com/denoland/deno/releases/download/v1.38.2/deno-x86_64-apple-darwin.zip
|
||||||
|
assetName = "deno-x86_64-apple-darwin.zip"
|
||||||
|
default:
|
||||||
|
a.Logger.Debugln("InstallDeno(): Unsupported architecture and OS:", runtime.GOARCH, runtime.GOOS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "linux":
|
||||||
|
switch runtime.GOARCH {
|
||||||
|
case "amd64":
|
||||||
|
// https://github.com/denoland/deno/releases/download/v1.38.2/deno-x86_64-unknown-linux-gnu.zip
|
||||||
|
assetName = "deno-x86_64-unknown-linux-gnu.zip"
|
||||||
|
default:
|
||||||
|
a.Logger.Debugln("InstallDeno(): Unsupported architecture and OS:", runtime.GOARCH, runtime.GOOS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
a.Logger.Debugln("InstallDeno(): Unsupported OS:", runtime.GOOS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
url = fmt.Sprintf("https://github.com/denoland/deno/releases/download/%s/%s", conf.InstallDenoVersion, assetName)
|
||||||
|
}
|
||||||
|
a.Logger.Debugln("InstallDeno(): Deno download url:", url)
|
||||||
|
|
||||||
|
tmpDir, err := os.MkdirTemp("", "denotemp")
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallDeno(): Error creating deno temp directory:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func(path string) {
|
||||||
|
err := os.RemoveAll(path)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallDeno(): Error removing deno temp directory:", err)
|
||||||
|
}
|
||||||
|
}(tmpDir)
|
||||||
|
|
||||||
|
tmpAssetName := filepath.Join(tmpDir, assetName)
|
||||||
|
a.Logger.Debugln("InstallDeno(): tmpAssetName:", tmpAssetName)
|
||||||
|
|
||||||
|
rClient := resty.New()
|
||||||
|
rClient.SetTimeout(20 * time.Minute)
|
||||||
|
rClient.SetRetryCount(10)
|
||||||
|
rClient.SetRetryWaitTime(1 * time.Minute)
|
||||||
|
rClient.SetRetryMaxWaitTime(15 * time.Minute)
|
||||||
|
if len(a.Proxy) > 0 {
|
||||||
|
rClient.SetProxy(a.Proxy)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := rClient.R().SetOutput(tmpAssetName).Get(url)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallDeno(): Unable to download deno:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if r.IsError() {
|
||||||
|
a.Logger.Errorln("InstallDeno(): Unable to download deno. Status code:", r.StatusCode())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.InstallDenoUrl != "" {
|
||||||
|
// InstallDenoUrl is not compressed.
|
||||||
|
err = copyFile(filepath.Join(tmpDir, tmpAssetName), a.DenoBin)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallDeno(): Failed to copy deno file to install dir:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// GitHub asset is zip compressed.
|
||||||
|
err = Unzip(tmpAssetName, tmpDir)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallDeno(): Failed to unzip downloaded zip file:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = copyFile(filepath.Join(tmpDir, "deno"), a.DenoBin)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallDeno(): Failed to copy deno file to install dir:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.Chmod(a.DenoBin, 0755)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallDeno(): Failed to chmod deno binary:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAgentCheckInConfig will get the agent configuration from the server.
|
||||||
|
// The Windows agent stores the configuration in the registry. The UNIX agent does not store the config.
|
||||||
|
// @return AgentCheckInConfig
|
||||||
func (a *Agent) GetAgentCheckInConfig(ret AgentCheckInConfig) AgentCheckInConfig {
|
func (a *Agent) GetAgentCheckInConfig(ret AgentCheckInConfig) AgentCheckInConfig {
|
||||||
|
// TODO: Persist the config to disk.
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// windows only below TODO add into stub file
|
||||||
func (a *Agent) PlatVer() (string, error) { return "", nil }
|
func (a *Agent) PlatVer() (string, error) { return "", nil }
|
||||||
|
|
||||||
func (a *Agent) SendSoftware() {}
|
func (a *Agent) SendSoftware() {}
|
||||||
@@ -555,8 +941,6 @@ func (a *Agent) GetInstalledSoftware() []trmm.WinSoftwareList { return []trmm.Wi
|
|||||||
|
|
||||||
func (a *Agent) ChecksRunning() bool { return false }
|
func (a *Agent) ChecksRunning() bool { return false }
|
||||||
|
|
||||||
func (a *Agent) RunTask(id int) error { return nil }
|
|
||||||
|
|
||||||
func (a *Agent) InstallChoco() {}
|
func (a *Agent) InstallChoco() {}
|
||||||
|
|
||||||
func (a *Agent) InstallWithChoco(name string) (string, error) { return "", nil }
|
func (a *Agent) InstallWithChoco(name string) (string, error) { return "", nil }
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ func NewAgentConfig() *rmm.AgentConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) RunScript(code string, shell string, args []string, timeout int, runasuser bool, envVars []string) (stdout, stderr string, exitcode int, e error) {
|
func (a *Agent) RunScript(code string, shell string, args []string, timeout int, runasuser bool, envVars []string, nushellEnableConfig bool, denoDefaultPermissions string) (stdout, stderr string, exitcode int, e error) {
|
||||||
|
|
||||||
content := []byte(code)
|
content := []byte(code)
|
||||||
|
|
||||||
@@ -118,6 +118,10 @@ func (a *Agent) RunScript(code string, shell string, args []string, timeout int,
|
|||||||
ext = "*.py"
|
ext = "*.py"
|
||||||
case "cmd":
|
case "cmd":
|
||||||
ext = "*.bat"
|
ext = "*.bat"
|
||||||
|
case "nushell":
|
||||||
|
ext = "*.nu"
|
||||||
|
case "deno":
|
||||||
|
ext = "*.ts"
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpDir := a.WinTmpDir
|
tmpDir := a.WinTmpDir
|
||||||
@@ -151,6 +155,56 @@ func (a *Agent) RunScript(code string, shell string, args []string, timeout int,
|
|||||||
cmdArgs = []string{tmpfn.Name()}
|
cmdArgs = []string{tmpfn.Name()}
|
||||||
case "cmd":
|
case "cmd":
|
||||||
exe = tmpfn.Name()
|
exe = tmpfn.Name()
|
||||||
|
case "nushell":
|
||||||
|
exe = a.NuBin
|
||||||
|
var nushellArgs []string
|
||||||
|
if nushellEnableConfig {
|
||||||
|
nushellArgs = []string{
|
||||||
|
"--config",
|
||||||
|
filepath.Join(a.ProgramDir, "etc", "nushell", "config.nu"),
|
||||||
|
"--env-config",
|
||||||
|
filepath.Join(a.ProgramDir, "etc", "nushell", "env.nu"),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nushellArgs = []string{"--no-config-file"}
|
||||||
|
}
|
||||||
|
cmdArgs = append(nushellArgs, tmpfn.Name())
|
||||||
|
if !trmm.FileExists(a.NuBin) {
|
||||||
|
a.Logger.Errorln("RunScript(): Executable does not exist. Install Nu and try again:", a.NuBin)
|
||||||
|
err := errors.New("File Not Found: " + a.NuBin)
|
||||||
|
return "", err.Error(), 85, err
|
||||||
|
}
|
||||||
|
case "deno":
|
||||||
|
exe = a.DenoBin
|
||||||
|
cmdArgs = []string{"run", "--no-prompt"}
|
||||||
|
if !trmm.FileExists(a.DenoBin) {
|
||||||
|
a.Logger.Errorln("RunScript(): Executable does not exist. Install deno and try again:", a.DenoBin)
|
||||||
|
err := errors.New("File Not Found: " + a.DenoBin)
|
||||||
|
return "", err.Error(), 85, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search the environment variables for DENO_PERMISSIONS and use that to set permissions for the script.
|
||||||
|
// https://docs.deno.com/runtime/manual/basics/permissions#permissions-list
|
||||||
|
// DENO_PERMISSIONS is not an official environment variable.
|
||||||
|
// https://docs.deno.com/runtime/manual/basics/env_variables
|
||||||
|
// DENO_DEFAULT_PERMISSIONS is used if not found in the environment variables.
|
||||||
|
found := false
|
||||||
|
for i, v := range envVars {
|
||||||
|
if strings.HasPrefix(v, "DENO_PERMISSIONS=") {
|
||||||
|
permissions := strings.Split(v, "=")[1]
|
||||||
|
cmdArgs = append(cmdArgs, strings.Split(permissions, " ")...)
|
||||||
|
// Remove the DENO_PERMISSIONS variable from the environment variables slice.
|
||||||
|
// It's possible more variables may exist with the same prefix.
|
||||||
|
envVars = append(envVars[:i], envVars[i+1:]...)
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found && denoDefaultPermissions != "" {
|
||||||
|
cmdArgs = append(cmdArgs, strings.Split(denoDefaultPermissions, " ")...)
|
||||||
|
}
|
||||||
|
cmdArgs = append(cmdArgs, tmpfn.Name())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
@@ -698,6 +752,15 @@ func (a *Agent) AgentUninstall(code string) {
|
|||||||
|
|
||||||
// RunMigrations cleans up unused stuff from older agents
|
// RunMigrations cleans up unused stuff from older agents
|
||||||
func (a *Agent) RunMigrations() {
|
func (a *Agent) RunMigrations() {
|
||||||
|
|
||||||
|
// changed pybin dirs in v2.8.0
|
||||||
|
for _, i := range []string{"py38-x64", "py38-x32"} {
|
||||||
|
py := filepath.Join(a.ProgramDir, i)
|
||||||
|
if trmm.FileExists(py) {
|
||||||
|
os.RemoveAll(py)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, i := range []string{"nssm.exe", "nssm-x86.exe"} {
|
for _, i := range []string{"nssm.exe", "nssm-x86.exe"} {
|
||||||
nssm := filepath.Join(a.ProgramDir, i)
|
nssm := filepath.Join(a.ProgramDir, i)
|
||||||
if trmm.FileExists(nssm) {
|
if trmm.FileExists(nssm) {
|
||||||
@@ -791,26 +854,23 @@ func (a *Agent) GetPython(force bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var archZip string
|
|
||||||
var folder string
|
|
||||||
switch runtime.GOARCH {
|
|
||||||
case "amd64":
|
|
||||||
archZip = "py38-x64.zip"
|
|
||||||
folder = "py38-x64"
|
|
||||||
case "386":
|
|
||||||
archZip = "py38-x32.zip"
|
|
||||||
folder = "py38-x32"
|
|
||||||
}
|
|
||||||
pyFolder := filepath.Join(a.ProgramDir, folder)
|
|
||||||
pyZip := filepath.Join(a.ProgramDir, archZip)
|
|
||||||
a.Logger.Debugln(pyZip)
|
|
||||||
a.Logger.Debugln(a.PyBin)
|
|
||||||
defer os.Remove(pyZip)
|
|
||||||
|
|
||||||
if force {
|
if force {
|
||||||
os.RemoveAll(pyFolder)
|
os.RemoveAll(a.PyBaseDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sleepDelay := randRange(1, 10)
|
||||||
|
a.Logger.Debugf("GetPython() sleeping for %v seconds\n", sleepDelay)
|
||||||
|
time.Sleep(time.Duration(sleepDelay) * time.Second)
|
||||||
|
|
||||||
|
if !trmm.FileExists(a.PyBaseDir) {
|
||||||
|
os.MkdirAll(a.PyBaseDir, 0775)
|
||||||
|
}
|
||||||
|
|
||||||
|
archZip := a.PyDir + ".zip"
|
||||||
|
|
||||||
|
pyZip := filepath.Join(a.PyBaseDir, archZip)
|
||||||
|
defer os.Remove(pyZip)
|
||||||
|
|
||||||
rClient := resty.New()
|
rClient := resty.New()
|
||||||
rClient.SetTimeout(20 * time.Minute)
|
rClient.SetTimeout(20 * time.Minute)
|
||||||
rClient.SetRetryCount(10)
|
rClient.SetRetryCount(10)
|
||||||
@@ -820,7 +880,7 @@ func (a *Agent) GetPython(force bool) {
|
|||||||
rClient.SetProxy(a.Proxy)
|
rClient.SetProxy(a.Proxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
url := fmt.Sprintf("https://github.com/amidaware/rmmagent/releases/download/v2.0.0/%s", archZip)
|
url := fmt.Sprintf("https://github.com/amidaware/rmmagent/releases/download/v2.8.0/%s", archZip)
|
||||||
a.Logger.Debugln(url)
|
a.Logger.Debugln(url)
|
||||||
r, err := rClient.R().SetOutput(pyZip).Get(url)
|
r, err := rClient.R().SetOutput(pyZip).Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -832,12 +892,306 @@ func (a *Agent) GetPython(force bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = Unzip(pyZip, a.ProgramDir)
|
err = Unzip(pyZip, a.PyBaseDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.Logger.Errorln(err)
|
a.Logger.Errorln(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InstallNushell will download nushell from GitHub and install (copy) it to ProgramDir\bin, where ProgramDir is
|
||||||
|
// initialized to C:\Program Files\TacticalAgent
|
||||||
|
func (a *Agent) InstallNushell(force bool) {
|
||||||
|
sleepDelay := randRange(1, 10)
|
||||||
|
a.Logger.Debugf("InstallNushell() sleeping for %v seconds", sleepDelay)
|
||||||
|
time.Sleep(time.Duration(sleepDelay) * time.Second)
|
||||||
|
|
||||||
|
conf := a.GetAgentCheckInConfig(a.GetCheckInConfFromAPI())
|
||||||
|
if !conf.InstallNushell {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if trmm.FileExists(a.NuBin) {
|
||||||
|
if force {
|
||||||
|
a.Logger.Debugln(a.NuBin, "InstallNushell(): Forced install. Removing nu.exe binary.")
|
||||||
|
err := os.Remove(a.NuBin)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Error removing nu.exe binary:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
programBinDir := filepath.Join(a.ProgramDir, "bin")
|
||||||
|
if !trmm.FileExists(programBinDir) {
|
||||||
|
err := os.MkdirAll(programBinDir, 0755)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Error creating Program Files bin folder:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.NushellEnableConfig {
|
||||||
|
// Create 0-byte config files for Nushell
|
||||||
|
nushellPath := filepath.Join(a.ProgramDir, "etc", "nushell")
|
||||||
|
nushellConfig := filepath.Join(nushellPath, "config.nu")
|
||||||
|
nushellEnv := filepath.Join(nushellPath, "env.nu")
|
||||||
|
if !trmm.FileExists(nushellPath) {
|
||||||
|
err := os.MkdirAll(nushellPath, 0755)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Error creating Program Files/nushell:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !trmm.FileExists(nushellConfig) {
|
||||||
|
_, err := os.Create(nushellConfig)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Error creating nushell config.nu:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = os.Chmod(nushellConfig, 0744)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Error changing permissions for nushell config.nu:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !trmm.FileExists(nushellEnv) {
|
||||||
|
_, err := os.Create(nushellEnv)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Error creating nushell env.nu:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = os.Chmod(nushellEnv, 0744)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Error changing permissions for nushell env.nu:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
assetName string
|
||||||
|
url string
|
||||||
|
)
|
||||||
|
|
||||||
|
if conf.InstallNushellUrl != "" {
|
||||||
|
url = conf.InstallNushellUrl
|
||||||
|
url = strings.ReplaceAll(url, "{OS}", runtime.GOOS)
|
||||||
|
url = strings.ReplaceAll(url, "{ARCH}", runtime.GOARCH)
|
||||||
|
url = strings.ReplaceAll(url, "{VERSION}", conf.InstallNushellVersion)
|
||||||
|
} else {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "windows":
|
||||||
|
switch runtime.GOARCH {
|
||||||
|
case "amd64":
|
||||||
|
// https://github.com/nushell/nushell/releases/download/0.87.0/nu-0.87.0-x86_64-windows-msvc-full.zip
|
||||||
|
assetName = fmt.Sprintf("nu-%s-x86_64-windows-msvc-full.zip", conf.InstallNushellVersion)
|
||||||
|
case "arm64":
|
||||||
|
// https://github.com/nushell/nushell/releases/download/0.87.0/nu-0.87.0-aarch64-windows-msvc-full.zip
|
||||||
|
assetName = fmt.Sprintf("nu-%s-aarch64-windows-msvc-full.zip", conf.InstallNushellVersion)
|
||||||
|
default:
|
||||||
|
a.Logger.Debugln("InstallNushell(): Unsupported architecture and OS:", runtime.GOARCH, runtime.GOOS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
a.Logger.Debugln("InstallNushell(): Unsupported OS:", runtime.GOOS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
url = fmt.Sprintf("https://github.com/nushell/nushell/releases/download/%s/%s", conf.InstallNushellVersion, assetName)
|
||||||
|
}
|
||||||
|
a.Logger.Debugln("InstallNushell(): Nu download url:", url)
|
||||||
|
|
||||||
|
err := createWinTempDir()
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): createWinTempDir:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpDir, err := os.MkdirTemp(a.WinTmpDir, "nutemp")
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Error creating nushell temp directory:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func(path string) {
|
||||||
|
err := os.RemoveAll(path)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Error removing nushell temp directory:", err)
|
||||||
|
}
|
||||||
|
}(tmpDir)
|
||||||
|
|
||||||
|
tmpAssetName := filepath.Join(tmpDir, assetName)
|
||||||
|
a.Logger.Debugln("InstallNushell(): tmpAssetName:", tmpAssetName)
|
||||||
|
|
||||||
|
rClient := resty.New()
|
||||||
|
rClient.SetTimeout(20 * time.Minute)
|
||||||
|
rClient.SetRetryCount(10)
|
||||||
|
rClient.SetRetryWaitTime(1 * time.Minute)
|
||||||
|
rClient.SetRetryMaxWaitTime(15 * time.Minute)
|
||||||
|
if len(a.Proxy) > 0 {
|
||||||
|
rClient.SetProxy(a.Proxy)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := rClient.R().SetOutput(tmpAssetName).Get(url)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Unable to download nu:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if r.IsError() {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Unable to download nu. Status code:", r.StatusCode())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.InstallNushellUrl != "" {
|
||||||
|
// InstallNushellUrl is not compressed.
|
||||||
|
err = copyFile(filepath.Join(tmpDir, tmpAssetName), a.NuBin)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Failed to copy nu file to install dir:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = Unzip(tmpAssetName, tmpDir)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Failed to unzip downloaded zip file:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = copyFile(filepath.Join(tmpDir, "nu.exe"), a.NuBin)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallNushell(): Failed to copy nu.exe file to install dir:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// InstallDeno will download deno from GitHub and install (copy) it to ProgramDir\bin, where ProgramDir is
|
||||||
|
// initialized to C:\Program Files\TacticalAgent
|
||||||
|
func (a *Agent) InstallDeno(force bool) {
|
||||||
|
sleepDelay := randRange(1, 10)
|
||||||
|
a.Logger.Debugf("InstallDeno() sleeping for %v seconds", sleepDelay)
|
||||||
|
time.Sleep(time.Duration(sleepDelay) * time.Second)
|
||||||
|
|
||||||
|
conf := a.GetAgentCheckInConfig(a.GetCheckInConfFromAPI())
|
||||||
|
if !conf.InstallDeno {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if trmm.FileExists(a.DenoBin) {
|
||||||
|
if force {
|
||||||
|
err := os.Remove(a.DenoBin)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallDeno(): Error removing deno binary:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
programBinDir := filepath.Join(a.ProgramDir, "bin")
|
||||||
|
if !trmm.FileExists(programBinDir) {
|
||||||
|
err := os.MkdirAll(programBinDir, 0755)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallDeno(): Error creating Program Files bin folder:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
assetName string
|
||||||
|
url string
|
||||||
|
)
|
||||||
|
|
||||||
|
if conf.InstallDenoUrl != "" {
|
||||||
|
url = conf.InstallDenoUrl
|
||||||
|
url = strings.ReplaceAll(url, "{OS}", runtime.GOOS)
|
||||||
|
url = strings.ReplaceAll(url, "{ARCH}", runtime.GOARCH)
|
||||||
|
url = strings.ReplaceAll(url, "{VERSION}", conf.InstallDenoVersion)
|
||||||
|
} else {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "windows":
|
||||||
|
switch runtime.GOARCH {
|
||||||
|
case "amd64":
|
||||||
|
// https://github.com/denoland/deno/releases/download/v1.38.2/deno-x86_64-pc-windows-msvc.zip
|
||||||
|
assetName = "deno-x86_64-pc-windows-msvc.zip"
|
||||||
|
default:
|
||||||
|
a.Logger.Debugln("InstallDeno(): Unsupported architecture and OS:", runtime.GOARCH, runtime.GOOS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
a.Logger.Debugln("InstallDeno(): Unsupported OS:", runtime.GOOS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
url = fmt.Sprintf("https://github.com/denoland/deno/releases/download/%s/%s", conf.InstallDenoVersion, assetName)
|
||||||
|
}
|
||||||
|
a.Logger.Debugln("InstallDeno(): Deno download url:", url)
|
||||||
|
|
||||||
|
err := createWinTempDir()
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallDeno(): createWinTempDir:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpDir, err := os.MkdirTemp(a.WinTmpDir, "denotemp")
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallDeno(): Error creating deno temp directory:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func(path string) {
|
||||||
|
err := os.RemoveAll(path)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallDeno(): Error removing deno temp directory:", err)
|
||||||
|
}
|
||||||
|
}(tmpDir)
|
||||||
|
|
||||||
|
tmpAssetName := filepath.Join(tmpDir, assetName)
|
||||||
|
a.Logger.Debugln("InstallDeno(): tmpAssetName:", tmpAssetName)
|
||||||
|
|
||||||
|
rClient := resty.New()
|
||||||
|
rClient.SetTimeout(20 * time.Minute)
|
||||||
|
rClient.SetRetryCount(10)
|
||||||
|
rClient.SetRetryWaitTime(1 * time.Minute)
|
||||||
|
rClient.SetRetryMaxWaitTime(15 * time.Minute)
|
||||||
|
if len(a.Proxy) > 0 {
|
||||||
|
rClient.SetProxy(a.Proxy)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := rClient.R().SetOutput(tmpAssetName).Get(url)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallDeno(): Unable to download deno:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if r.IsError() {
|
||||||
|
a.Logger.Errorln("InstallDeno(): Unable to download deno. Status code:", r.StatusCode())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.InstallDenoUrl != "" {
|
||||||
|
// InstallDenoUrl is not compressed.
|
||||||
|
err = copyFile(filepath.Join(tmpDir, tmpAssetName), a.DenoBin)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallDeno(): Failed to copy deno file to install dir:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// GitHub asset is zip compressed.
|
||||||
|
err = Unzip(tmpAssetName, tmpDir)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallDeno(): Failed to unzip downloaded zip file:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = copyFile(filepath.Join(tmpDir, "deno.exe"), a.DenoBin)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("InstallDeno(): Failed to copy deno.exe file to install dir:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (a *Agent) RecoverMesh() {
|
func (a *Agent) RecoverMesh() {
|
||||||
a.Logger.Infoln("Attempting mesh recovery")
|
a.Logger.Infoln("Attempting mesh recovery")
|
||||||
defer CMD("net", []string{"start", a.MeshSVC}, 60, false)
|
defer CMD("net", []string{"start", a.MeshSVC}, 60, false)
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ type ScriptCheckResult struct {
|
|||||||
// ScriptCheck runs either bat, powershell or python script
|
// ScriptCheck runs either bat, powershell or python script
|
||||||
func (a *Agent) ScriptCheck(data rmm.Check, r *resty.Client) {
|
func (a *Agent) ScriptCheck(data rmm.Check, r *resty.Client) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
stdout, stderr, retcode, _ := a.RunScript(data.Script.Code, data.Script.Shell, data.ScriptArgs, data.Timeout, data.Script.RunAsUser, data.EnvVars)
|
stdout, stderr, retcode, _ := a.RunScript(data.Script.Code, data.Script.Shell, data.ScriptArgs, data.Timeout, data.Script.RunAsUser, data.EnvVars, data.NushellEnableConfig, data.DenoDefaultPermissions)
|
||||||
|
|
||||||
payload := ScriptCheckResult{
|
payload := ScriptCheckResult{
|
||||||
ID: data.CheckPK,
|
ID: data.CheckPK,
|
||||||
@@ -260,7 +260,7 @@ func (a *Agent) EventLogCheck(data rmm.Check, r *resty.Client) {
|
|||||||
|
|
||||||
for _, i := range evtLog {
|
for _, i := range evtLog {
|
||||||
if i.EventType == data.EventType {
|
if i.EventType == data.EventType {
|
||||||
if !data.EventIDWildcard && !(int(i.EventID) == data.EventID) {
|
if !data.EventIDWildcard && (int(i.EventID) != data.EventID) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ func (a *Agent) InstallChoco() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, exitcode, err := a.RunScript(string(r.Body()), "powershell", []string{}, 900, false, []string{})
|
_, _, exitcode, err := a.RunScript(string(r.Body()), "powershell", []string{}, 900, false, []string{}, false, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.Logger.Debugln(err)
|
a.Logger.Debugln(err)
|
||||||
a.rClient.R().SetBody(result).Post(url)
|
a.rClient.R().SetBody(result).Post(url)
|
||||||
|
|||||||
@@ -20,5 +20,5 @@ import _ "embed"
|
|||||||
var ventura_mesh_fix string
|
var ventura_mesh_fix string
|
||||||
|
|
||||||
func (a *Agent) FixVenturaMesh() {
|
func (a *Agent) FixVenturaMesh() {
|
||||||
a.RunScript(ventura_mesh_fix, "foo", []string{}, 45, false, []string{})
|
a.RunScript(ventura_mesh_fix, "foo", []string{}, 45, false, []string{}, false, "")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,8 +158,11 @@ func getResourceMessage(providerName, sourceName string, eventID uint32, argsptr
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
handle, err := LoadLibraryEx(syscall.StringToUTF16Ptr(val), 0,
|
handlePtr, err := windows.UTF16PtrFromString(val)
|
||||||
DONT_RESOLVE_DLL_REFERENCES|LOAD_LIBRARY_AS_DATAFILE)
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
handle, err := LoadLibraryEx(handlePtr, 0, DONT_RESOLVE_DLL_REFERENCES|LOAD_LIBRARY_AS_DATAFILE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -180,7 +183,7 @@ func getResourceMessage(providerName, sourceName string, eventID uint32, argsptr
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
message, _ := bytesToString(msgbuf[:numChars*2])
|
message, _ := bytesToString(msgbuf[:numChars*2])
|
||||||
message = strings.Replace(message, "\r", "", -1)
|
message = strings.ReplaceAll(message, "\r", "")
|
||||||
message = strings.TrimSuffix(message, "\n")
|
message = strings.TrimSuffix(message, "\n")
|
||||||
return message, nil
|
return message, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -258,8 +258,13 @@ func (a *Agent) Install(i *Installer) {
|
|||||||
// check in once
|
// check in once
|
||||||
a.DoNatsCheckIn()
|
a.DoNatsCheckIn()
|
||||||
|
|
||||||
|
if runtime.GOOS == "linux" {
|
||||||
|
// Used for Nushell and Deno binaries
|
||||||
|
os.MkdirAll(nixAgentBinDir, 0755)
|
||||||
|
}
|
||||||
|
|
||||||
if runtime.GOOS == "darwin" {
|
if runtime.GOOS == "darwin" {
|
||||||
os.MkdirAll(nixAgentDir, 0755)
|
os.MkdirAll(nixAgentBinDir, 0755)
|
||||||
self, _ := os.Executable()
|
self, _ := os.Executable()
|
||||||
copyFile(self, nixAgentBin)
|
copyFile(self, nixAgentBin)
|
||||||
os.Chmod(nixAgentBin, 0755)
|
os.Chmod(nixAgentBin, 0755)
|
||||||
@@ -300,6 +305,8 @@ func (a *Agent) Install(i *Installer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
|
os.MkdirAll(filepath.Join(a.ProgramDir, "bin"), 0755)
|
||||||
|
|
||||||
// send software api
|
// send software api
|
||||||
a.SendSoftware()
|
a.SendSoftware()
|
||||||
|
|
||||||
@@ -341,7 +348,7 @@ func (a *Agent) Install(i *Installer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a.installerMsg("Installation was successfull!\nAllow a few minutes for the agent to properly display in the RMM", "info", i.Silent)
|
a.installerMsg("Installation was successful!\nAllow a few minutes for the agent to properly display in the RMM", "info", i.Silent)
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyFile(src, dst string) error {
|
func copyFile(src, dst string) error {
|
||||||
|
|||||||
26
agent/rpc.go
26
agent/rpc.go
@@ -42,6 +42,8 @@ type NatsMsg struct {
|
|||||||
Code string `json:"code"`
|
Code string `json:"code"`
|
||||||
RunAsUser bool `json:"run_as_user"`
|
RunAsUser bool `json:"run_as_user"`
|
||||||
EnvVars []string `json:"env_vars"`
|
EnvVars []string `json:"env_vars"`
|
||||||
|
NushellEnableConfig bool `json:"nushell_enable_config"`
|
||||||
|
DenoDefaultPermissions string `json:"deno_default_permissions"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -264,7 +266,7 @@ func (a *Agent) RunRPC() {
|
|||||||
var resultData rmm.RunScriptResp
|
var resultData rmm.RunScriptResp
|
||||||
ret := codec.NewEncoderBytes(&resp, new(codec.MsgpackHandle))
|
ret := codec.NewEncoderBytes(&resp, new(codec.MsgpackHandle))
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
stdout, stderr, retcode, err := a.RunScript(p.Data["code"], p.Data["shell"], p.ScriptArgs, p.Timeout, p.RunAsUser, p.EnvVars)
|
stdout, stderr, retcode, err := a.RunScript(p.Data["code"], p.Data["shell"], p.ScriptArgs, p.Timeout, p.RunAsUser, p.EnvVars, p.NushellEnableConfig, p.DenoDefaultPermissions)
|
||||||
resultData.ExecTime = time.Since(start).Seconds()
|
resultData.ExecTime = time.Since(start).Seconds()
|
||||||
resultData.ID = p.ID
|
resultData.ID = p.ID
|
||||||
|
|
||||||
@@ -294,7 +296,7 @@ func (a *Agent) RunRPC() {
|
|||||||
var retData rmm.RunScriptResp
|
var retData rmm.RunScriptResp
|
||||||
ret := codec.NewEncoderBytes(&resp, new(codec.MsgpackHandle))
|
ret := codec.NewEncoderBytes(&resp, new(codec.MsgpackHandle))
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
stdout, stderr, retcode, err := a.RunScript(p.Data["code"], p.Data["shell"], p.ScriptArgs, p.Timeout, p.RunAsUser, p.EnvVars)
|
stdout, stderr, retcode, err := a.RunScript(p.Data["code"], p.Data["shell"], p.ScriptArgs, p.Timeout, p.RunAsUser, p.EnvVars, p.NushellEnableConfig, p.DenoDefaultPermissions)
|
||||||
|
|
||||||
retData.ExecTime = time.Since(start).Seconds()
|
retData.ExecTime = time.Since(start).Seconds()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -339,6 +341,22 @@ func (a *Agent) RunRPC() {
|
|||||||
msg.Respond(resp)
|
msg.Respond(resp)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
case "shutdown":
|
||||||
|
go func() {
|
||||||
|
a.Logger.Debugln("Scheduling immediate shutdown")
|
||||||
|
var resp []byte
|
||||||
|
ret := codec.NewEncoderBytes(&resp, new(codec.MsgpackHandle))
|
||||||
|
ret.Encode("ok")
|
||||||
|
msg.Respond(resp)
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
CMD("shutdown.exe", []string{"/s", "/t", "5", "/f"}, 15, false)
|
||||||
|
} else {
|
||||||
|
opts := a.NewCMDOpts()
|
||||||
|
opts.Command = "shutdown -h now"
|
||||||
|
a.CmdV2(opts)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
case "rebootnow":
|
case "rebootnow":
|
||||||
go func() {
|
go func() {
|
||||||
a.Logger.Debugln("Scheduling immediate reboot")
|
a.Logger.Debugln("Scheduling immediate reboot")
|
||||||
@@ -437,6 +455,10 @@ func (a *Agent) RunRPC() {
|
|||||||
}()
|
}()
|
||||||
case "installpython":
|
case "installpython":
|
||||||
go a.GetPython(true)
|
go a.GetPython(true)
|
||||||
|
case "installnushell":
|
||||||
|
go a.InstallNushell(true)
|
||||||
|
case "installdeno":
|
||||||
|
go a.InstallDeno(true)
|
||||||
case "installchoco":
|
case "installchoco":
|
||||||
go a.InstallChoco()
|
go a.InstallChoco()
|
||||||
case "installwithchoco":
|
case "installwithchoco":
|
||||||
|
|||||||
@@ -119,9 +119,10 @@ func (a *Agent) EditService(name, startupType string) rmm.WinSvcResp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
conf.StartType = startType
|
conf.StartType = startType
|
||||||
if startupType == "autodelay" {
|
switch startupType {
|
||||||
|
case "autodelay":
|
||||||
conf.DelayedAutoStart = true
|
conf.DelayedAutoStart = true
|
||||||
} else if startupType == "auto" {
|
case "auto":
|
||||||
conf.DelayedAutoStart = false
|
conf.DelayedAutoStart = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
39
agent/svc.go
39
agent/svc.go
@@ -38,9 +38,19 @@ type AgentCheckInConfig struct {
|
|||||||
WMI int `json:"checkin_wmi"`
|
WMI int `json:"checkin_wmi"`
|
||||||
SyncMesh int `json:"checkin_syncmesh"`
|
SyncMesh int `json:"checkin_syncmesh"`
|
||||||
LimitData bool `json:"limit_data"`
|
LimitData bool `json:"limit_data"`
|
||||||
|
InstallNushell bool `json:"install_nushell"`
|
||||||
|
InstallNushellVersion string `json:"install_nushell_version"`
|
||||||
|
InstallNushellUrl string `json:"install_nushell_url"`
|
||||||
|
NushellEnableConfig bool `json:"nushell_enable_config"`
|
||||||
|
InstallDeno bool `json:"install_deno"`
|
||||||
|
InstallDenoVersion string `json:"install_deno_version"`
|
||||||
|
InstallDenoUrl string `json:"install_deno_url"`
|
||||||
|
DenoDefaultPermissions string `json:"deno_default_permissions"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) AgentSvc(nc *nats.Conn) {
|
func (a *Agent) AgentSvc(nc *nats.Conn) {
|
||||||
|
a.RunMigrations()
|
||||||
|
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
go a.GetPython(false)
|
go a.GetPython(false)
|
||||||
|
|
||||||
@@ -49,7 +59,6 @@ func (a *Agent) AgentSvc(nc *nats.Conn) {
|
|||||||
a.Logger.Errorln("AgentSvc() createWinTempDir():", err)
|
a.Logger.Errorln("AgentSvc() createWinTempDir():", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
a.RunMigrations()
|
|
||||||
|
|
||||||
sleepDelay := randRange(7, 25)
|
sleepDelay := randRange(7, 25)
|
||||||
a.Logger.Debugf("AgentSvc() sleeping for %v seconds", sleepDelay)
|
a.Logger.Debugf("AgentSvc() sleeping for %v seconds", sleepDelay)
|
||||||
@@ -61,8 +70,9 @@ func (a *Agent) AgentSvc(nc *nats.Conn) {
|
|||||||
a.CleanupAgentUpdates()
|
a.CleanupAgentUpdates()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Windows has GetAgentCheckInConfig() while unix has a stub GetAgentCheckInConfig()
|
||||||
conf := a.GetAgentCheckInConfig(a.GetCheckInConfFromAPI())
|
conf := a.GetAgentCheckInConfig(a.GetCheckInConfFromAPI())
|
||||||
a.Logger.Debugf("+%v\n", conf)
|
a.Logger.Debugf("AgentCheckInConf: %+v\n", conf)
|
||||||
for _, s := range natsCheckin {
|
for _, s := range natsCheckin {
|
||||||
if conf.LimitData && stringInSlice(s, limitNatsData) {
|
if conf.LimitData && stringInSlice(s, limitNatsData) {
|
||||||
continue
|
continue
|
||||||
@@ -72,6 +82,15 @@ func (a *Agent) AgentSvc(nc *nats.Conn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The server conf check is also done in the functions to keep the parameters the same.
|
||||||
|
// Don't force a download when restarting the service.
|
||||||
|
if conf.InstallNushell {
|
||||||
|
go a.InstallNushell(false)
|
||||||
|
}
|
||||||
|
if conf.InstallDeno {
|
||||||
|
go a.InstallDeno(false)
|
||||||
|
}
|
||||||
|
|
||||||
go a.SyncMeshNodeID()
|
go a.SyncMeshNodeID()
|
||||||
|
|
||||||
time.Sleep(time.Duration(randRange(1, 3)) * time.Second)
|
time.Sleep(time.Duration(randRange(1, 3)) * time.Second)
|
||||||
@@ -139,6 +158,14 @@ func (a *Agent) GetCheckInConfFromAPI() AgentCheckInConfig {
|
|||||||
ret.WMI = randRange(3000, 4000)
|
ret.WMI = randRange(3000, 4000)
|
||||||
ret.SyncMesh = randRange(800, 1200)
|
ret.SyncMesh = randRange(800, 1200)
|
||||||
ret.LimitData = false
|
ret.LimitData = false
|
||||||
|
ret.InstallNushell = false
|
||||||
|
ret.InstallNushellVersion = ""
|
||||||
|
ret.InstallNushellUrl = ""
|
||||||
|
ret.NushellEnableConfig = false
|
||||||
|
ret.InstallDeno = false
|
||||||
|
ret.InstallDenoVersion = ""
|
||||||
|
ret.InstallDenoUrl = ""
|
||||||
|
ret.DenoDefaultPermissions = ""
|
||||||
} else {
|
} else {
|
||||||
ret.Hello = r.Result().(*AgentCheckInConfig).Hello
|
ret.Hello = r.Result().(*AgentCheckInConfig).Hello
|
||||||
ret.AgentInfo = r.Result().(*AgentCheckInConfig).AgentInfo
|
ret.AgentInfo = r.Result().(*AgentCheckInConfig).AgentInfo
|
||||||
@@ -149,6 +176,14 @@ func (a *Agent) GetCheckInConfFromAPI() AgentCheckInConfig {
|
|||||||
ret.WMI = r.Result().(*AgentCheckInConfig).WMI
|
ret.WMI = r.Result().(*AgentCheckInConfig).WMI
|
||||||
ret.SyncMesh = r.Result().(*AgentCheckInConfig).SyncMesh
|
ret.SyncMesh = r.Result().(*AgentCheckInConfig).SyncMesh
|
||||||
ret.LimitData = r.Result().(*AgentCheckInConfig).LimitData
|
ret.LimitData = r.Result().(*AgentCheckInConfig).LimitData
|
||||||
|
ret.InstallNushell = r.Result().(*AgentCheckInConfig).InstallNushell
|
||||||
|
ret.InstallNushellVersion = r.Result().(*AgentCheckInConfig).InstallNushellVersion
|
||||||
|
ret.InstallNushellUrl = r.Result().(*AgentCheckInConfig).InstallNushellUrl
|
||||||
|
ret.NushellEnableConfig = r.Result().(*AgentCheckInConfig).NushellEnableConfig
|
||||||
|
ret.InstallDeno = r.Result().(*AgentCheckInConfig).InstallDeno
|
||||||
|
ret.InstallDenoVersion = r.Result().(*AgentCheckInConfig).InstallDenoVersion
|
||||||
|
ret.InstallDenoUrl = r.Result().(*AgentCheckInConfig).InstallDenoUrl
|
||||||
|
ret.DenoDefaultPermissions = r.Result().(*AgentCheckInConfig).DenoDefaultPermissions
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,119 +12,16 @@ https://license.tacticalrmm.com
|
|||||||
package agent
|
package agent
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
rmm "github.com/amidaware/rmmagent/shared"
|
|
||||||
"github.com/amidaware/taskmaster"
|
"github.com/amidaware/taskmaster"
|
||||||
"github.com/rickb777/date/period"
|
"github.com/rickb777/date/period"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *Agent) RunTask(id int) error {
|
|
||||||
data := rmm.AutomatedTask{}
|
|
||||||
url := fmt.Sprintf("/api/v3/%d/%s/taskrunner/", id, a.AgentID)
|
|
||||||
r1, gerr := a.rClient.R().Get(url)
|
|
||||||
if gerr != nil {
|
|
||||||
a.Logger.Debugln(gerr)
|
|
||||||
return gerr
|
|
||||||
}
|
|
||||||
|
|
||||||
if r1.IsError() {
|
|
||||||
a.Logger.Debugln("Run Task:", r1.String())
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(r1.Body(), &data); err != nil {
|
|
||||||
a.Logger.Debugln(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
start := time.Now()
|
|
||||||
|
|
||||||
type TaskResult struct {
|
|
||||||
Stdout string `json:"stdout"`
|
|
||||||
Stderr string `json:"stderr"`
|
|
||||||
RetCode int `json:"retcode"`
|
|
||||||
ExecTime float64 `json:"execution_time"`
|
|
||||||
}
|
|
||||||
|
|
||||||
payload := TaskResult{}
|
|
||||||
|
|
||||||
// loop through all task actions
|
|
||||||
for _, action := range data.TaskActions {
|
|
||||||
|
|
||||||
action_start := time.Now()
|
|
||||||
if action.ActionType == "script" {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
// add text to stdout showing which script ran if more than 1 script
|
|
||||||
action_exec_time := time.Since(action_start).Seconds()
|
|
||||||
|
|
||||||
if len(data.TaskActions) > 1 {
|
|
||||||
payload.Stdout += fmt.Sprintf("\n------------\nRunning Script: %s. Execution Time: %f\n------------\n\n", action.ScriptName, action_exec_time)
|
|
||||||
}
|
|
||||||
|
|
||||||
// save results
|
|
||||||
payload.Stdout += stdout
|
|
||||||
payload.Stderr += stderr
|
|
||||||
payload.RetCode = retcode
|
|
||||||
|
|
||||||
if !data.ContinueOnError && stderr != "" {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if action.ActionType == "cmd" {
|
|
||||||
// out[0] == stdout, out[1] == stderr
|
|
||||||
out, err := CMDShell(action.Shell, []string{}, action.Command, action.Timeout, false, action.RunAsUser)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
a.Logger.Debugln(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(data.TaskActions) > 1 {
|
|
||||||
action_exec_time := time.Since(action_start).Seconds()
|
|
||||||
|
|
||||||
// add text to stdout showing which script ran
|
|
||||||
payload.Stdout += fmt.Sprintf("\n------------\nRunning Command: %s. Execution Time: %f\n------------\n\n", action.Command, action_exec_time)
|
|
||||||
}
|
|
||||||
// save results
|
|
||||||
payload.Stdout += out[0]
|
|
||||||
payload.Stderr += out[1]
|
|
||||||
|
|
||||||
// no error
|
|
||||||
if out[1] == "" {
|
|
||||||
payload.RetCode = 0
|
|
||||||
} else {
|
|
||||||
payload.RetCode = 1
|
|
||||||
|
|
||||||
if !data.ContinueOnError {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
a.Logger.Debugln("Invalid Action", action)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
payload.ExecTime = time.Since(start).Seconds()
|
|
||||||
|
|
||||||
_, perr := a.rClient.R().SetBody(payload).Patch(url)
|
|
||||||
if perr != nil {
|
|
||||||
a.Logger.Debugln(perr)
|
|
||||||
return perr
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type SchedTask struct {
|
type SchedTask struct {
|
||||||
PK int `json:"pk"`
|
PK int `json:"pk"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
|
|||||||
@@ -12,8 +12,11 @@ https://license.tacticalrmm.com
|
|||||||
package agent
|
package agent
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"archive/tar"
|
||||||
"archive/zip"
|
"archive/zip"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"compress/gzip"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
@@ -89,6 +92,7 @@ func DoPing(host string) (PingResponse, error) {
|
|||||||
func (a *Agent) PublicIP() string {
|
func (a *Agent) PublicIP() string {
|
||||||
a.Logger.Debugln("PublicIP start")
|
a.Logger.Debugln("PublicIP start")
|
||||||
client := resty.New()
|
client := resty.New()
|
||||||
|
client.SetHeader("User-Agent", a.AgentHeader)
|
||||||
client.SetTimeout(4 * time.Second)
|
client.SetTimeout(4 * time.Second)
|
||||||
if len(a.Proxy) > 0 {
|
if len(a.Proxy) > 0 {
|
||||||
client.SetProxy(a.Proxy)
|
client.SetProxy(a.Proxy)
|
||||||
@@ -280,6 +284,73 @@ func Unzip(src, dest string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExtractTarGz extracts a tar.gz file to the specified directory.
|
||||||
|
// Returns the extracted directory name.
|
||||||
|
// https://stackoverflow.com/questions/57639648/how-to-decompress-tar-gz-file-in-go
|
||||||
|
func (a *Agent) ExtractTarGz(targz string, destDir string) (extractedDir string, err error) {
|
||||||
|
gzipStream, err := os.Open(targz)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("ExtractTarGz(): Open() failed:", err.Error())
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer gzipStream.Close()
|
||||||
|
|
||||||
|
uncompressedStream, err := gzip.NewReader(gzipStream)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("ExtractTarGz(): NewReader() failed:", err.Error())
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer uncompressedStream.Close()
|
||||||
|
|
||||||
|
extractedDir = ""
|
||||||
|
tarReader := tar.NewReader(uncompressedStream)
|
||||||
|
for {
|
||||||
|
header, err := tarReader.Next()
|
||||||
|
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("ExtractTarGz(): Next() failed:", err.Error())
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch header.Typeflag {
|
||||||
|
case tar.TypeDir:
|
||||||
|
if err := os.MkdirAll(filepath.Join(destDir, header.Name), 0755); err != nil {
|
||||||
|
a.Logger.Errorln("ExtractTarGz(): Mkdir() failed:", err.Error())
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if extractedDir == "" {
|
||||||
|
extractedDir = header.Name
|
||||||
|
}
|
||||||
|
case tar.TypeReg:
|
||||||
|
outFile, err := os.Create(filepath.Join(destDir, header.Name))
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("ExtractTarGz(): Create() failed:", err.Error())
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if _, err := io.Copy(outFile, tarReader); err != nil {
|
||||||
|
a.Logger.Errorln("ExtractTarGz(): Copy() failed:", err.Error())
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
err = outFile.Close()
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Errorln("ExtractTarGz(): Close() failed:", err.Error())
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
errMsg := fmt.Sprintf("ExtractTarGz(): Unknown type: %v in %s", header.Typeflag, header.Name)
|
||||||
|
a.Logger.Errorln(errMsg)
|
||||||
|
return "", errors.New(errMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return extractedDir, nil
|
||||||
|
}
|
||||||
|
|
||||||
// https://yourbasic.org/golang/formatting-byte-size-to-human-readable-format/
|
// https://yourbasic.org/golang/formatting-byte-size-to-human-readable-format/
|
||||||
func ByteCountSI(b uint64) string {
|
func ByteCountSI(b uint64) string {
|
||||||
const unit = 1024
|
const unit = 1024
|
||||||
@@ -362,14 +433,19 @@ func getCwd() (string, error) {
|
|||||||
return filepath.Dir(self), nil
|
return filepath.Dir(self), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createNixTmpFile() (*os.File, error) {
|
func createNixTmpFile(shell ...string) (*os.File, error) {
|
||||||
var f *os.File
|
var f *os.File
|
||||||
cwd, err := getCwd()
|
cwd, err := getCwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return f, err
|
return f, err
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err = os.CreateTemp(cwd, "trmm")
|
ext := ""
|
||||||
|
if len(shell) > 0 && shell[0] == "deno" {
|
||||||
|
ext = ".ts"
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err = os.CreateTemp(cwd, fmt.Sprintf("trmm*%s", ext))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return f, err
|
return f, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<assemblyIdentity
|
<assemblyIdentity
|
||||||
type="win32"
|
type="win32"
|
||||||
name="TacticalRMM"
|
name="TacticalRMM"
|
||||||
version="2.6.2.0"
|
version="2.8.0.0"
|
||||||
processorArchitecture="*"/>
|
processorArchitecture="*"/>
|
||||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
<security>
|
<security>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#define MyAppName "Tactical RMM Agent"
|
#define MyAppName "Tactical RMM Agent"
|
||||||
#define MyAppVersion "2.6.2"
|
#define MyAppVersion "2.8.0"
|
||||||
#define MyAppPublisher "AmidaWare Inc"
|
#define MyAppPublisher "AmidaWare Inc"
|
||||||
#define MyAppURL "https://github.com/amidaware"
|
#define MyAppURL "https://github.com/amidaware"
|
||||||
#define MyAppExeName "tacticalrmm.exe"
|
#define MyAppExeName "tacticalrmm.exe"
|
||||||
@@ -28,6 +28,8 @@ WizardStyle=modern
|
|||||||
RestartApplications=no
|
RestartApplications=no
|
||||||
CloseApplications=no
|
CloseApplications=no
|
||||||
MinVersion=6.0
|
MinVersion=6.0
|
||||||
|
VersionInfoVersion=1.0.0.0
|
||||||
|
AppCopyright="Copyright (C) 2024 {#MyAppPublisher}"
|
||||||
|
|
||||||
[Languages]
|
[Languages]
|
||||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||||
|
|||||||
20
go.mod
20
go.mod
@@ -7,30 +7,31 @@ require (
|
|||||||
github.com/elastic/go-sysinfo v1.11.2
|
github.com/elastic/go-sysinfo v1.11.2
|
||||||
github.com/go-ole/go-ole v1.3.0
|
github.com/go-ole/go-ole v1.3.0
|
||||||
github.com/go-ping/ping v1.1.0
|
github.com/go-ping/ping v1.1.0
|
||||||
github.com/go-resty/resty/v2 v2.11.0
|
github.com/go-resty/resty/v2 v2.13.1
|
||||||
github.com/gonutz/w32/v2 v2.11.1
|
github.com/gonutz/w32/v2 v2.11.1
|
||||||
github.com/iamacarpet/go-win64api v0.0.0-20230324134531-ef6dbdd6db97
|
github.com/iamacarpet/go-win64api v0.0.0-20230324134531-ef6dbdd6db97
|
||||||
github.com/nats-io/nats.go v1.32.0
|
github.com/nats-io/nats.go v1.36.0
|
||||||
github.com/rickb777/date v1.19.1
|
github.com/rickb777/date v1.19.1
|
||||||
github.com/shirou/gopsutil/v3 v3.23.12
|
github.com/shirou/gopsutil/v3 v3.23.12
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
github.com/ugorji/go/codec v1.2.12
|
github.com/ugorji/go/codec v1.2.12
|
||||||
github.com/wh1te909/go-win64api v0.0.0-20230802051600-21b24f62e846
|
github.com/wh1te909/go-win64api v0.0.0-20230802051600-21b24f62e846
|
||||||
github.com/wh1te909/trmm-shared v0.0.0-20220227075846-f9f757361139
|
github.com/wh1te909/trmm-shared v0.0.0-20220227075846-f9f757361139
|
||||||
golang.org/x/net v0.19.0 // indirect
|
golang.org/x/net v0.25.0 // indirect
|
||||||
golang.org/x/sys v0.16.0
|
golang.org/x/sys v0.20.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/amidaware/taskmaster v0.0.0-20220111015025-c9cd178bbbf2
|
github.com/amidaware/taskmaster v0.0.0-20220111015025-c9cd178bbbf2
|
||||||
github.com/go-cmd/cmd v1.4.2
|
github.com/go-cmd/cmd v1.4.3
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/fourcorelabs/wintoken v1.0.0
|
github.com/fourcorelabs/wintoken v1.0.0
|
||||||
github.com/jaypipes/ghw v0.12.0
|
github.com/jaypipes/ghw v0.12.0
|
||||||
github.com/kardianos/service v1.2.2
|
github.com/kardianos/service v1.2.2
|
||||||
github.com/spf13/viper v1.18.2
|
github.com/spf13/viper v1.19.0
|
||||||
|
golang.org/x/text v0.15.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -51,7 +52,7 @@ require (
|
|||||||
github.com/nats-io/nkeys v0.4.7 // indirect
|
github.com/nats-io/nkeys v0.4.7 // indirect
|
||||||
github.com/nats-io/nuid v1.0.1 // indirect
|
github.com/nats-io/nuid v1.0.1 // indirect
|
||||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c // indirect
|
github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c // indirect
|
||||||
github.com/prometheus/procfs v0.8.0 // indirect
|
github.com/prometheus/procfs v0.8.0 // indirect
|
||||||
@@ -70,10 +71,9 @@ require (
|
|||||||
github.com/yusufpapurcu/wmi v1.2.3 // indirect
|
github.com/yusufpapurcu/wmi v1.2.3 // indirect
|
||||||
go.uber.org/atomic v1.9.0 // indirect
|
go.uber.org/atomic v1.9.0 // indirect
|
||||||
go.uber.org/multierr v1.9.0 // indirect
|
go.uber.org/multierr v1.9.0 // indirect
|
||||||
golang.org/x/crypto v0.18.0 // indirect
|
golang.org/x/crypto v0.23.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||||
golang.org/x/sync v0.5.0 // indirect
|
golang.org/x/sync v0.6.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2 // indirect
|
gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2 // indirect
|
||||||
|
|||||||
55
go.sum
55
go.sum
@@ -28,8 +28,8 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos
|
|||||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/go-cmd/cmd v1.4.2 h1:pnX38iIJHh4huzBSqfkAZkfXrVwM/5EccAJmrVqMnbg=
|
github.com/go-cmd/cmd v1.4.3 h1:6y3G+3UqPerXvPcXvj+5QNPHT02BUw7p6PsqRxLNA7Y=
|
||||||
github.com/go-cmd/cmd v1.4.2/go.mod h1:u3hxg/ry+D5kwh8WvUkHLAMe2zQCaXd00t35WfQaOFk=
|
github.com/go-cmd/cmd v1.4.3/go.mod h1:u3hxg/ry+D5kwh8WvUkHLAMe2zQCaXd00t35WfQaOFk=
|
||||||
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
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.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
@@ -37,8 +37,8 @@ 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-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 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw=
|
||||||
github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk=
|
github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk=
|
||||||
github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8=
|
github.com/go-resty/resty/v2 v2.13.1 h1:x+LHXBI2nMB1vqndymf26quycC4aggYJ7DECYbiz03g=
|
||||||
github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
|
github.com/go-resty/resty/v2 v2.13.1/go.mod h1:GznXlLxkq6Nh4sU59rPmUw3VtgpO3aS96ORAI6Q7d+0=
|
||||||
github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
|
github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
|
||||||
github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
@@ -109,8 +109,8 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG
|
|||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
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 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/nats-io/nats.go v1.32.0 h1:Bx9BZS+aXYlxW08k8Gd3yR2s73pV5XSoAQUyp1Kwvp0=
|
github.com/nats-io/nats.go v1.36.0 h1:suEUPuWzTSse/XhESwqLxXGuj8vGRuPRoG7MoRN/qyU=
|
||||||
github.com/nats-io/nats.go v1.32.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8=
|
github.com/nats-io/nats.go v1.36.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8=
|
||||||
github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI=
|
github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI=
|
||||||
github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
|
github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
|
||||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||||
@@ -125,8 +125,8 @@ github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
|
|||||||
github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw=
|
github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw=
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
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/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.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||||
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
@@ -167,17 +167,19 @@ github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
|
|||||||
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
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/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
|
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
|
||||||
github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
|
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
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/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
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.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
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/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
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 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||||
@@ -200,9 +202,9 @@ go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTV
|
|||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
||||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
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/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
@@ -219,16 +221,16 @@ golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qx
|
|||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
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.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.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/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-20210220032951-036812b2e83c/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.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.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -257,26 +259,27 @@ 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.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.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.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||||
|
golang.org/x/sys v0.20.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-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.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.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.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||||
|
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||||
golang.org/x/text v0.3.0/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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
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.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.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/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
|
||||||
|
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
|
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
|||||||
6
main.go
6
main.go
@@ -25,7 +25,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
version = "2.6.2"
|
version = "2.8.0"
|
||||||
log = logrus.New()
|
log = logrus.New()
|
||||||
logFile *os.File
|
logFile *os.File
|
||||||
)
|
)
|
||||||
@@ -117,6 +117,10 @@ func main() {
|
|||||||
fmt.Println(a.PublicIP())
|
fmt.Println(a.PublicIP())
|
||||||
case "getpython":
|
case "getpython":
|
||||||
a.GetPython(true)
|
a.GetPython(true)
|
||||||
|
case "installdeno":
|
||||||
|
a.InstallDeno(true)
|
||||||
|
case "installnushell":
|
||||||
|
a.InstallNushell(true)
|
||||||
case "runmigrations":
|
case "runmigrations":
|
||||||
a.RunMigrations()
|
a.RunMigrations()
|
||||||
case "recovermesh":
|
case "recovermesh":
|
||||||
|
|||||||
@@ -167,6 +167,8 @@ type Check struct {
|
|||||||
IP string `json:"ip"`
|
IP string `json:"ip"`
|
||||||
ScriptArgs []string `json:"script_args"`
|
ScriptArgs []string `json:"script_args"`
|
||||||
EnvVars []string `json:"env_vars"`
|
EnvVars []string `json:"env_vars"`
|
||||||
|
NushellEnableConfig bool `json:"nushell_enable_config"`
|
||||||
|
DenoDefaultPermissions string `json:"deno_default_permissions"`
|
||||||
Timeout int `json:"timeout"`
|
Timeout int `json:"timeout"`
|
||||||
ServiceName string `json:"svc_name"`
|
ServiceName string `json:"svc_name"`
|
||||||
PassStartPending bool `json:"pass_if_start_pending"`
|
PassStartPending bool `json:"pass_if_start_pending"`
|
||||||
@@ -197,6 +199,8 @@ type TaskAction struct {
|
|||||||
Timeout int `json:"timeout"`
|
Timeout int `json:"timeout"`
|
||||||
RunAsUser bool `json:"run_as_user"`
|
RunAsUser bool `json:"run_as_user"`
|
||||||
EnvVars []string `json:"env_vars"`
|
EnvVars []string `json:"env_vars"`
|
||||||
|
NushellEnableConfig bool `json:"nushell_enable_config"`
|
||||||
|
DenoDefaultPermissions string `json:"deno_default_permissions"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AutomatedTask struct {
|
type AutomatedTask struct {
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
"FixedFileInfo": {
|
"FixedFileInfo": {
|
||||||
"FileVersion": {
|
"FileVersion": {
|
||||||
"Major": 2,
|
"Major": 2,
|
||||||
"Minor": 6,
|
"Minor": 8,
|
||||||
"Patch": 2,
|
"Patch": 0,
|
||||||
"Build": 0
|
"Build": 0
|
||||||
},
|
},
|
||||||
"ProductVersion": {
|
"ProductVersion": {
|
||||||
"Major": 2,
|
"Major": 2,
|
||||||
"Minor": 6,
|
"Minor": 8,
|
||||||
"Patch": 2,
|
"Patch": 0,
|
||||||
"Build": 0
|
"Build": 0
|
||||||
},
|
},
|
||||||
"FileFlagsMask": "3f",
|
"FileFlagsMask": "3f",
|
||||||
@@ -22,14 +22,14 @@
|
|||||||
"Comments": "",
|
"Comments": "",
|
||||||
"CompanyName": "AmidaWare Inc",
|
"CompanyName": "AmidaWare Inc",
|
||||||
"FileDescription": "Tactical RMM Agent",
|
"FileDescription": "Tactical RMM Agent",
|
||||||
"FileVersion": "v2.6.2.0",
|
"FileVersion": "v2.8.0.0",
|
||||||
"InternalName": "tacticalrmm.exe",
|
"InternalName": "tacticalrmm.exe",
|
||||||
"LegalCopyright": "Copyright (c) 2023 AmidaWare Inc",
|
"LegalCopyright": "Copyright (c) 2024 AmidaWare Inc",
|
||||||
"LegalTrademarks": "",
|
"LegalTrademarks": "",
|
||||||
"OriginalFilename": "tacticalrmm.exe",
|
"OriginalFilename": "tacticalrmm.exe",
|
||||||
"PrivateBuild": "",
|
"PrivateBuild": "",
|
||||||
"ProductName": "Tactical RMM Agent",
|
"ProductName": "Tactical RMM Agent",
|
||||||
"ProductVersion": "v2.6.2.0",
|
"ProductVersion": "v2.8.0.0",
|
||||||
"SpecialBuild": ""
|
"SpecialBuild": ""
|
||||||
},
|
},
|
||||||
"VarFileInfo": {
|
"VarFileInfo": {
|
||||||
|
|||||||
Reference in New Issue
Block a user