splitting install - adding mesh support
This commit is contained in:
parent
b21bd64663
commit
f5e2e01986
5 changed files with 734 additions and 230 deletions
|
|
@ -478,8 +478,52 @@ func (a *Agent) GetWinUpdates() {}
|
||||||
|
|
||||||
func (a *Agent) InstallUpdates(guids []string) {}
|
func (a *Agent) InstallUpdates(guids []string) {}
|
||||||
|
|
||||||
func (a *Agent) installMesh(meshbin, exe, proxy string) (string, error) {
|
func (a *Agent) installMesh(meshbin, bin, proxy string) (string, error) {
|
||||||
return "not implemented", nil
|
var meshNodeID string
|
||||||
|
meshInstallArgs := []string{"-fullinstall"}
|
||||||
|
if len(proxy) > 0 {
|
||||||
|
meshProxy := fmt.Sprintf("--WebProxy=%s", proxy)
|
||||||
|
meshInstallArgs = append(meshInstallArgs, meshProxy)
|
||||||
|
}
|
||||||
|
a.Logger.Debugln("Mesh install args:", meshInstallArgs)
|
||||||
|
|
||||||
|
meshOut, meshErr := CMD(meshbin, meshInstallArgs, int(90), false)
|
||||||
|
if meshErr != nil {
|
||||||
|
fmt.Println(meshOut[0])
|
||||||
|
fmt.Println(meshOut[1])
|
||||||
|
fmt.Println(meshErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(meshOut)
|
||||||
|
a.Logger.Debugln("Sleeping for 5")
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
|
meshSuccess := false
|
||||||
|
|
||||||
|
for !meshSuccess {
|
||||||
|
a.Logger.Debugln("Getting mesh node id")
|
||||||
|
pMesh, pErr := CMD(bin, []string{"-nodeid"}, int(30), false)
|
||||||
|
if pErr != nil {
|
||||||
|
a.Logger.Errorln(pErr)
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if pMesh[1] != "" {
|
||||||
|
a.Logger.Errorln(pMesh[1])
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
meshNodeID = StripAll(pMesh[0])
|
||||||
|
a.Logger.Debugln("Node id:", meshNodeID)
|
||||||
|
if strings.Contains(strings.ToLower(meshNodeID), "not defined") {
|
||||||
|
a.Logger.Errorln(meshNodeID)
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
meshSuccess = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return meshNodeID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CMDShell(shell string, cmdArgs []string, command string, timeout int, detached bool) (output [2]string, e error) {
|
func CMDShell(shell string, cmdArgs []string, command string, timeout int, detached bool) (output [2]string, e error) {
|
||||||
|
|
|
||||||
228
agent/install.go
228
agent/install.go
|
|
@ -12,19 +12,9 @@ https://license.tacticalrmm.com
|
||||||
package agent
|
package agent
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
|
||||||
"runtime"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-resty/resty/v2"
|
|
||||||
trmm "github.com/wh1te909/trmm-shared"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Installer struct {
|
type Installer struct {
|
||||||
|
|
@ -49,225 +39,7 @@ type Installer struct {
|
||||||
MeshNodeID string
|
MeshNodeID string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) Install(i *Installer) {
|
|
||||||
a.checkExistingAndRemove(i.Silent)
|
|
||||||
|
|
||||||
i.Headers = map[string]string{
|
|
||||||
"content-type": "application/json",
|
|
||||||
"Authorization": fmt.Sprintf("Token %s", i.Token),
|
|
||||||
}
|
|
||||||
a.AgentID = GenerateAgentID()
|
|
||||||
a.Logger.Debugln("Agent ID:", a.AgentID)
|
|
||||||
|
|
||||||
u, err := url.Parse(i.RMM)
|
|
||||||
if err != nil {
|
|
||||||
a.installerMsg(err.Error(), "error", i.Silent)
|
|
||||||
}
|
|
||||||
|
|
||||||
if u.Scheme != "https" && u.Scheme != "http" {
|
|
||||||
a.installerMsg("Invalid URL (must contain https or http)", "error", i.Silent)
|
|
||||||
}
|
|
||||||
|
|
||||||
// will match either ipv4 , or ipv4:port
|
|
||||||
var ipPort = regexp.MustCompile(`[0-9]+(?:\.[0-9]+){3}(:[0-9]+)?`)
|
|
||||||
|
|
||||||
// if ipv4:port, strip the port to get ip for salt master
|
|
||||||
if ipPort.MatchString(u.Host) && strings.Contains(u.Host, ":") {
|
|
||||||
i.SaltMaster = strings.Split(u.Host, ":")[0]
|
|
||||||
} else if strings.Contains(u.Host, ":") {
|
|
||||||
i.SaltMaster = strings.Split(u.Host, ":")[0]
|
|
||||||
} else {
|
|
||||||
i.SaltMaster = u.Host
|
|
||||||
}
|
|
||||||
|
|
||||||
a.Logger.Debugln("API:", i.SaltMaster)
|
|
||||||
|
|
||||||
terr := TestTCP(fmt.Sprintf("%s:4222", i.SaltMaster))
|
|
||||||
if terr != nil {
|
|
||||||
a.installerMsg(fmt.Sprintf("ERROR: Either port 4222 TCP is not open on your RMM, or nats.service is not running.\n\n%s", terr.Error()), "error", i.Silent)
|
|
||||||
}
|
|
||||||
|
|
||||||
baseURL := u.Scheme + "://" + u.Host
|
|
||||||
a.Logger.Debugln("Base URL:", baseURL)
|
|
||||||
|
|
||||||
iClient := resty.New()
|
|
||||||
iClient.SetCloseConnection(true)
|
|
||||||
iClient.SetTimeout(15 * time.Second)
|
|
||||||
iClient.SetDebug(a.Debug)
|
|
||||||
iClient.SetHeaders(i.Headers)
|
|
||||||
|
|
||||||
// set proxy if applicable
|
|
||||||
if len(i.Proxy) > 0 {
|
|
||||||
a.Logger.Infoln("Using proxy:", i.Proxy)
|
|
||||||
iClient.SetProxy(i.Proxy)
|
|
||||||
}
|
|
||||||
|
|
||||||
creds, cerr := iClient.R().Get(fmt.Sprintf("%s/api/v3/installer/", baseURL))
|
|
||||||
if cerr != nil {
|
|
||||||
a.installerMsg(cerr.Error(), "error", i.Silent)
|
|
||||||
}
|
|
||||||
if creds.StatusCode() == 401 {
|
|
||||||
a.installerMsg("Installer token has expired. Please generate a new one.", "error", i.Silent)
|
|
||||||
}
|
|
||||||
|
|
||||||
verPayload := map[string]string{"version": a.Version}
|
|
||||||
iVersion, ierr := iClient.R().SetBody(verPayload).Post(fmt.Sprintf("%s/api/v3/installer/", baseURL))
|
|
||||||
if ierr != nil {
|
|
||||||
a.installerMsg(ierr.Error(), "error", i.Silent)
|
|
||||||
}
|
|
||||||
if iVersion.StatusCode() != 200 {
|
|
||||||
a.installerMsg(DjangoStringResp(iVersion.String()), "error", i.Silent)
|
|
||||||
}
|
|
||||||
|
|
||||||
rClient := resty.New()
|
|
||||||
rClient.SetCloseConnection(true)
|
|
||||||
rClient.SetTimeout(i.Timeout * time.Second)
|
|
||||||
rClient.SetDebug(a.Debug)
|
|
||||||
// set rest knox headers
|
|
||||||
rClient.SetHeaders(i.Headers)
|
|
||||||
|
|
||||||
// set local cert if applicable
|
|
||||||
if len(i.Cert) > 0 {
|
|
||||||
if !trmm.FileExists(i.Cert) {
|
|
||||||
a.installerMsg(fmt.Sprintf("%s does not exist", i.Cert), "error", i.Silent)
|
|
||||||
}
|
|
||||||
rClient.SetRootCertificate(i.Cert)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(i.Proxy) > 0 {
|
|
||||||
rClient.SetProxy(i.Proxy)
|
|
||||||
}
|
|
||||||
|
|
||||||
var installerMeshSystemEXE string
|
|
||||||
if len(i.MeshDir) > 0 {
|
|
||||||
installerMeshSystemEXE = filepath.Join(i.MeshDir, "MeshAgent.exe")
|
|
||||||
} else {
|
|
||||||
installerMeshSystemEXE = a.MeshSystemBin
|
|
||||||
}
|
|
||||||
|
|
||||||
var meshNodeID string
|
|
||||||
|
|
||||||
if runtime.GOOS == "windows" && !i.NoMesh {
|
|
||||||
mesh := filepath.Join(a.ProgramDir, a.MeshInstaller)
|
|
||||||
if i.LocalMesh == "" {
|
|
||||||
a.Logger.Infoln("Downloading mesh agent...")
|
|
||||||
payload := map[string]string{"goarch": a.GoArch, "plat": a.Platform}
|
|
||||||
r, err := rClient.R().SetBody(payload).SetOutput(mesh).Post(fmt.Sprintf("%s/api/v3/meshexe/", baseURL))
|
|
||||||
if err != nil {
|
|
||||||
a.installerMsg(fmt.Sprintf("Failed to download mesh agent: %s", err.Error()), "error", i.Silent)
|
|
||||||
}
|
|
||||||
if r.StatusCode() != 200 {
|
|
||||||
a.installerMsg(fmt.Sprintf("Unable to download the mesh agent from the RMM. %s", r.String()), "error", i.Silent)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err := copyFile(i.LocalMesh, mesh)
|
|
||||||
if err != nil {
|
|
||||||
a.installerMsg(err.Error(), "error", i.Silent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
a.Logger.Infoln("Installing mesh agent...")
|
|
||||||
a.Logger.Debugln("Mesh agent:", mesh)
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
|
|
||||||
meshNodeID, err = a.installMesh(mesh, installerMeshSystemEXE, i.Proxy)
|
|
||||||
if err != nil {
|
|
||||||
a.installerMsg(fmt.Sprintf("Failed to install mesh agent: %s", err.Error()), "error", i.Silent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(i.MeshNodeID) > 0 {
|
|
||||||
meshNodeID = i.MeshNodeID
|
|
||||||
}
|
|
||||||
|
|
||||||
a.Logger.Infoln("Adding agent to dashboard")
|
|
||||||
// add agent
|
|
||||||
type NewAgentResp struct {
|
|
||||||
AgentPK int `json:"pk"`
|
|
||||||
Token string `json:"token"`
|
|
||||||
}
|
|
||||||
agentPayload := map[string]interface{}{
|
|
||||||
"agent_id": a.AgentID,
|
|
||||||
"hostname": a.Hostname,
|
|
||||||
"site": i.SiteID,
|
|
||||||
"monitoring_type": i.AgentType,
|
|
||||||
"mesh_node_id": meshNodeID,
|
|
||||||
"description": i.Description,
|
|
||||||
"goarch": a.GoArch,
|
|
||||||
"plat": a.Platform,
|
|
||||||
}
|
|
||||||
|
|
||||||
r, err := rClient.R().SetBody(agentPayload).SetResult(&NewAgentResp{}).Post(fmt.Sprintf("%s/api/v3/newagent/", baseURL))
|
|
||||||
if err != nil {
|
|
||||||
a.installerMsg(err.Error(), "error", i.Silent)
|
|
||||||
}
|
|
||||||
if r.StatusCode() != 200 {
|
|
||||||
a.installerMsg(r.String(), "error", i.Silent)
|
|
||||||
}
|
|
||||||
|
|
||||||
agentPK := r.Result().(*NewAgentResp).AgentPK
|
|
||||||
agentToken := r.Result().(*NewAgentResp).Token
|
|
||||||
|
|
||||||
a.Logger.Debugln("Agent token:", agentToken)
|
|
||||||
a.Logger.Debugln("Agent PK:", agentPK)
|
|
||||||
|
|
||||||
createAgentConfig(baseURL, a.AgentID, i.SaltMaster, agentToken, strconv.Itoa(agentPK), i.Cert, i.Proxy, i.MeshDir)
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
// refresh our agent with new values
|
|
||||||
a = New(a.Logger, a.Version)
|
|
||||||
a.Logger.Debugf("%+v\n", a)
|
|
||||||
|
|
||||||
// set new headers, no longer knox auth...use agent auth
|
|
||||||
rClient.SetHeaders(a.Headers)
|
|
||||||
|
|
||||||
time.Sleep(3 * time.Second)
|
|
||||||
// check in once
|
|
||||||
a.DoNatsCheckIn()
|
|
||||||
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
// send software api
|
|
||||||
a.SendSoftware()
|
|
||||||
|
|
||||||
a.Logger.Debugln("Creating temp dir")
|
|
||||||
a.CreateTRMMTempDir()
|
|
||||||
|
|
||||||
a.Logger.Debugln("Disabling automatic windows updates")
|
|
||||||
a.PatchMgmnt(true)
|
|
||||||
|
|
||||||
a.Logger.Infoln("Installing service...")
|
|
||||||
err := a.InstallService()
|
|
||||||
if err != nil {
|
|
||||||
a.installerMsg(err.Error(), "error", i.Silent)
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
a.Logger.Infoln("Starting service...")
|
|
||||||
out := a.ControlService(winSvcName, "start")
|
|
||||||
if !out.Success {
|
|
||||||
a.installerMsg(out.ErrorMsg, "error", i.Silent)
|
|
||||||
}
|
|
||||||
|
|
||||||
a.Logger.Infoln("Adding windows defender exclusions")
|
|
||||||
a.addDefenderExlusions()
|
|
||||||
|
|
||||||
if i.Power {
|
|
||||||
a.Logger.Infoln("Disabling sleep/hibernate...")
|
|
||||||
DisableSleepHibernate()
|
|
||||||
}
|
|
||||||
|
|
||||||
if i.Ping {
|
|
||||||
a.Logger.Infoln("Enabling ping...")
|
|
||||||
EnablePing()
|
|
||||||
}
|
|
||||||
|
|
||||||
if i.RDP {
|
|
||||||
a.Logger.Infoln("Enabling RDP...")
|
|
||||||
EnableRDP()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
a.installerMsg("Installation was successfull!\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 {
|
||||||
in, err := os.Open(src)
|
in, err := os.Open(src)
|
||||||
|
|
|
||||||
276
agent/install_darwin.go
Normal file
276
agent/install_darwin.go
Normal file
|
|
@ -0,0 +1,276 @@
|
||||||
|
//go:build !windows
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/url"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-resty/resty/v2"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
trmm "github.com/wh1te909/trmm-shared"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
etcConfig = "/etc/tacticalagent"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *Agent) Install(i *Installer) {
|
||||||
|
a.checkExistingAndRemove(i.Silent)
|
||||||
|
i.Headers = map[string]string{
|
||||||
|
"content-type": "application/json",
|
||||||
|
"Authorization": fmt.Sprintf("Token %s", i.Token),
|
||||||
|
}
|
||||||
|
|
||||||
|
a.AgentID = GenerateAgentID()
|
||||||
|
a.Logger.Debugln("Agent ID:", a.AgentID)
|
||||||
|
u, err := url.Parse(i.RMM)
|
||||||
|
if err != nil {
|
||||||
|
a.installerMsg(err.Error(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
if u.Scheme != "https" && u.Scheme != "http" {
|
||||||
|
a.installerMsg("Invalid URL (must contain https or http)", "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
// will match either ipv4 , or ipv4:port
|
||||||
|
var ipPort = regexp.MustCompile(`[0-9]+(?:\.[0-9]+){3}(:[0-9]+)?`)
|
||||||
|
// if ipv4:port, strip the port to get ip for salt master
|
||||||
|
if ipPort.MatchString(u.Host) && strings.Contains(u.Host, ":") {
|
||||||
|
i.SaltMaster = strings.Split(u.Host, ":")[0]
|
||||||
|
} else if strings.Contains(u.Host, ":") {
|
||||||
|
i.SaltMaster = strings.Split(u.Host, ":")[0]
|
||||||
|
} else {
|
||||||
|
i.SaltMaster = u.Host
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Logger.Debugln("API:", i.SaltMaster)
|
||||||
|
terr := TestTCP(fmt.Sprintf("%s:4222", i.SaltMaster))
|
||||||
|
if terr != nil {
|
||||||
|
a.installerMsg(fmt.Sprintf("ERROR: Either port 4222 TCP is not open on your RMM, or nats.service is not running.\n\n%s", terr.Error()), "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
baseURL := u.Scheme + "://" + u.Host
|
||||||
|
a.Logger.Debugln("Base URL:", baseURL)
|
||||||
|
|
||||||
|
iClient := resty.New()
|
||||||
|
iClient.SetCloseConnection(true)
|
||||||
|
iClient.SetTimeout(15 * time.Second)
|
||||||
|
iClient.SetDebug(a.Debug)
|
||||||
|
iClient.SetHeaders(i.Headers)
|
||||||
|
|
||||||
|
// set proxy if applicable
|
||||||
|
if len(i.Proxy) > 0 {
|
||||||
|
a.Logger.Infoln("Using proxy:", i.Proxy)
|
||||||
|
iClient.SetProxy(i.Proxy)
|
||||||
|
}
|
||||||
|
|
||||||
|
creds, cerr := iClient.R().Get(fmt.Sprintf("%s/api/v3/installer/", baseURL))
|
||||||
|
if cerr != nil {
|
||||||
|
a.installerMsg(cerr.Error(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
if creds.StatusCode() == 401 {
|
||||||
|
a.installerMsg("Installer token has expired. Please generate a new one.", "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
verPayload := map[string]string{"version": a.Version}
|
||||||
|
iVersion, ierr := iClient.R().SetBody(verPayload).Post(fmt.Sprintf("%s/api/v3/installer/", baseURL))
|
||||||
|
if ierr != nil {
|
||||||
|
a.installerMsg(ierr.Error(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
if iVersion.StatusCode() != 200 {
|
||||||
|
a.installerMsg(DjangoStringResp(iVersion.String()), "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
rClient := resty.New()
|
||||||
|
rClient.SetCloseConnection(true)
|
||||||
|
rClient.SetTimeout(i.Timeout * time.Second)
|
||||||
|
rClient.SetDebug(a.Debug)
|
||||||
|
// set rest knox headers
|
||||||
|
rClient.SetHeaders(i.Headers)
|
||||||
|
|
||||||
|
// set local cert if applicable
|
||||||
|
if len(i.Cert) > 0 {
|
||||||
|
if !trmm.FileExists(i.Cert) {
|
||||||
|
a.installerMsg(fmt.Sprintf("%s does not exist", i.Cert), "error", i.Silent)
|
||||||
|
}
|
||||||
|
rClient.SetRootCertificate(i.Cert)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(i.Proxy) > 0 {
|
||||||
|
rClient.SetProxy(i.Proxy)
|
||||||
|
}
|
||||||
|
|
||||||
|
var installerMeshSystemEXE string
|
||||||
|
if len(i.MeshDir) > 0 {
|
||||||
|
installerMeshSystemEXE = filepath.Join(i.MeshDir, "MeshAgent.exe")
|
||||||
|
} else {
|
||||||
|
installerMeshSystemEXE = a.MeshSystemBin
|
||||||
|
}
|
||||||
|
|
||||||
|
var meshNodeID string
|
||||||
|
|
||||||
|
if runtime.GOOS == "windows" && !i.NoMesh {
|
||||||
|
mesh := filepath.Join(a.ProgramDir, a.MeshInstaller)
|
||||||
|
if i.LocalMesh == "" {
|
||||||
|
a.Logger.Infoln("Downloading mesh agent...")
|
||||||
|
payload := map[string]string{"goarch": a.GoArch, "plat": a.Platform}
|
||||||
|
r, err := rClient.R().SetBody(payload).SetOutput(mesh).Post(fmt.Sprintf("%s/api/v3/meshexe/", baseURL))
|
||||||
|
if err != nil {
|
||||||
|
a.installerMsg(fmt.Sprintf("Failed to download mesh agent: %s", err.Error()), "error", i.Silent)
|
||||||
|
}
|
||||||
|
if r.StatusCode() != 200 {
|
||||||
|
a.installerMsg(fmt.Sprintf("Unable to download the mesh agent from the RMM. %s", r.String()), "error", i.Silent)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err := copyFile(i.LocalMesh, mesh)
|
||||||
|
if err != nil {
|
||||||
|
a.installerMsg(err.Error(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Logger.Infoln("Installing mesh agent...")
|
||||||
|
a.Logger.Debugln("Mesh agent:", mesh)
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
|
||||||
|
meshNodeID, err = a.installMesh(mesh, installerMeshSystemEXE, i.Proxy)
|
||||||
|
if err != nil {
|
||||||
|
a.installerMsg(fmt.Sprintf("Failed to install mesh agent: %s", err.Error()), "error", i.Silent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(i.MeshNodeID) > 0 {
|
||||||
|
meshNodeID = i.MeshNodeID
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Logger.Infoln("Adding agent to dashboard")
|
||||||
|
// add agent
|
||||||
|
type NewAgentResp struct {
|
||||||
|
AgentPK int `json:"pk"`
|
||||||
|
Token string `json:"token"`
|
||||||
|
}
|
||||||
|
agentPayload := map[string]interface{}{
|
||||||
|
"agent_id": a.AgentID,
|
||||||
|
"hostname": a.Hostname,
|
||||||
|
"site": i.SiteID,
|
||||||
|
"monitoring_type": i.AgentType,
|
||||||
|
"mesh_node_id": meshNodeID,
|
||||||
|
"description": i.Description,
|
||||||
|
"goarch": a.GoArch,
|
||||||
|
"plat": a.Platform,
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := rClient.R().SetBody(agentPayload).SetResult(&NewAgentResp{}).Post(fmt.Sprintf("%s/api/v3/newagent/", baseURL))
|
||||||
|
if err != nil {
|
||||||
|
a.installerMsg(err.Error(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
if r.StatusCode() != 200 {
|
||||||
|
a.installerMsg(r.String(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
agentPK := r.Result().(*NewAgentResp).AgentPK
|
||||||
|
agentToken := r.Result().(*NewAgentResp).Token
|
||||||
|
|
||||||
|
a.Logger.Debugln("Agent token:", agentToken)
|
||||||
|
a.Logger.Debugln("Agent PK:", agentPK)
|
||||||
|
|
||||||
|
createAgentConfig(baseURL, a.AgentID, i.SaltMaster, agentToken, strconv.Itoa(agentPK), i.Cert, i.Proxy, i.MeshDir)
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
// refresh our agent with new values
|
||||||
|
a = New(a.Logger, a.Version)
|
||||||
|
a.Logger.Debugf("%+v\n", a)
|
||||||
|
|
||||||
|
// set new headers, no longer knox auth...use agent auth
|
||||||
|
rClient.SetHeaders(a.Headers)
|
||||||
|
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
// check in once
|
||||||
|
a.DoNatsCheckIn()
|
||||||
|
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
// send software api
|
||||||
|
a.SendSoftware()
|
||||||
|
|
||||||
|
a.Logger.Debugln("Creating temp dir")
|
||||||
|
a.CreateTRMMTempDir()
|
||||||
|
|
||||||
|
a.Logger.Debugln("Disabling automatic windows updates")
|
||||||
|
a.PatchMgmnt(true)
|
||||||
|
|
||||||
|
a.Logger.Infoln("Installing service...")
|
||||||
|
err := a.InstallService()
|
||||||
|
if err != nil {
|
||||||
|
a.installerMsg(err.Error(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
a.Logger.Infoln("Starting service...")
|
||||||
|
out := a.ControlService(winSvcName, "start")
|
||||||
|
if !out.Success {
|
||||||
|
a.installerMsg(out.ErrorMsg, "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Logger.Infoln("Adding windows defender exclusions")
|
||||||
|
a.addDefenderExlusions()
|
||||||
|
|
||||||
|
if i.Power {
|
||||||
|
a.Logger.Infoln("Disabling sleep/hibernate...")
|
||||||
|
DisableSleepHibernate()
|
||||||
|
}
|
||||||
|
|
||||||
|
if i.Ping {
|
||||||
|
a.Logger.Infoln("Enabling ping...")
|
||||||
|
EnablePing()
|
||||||
|
}
|
||||||
|
|
||||||
|
if i.RDP {
|
||||||
|
a.Logger.Infoln("Enabling RDP...")
|
||||||
|
EnableRDP()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a.installerMsg("Installation was successfull!\nAllow a few minutes for the agent to properly display in the RMM", "info", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Agent) checkExistingAndRemove(silent bool) {}
|
||||||
|
|
||||||
|
func (a *Agent) installerMsg(msg, alert string, silent bool) {
|
||||||
|
if alert == "error" {
|
||||||
|
a.Logger.Fatalln(msg)
|
||||||
|
} else {
|
||||||
|
a.Logger.Info(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createAgentConfig(baseurl, agentid, apiurl, token, agentpk, cert, proxy, meshdir string) {
|
||||||
|
viper.SetConfigType("json")
|
||||||
|
viper.Set("baseurl", baseurl)
|
||||||
|
viper.Set("agentid", agentid)
|
||||||
|
viper.Set("apiurl", apiurl)
|
||||||
|
viper.Set("token", token)
|
||||||
|
viper.Set("agentpk", agentpk)
|
||||||
|
viper.Set("cert", cert)
|
||||||
|
viper.Set("proxy", proxy)
|
||||||
|
viper.Set("meshdir", meshdir)
|
||||||
|
viper.SetConfigPermissions(0660)
|
||||||
|
err := viper.SafeWriteConfigAs(etcConfig)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("createAgentConfig", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Agent) addDefenderExlusions() {}
|
||||||
|
|
||||||
|
func DisableSleepHibernate() {}
|
||||||
|
|
||||||
|
func EnablePing() {}
|
||||||
|
|
||||||
|
func EnableRDP() {}
|
||||||
|
|
@ -15,14 +15,210 @@ https://license.tacticalrmm.com
|
||||||
package agent
|
package agent
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"net/url"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-resty/resty/v2"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
trmm "github.com/wh1te909/trmm-shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
etcConfig = "/etc/tacticalagent"
|
etcConfig = "/etc/tacticalagent"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (a *Agent) Install(i *Installer) {
|
||||||
|
a.checkExistingAndRemove(i.Silent)
|
||||||
|
|
||||||
|
i.Headers = map[string]string{
|
||||||
|
"content-type": "application/json",
|
||||||
|
"Authorization": fmt.Sprintf("Token %s", i.Token),
|
||||||
|
}
|
||||||
|
a.AgentID = GenerateAgentID()
|
||||||
|
a.Logger.Debugln("Agent ID:", a.AgentID)
|
||||||
|
|
||||||
|
u, err := url.Parse(i.RMM)
|
||||||
|
if err != nil {
|
||||||
|
a.installerMsg(err.Error(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
if u.Scheme != "https" && u.Scheme != "http" {
|
||||||
|
a.installerMsg("Invalid URL (must contain https or http)", "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
// will match either ipv4 , or ipv4:port
|
||||||
|
var ipPort = regexp.MustCompile(`[0-9]+(?:\.[0-9]+){3}(:[0-9]+)?`)
|
||||||
|
|
||||||
|
// if ipv4:port, strip the port to get ip for salt master
|
||||||
|
if ipPort.MatchString(u.Host) && strings.Contains(u.Host, ":") {
|
||||||
|
i.SaltMaster = strings.Split(u.Host, ":")[0]
|
||||||
|
} else if strings.Contains(u.Host, ":") {
|
||||||
|
i.SaltMaster = strings.Split(u.Host, ":")[0]
|
||||||
|
} else {
|
||||||
|
i.SaltMaster = u.Host
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Logger.Debugln("API:", i.SaltMaster)
|
||||||
|
|
||||||
|
terr := TestTCP(fmt.Sprintf("%s:4222", i.SaltMaster))
|
||||||
|
if terr != nil {
|
||||||
|
a.installerMsg(fmt.Sprintf("ERROR: Either port 4222 TCP is not open on your RMM, or nats.service is not running.\n\n%s", terr.Error()), "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
baseURL := u.Scheme + "://" + u.Host
|
||||||
|
a.Logger.Debugln("Base URL:", baseURL)
|
||||||
|
|
||||||
|
iClient := resty.New()
|
||||||
|
iClient.SetCloseConnection(true)
|
||||||
|
iClient.SetTimeout(15 * time.Second)
|
||||||
|
iClient.SetDebug(a.Debug)
|
||||||
|
iClient.SetHeaders(i.Headers)
|
||||||
|
|
||||||
|
// set proxy if applicable
|
||||||
|
if len(i.Proxy) > 0 {
|
||||||
|
a.Logger.Infoln("Using proxy:", i.Proxy)
|
||||||
|
iClient.SetProxy(i.Proxy)
|
||||||
|
}
|
||||||
|
|
||||||
|
creds, cerr := iClient.R().Get(fmt.Sprintf("%s/api/v3/installer/", baseURL))
|
||||||
|
if cerr != nil {
|
||||||
|
a.installerMsg(cerr.Error(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
if creds.StatusCode() == 401 {
|
||||||
|
a.installerMsg("Installer token has expired. Please generate a new one.", "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
verPayload := map[string]string{"version": a.Version}
|
||||||
|
iVersion, ierr := iClient.R().SetBody(verPayload).Post(fmt.Sprintf("%s/api/v3/installer/", baseURL))
|
||||||
|
if ierr != nil {
|
||||||
|
a.installerMsg(ierr.Error(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
if iVersion.StatusCode() != 200 {
|
||||||
|
a.installerMsg(DjangoStringResp(iVersion.String()), "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
rClient := resty.New()
|
||||||
|
rClient.SetCloseConnection(true)
|
||||||
|
rClient.SetTimeout(i.Timeout * time.Second)
|
||||||
|
rClient.SetDebug(a.Debug)
|
||||||
|
// set rest knox headers
|
||||||
|
rClient.SetHeaders(i.Headers)
|
||||||
|
|
||||||
|
// set local cert if applicable
|
||||||
|
if len(i.Cert) > 0 {
|
||||||
|
if !trmm.FileExists(i.Cert) {
|
||||||
|
a.installerMsg(fmt.Sprintf("%s does not exist", i.Cert), "error", i.Silent)
|
||||||
|
}
|
||||||
|
rClient.SetRootCertificate(i.Cert)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(i.Proxy) > 0 {
|
||||||
|
rClient.SetProxy(i.Proxy)
|
||||||
|
}
|
||||||
|
|
||||||
|
var installerMeshSystemBin string
|
||||||
|
if len(i.MeshDir) > 0 {
|
||||||
|
installerMeshSystemBin = filepath.Join(i.MeshDir, "meshagent")
|
||||||
|
} else {
|
||||||
|
installerMeshSystemBin = a.MeshSystemBin
|
||||||
|
}
|
||||||
|
|
||||||
|
var meshNodeID string
|
||||||
|
mesh := a.MeshSystemBin
|
||||||
|
if i.LocalMesh == "" {
|
||||||
|
a.Logger.Infoln("Downloading mesh agent...")
|
||||||
|
payload := map[string]string{"goarch": a.GoArch, "plat": a.Platform}
|
||||||
|
r, err := rClient.R().SetBody(payload).SetOutput(mesh).Post(fmt.Sprintf("%s/api/v3/meshexe/", baseURL))
|
||||||
|
if err != nil {
|
||||||
|
a.installerMsg(fmt.Sprintf("Failed to download mesh agent: %s", err.Error()), "error", i.Silent)
|
||||||
|
}
|
||||||
|
if r.StatusCode() != 200 {
|
||||||
|
a.installerMsg(fmt.Sprintf("Unable to download the mesh agent from the RMM. %s", r.String()), "error", i.Silent)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err := copyFile(i.LocalMesh, mesh)
|
||||||
|
if err != nil {
|
||||||
|
a.installerMsg(err.Error(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Logger.Infoln("Installing mesh agent...")
|
||||||
|
a.Logger.Debugln("Mesh agent:", mesh)
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
meshNodeID, err = a.installMesh(mesh, installerMeshSystemBin, i.Proxy)
|
||||||
|
if err != nil {
|
||||||
|
a.installerMsg(fmt.Sprintf("Failed to install mesh agent: %s", err.Error()), "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(i.MeshNodeID) > 0 {
|
||||||
|
meshNodeID = i.MeshNodeID
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Logger.Infoln("Adding agent to dashboard")
|
||||||
|
// add agent
|
||||||
|
type NewAgentResp struct {
|
||||||
|
AgentPK int `json:"pk"`
|
||||||
|
Token string `json:"token"`
|
||||||
|
}
|
||||||
|
agentPayload := map[string]interface{}{
|
||||||
|
"agent_id": a.AgentID,
|
||||||
|
"hostname": a.Hostname,
|
||||||
|
"site": i.SiteID,
|
||||||
|
"monitoring_type": i.AgentType,
|
||||||
|
"mesh_node_id": meshNodeID,
|
||||||
|
"description": i.Description,
|
||||||
|
"goarch": a.GoArch,
|
||||||
|
"plat": a.Platform,
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := rClient.R().SetBody(agentPayload).SetResult(&NewAgentResp{}).Post(fmt.Sprintf("%s/api/v3/newagent/", baseURL))
|
||||||
|
if err != nil {
|
||||||
|
a.installerMsg(err.Error(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
if r.StatusCode() != 200 {
|
||||||
|
a.installerMsg(r.String(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
agentPK := r.Result().(*NewAgentResp).AgentPK
|
||||||
|
agentToken := r.Result().(*NewAgentResp).Token
|
||||||
|
a.Logger.Debugln("Agent token:", agentToken)
|
||||||
|
a.Logger.Debugln("Agent PK:", agentPK)
|
||||||
|
createAgentConfig(baseURL, a.AgentID, i.SaltMaster, agentToken, strconv.Itoa(agentPK), i.Cert, i.Proxy, i.MeshDir)
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
// refresh our agent with new values
|
||||||
|
a = New(a.Logger, a.Version)
|
||||||
|
a.Logger.Debugf("%+v\n", a)
|
||||||
|
// set new headers, no longer knox auth...use agent auth
|
||||||
|
rClient.SetHeaders(a.Headers)
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
// check in once
|
||||||
|
a.DoNatsCheckIn()
|
||||||
|
// send software api
|
||||||
|
a.SendSoftware()
|
||||||
|
a.Logger.Debugln("Creating temp dir")
|
||||||
|
a.CreateTRMMTempDir()
|
||||||
|
a.Logger.Infoln("Installing service...")
|
||||||
|
err = a.InstallService()
|
||||||
|
if err != nil {
|
||||||
|
a.installerMsg(err.Error(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
a.Logger.Infoln("Starting service...")
|
||||||
|
out := a.ControlService(winSvcName, "start")
|
||||||
|
if !out.Success {
|
||||||
|
a.installerMsg(out.ErrorMsg, "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
a.installerMsg("Installation was successfull!\nAllow a few minutes for the agent to properly display in the RMM", "info", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *Agent) checkExistingAndRemove(silent bool) {}
|
func (a *Agent) checkExistingAndRemove(silent bool) {}
|
||||||
|
|
||||||
func (a *Agent) installerMsg(msg, alert string, silent bool) {
|
func (a *Agent) installerMsg(msg, alert string, silent bool) {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,222 @@ import (
|
||||||
"golang.org/x/sys/windows/registry"
|
"golang.org/x/sys/windows/registry"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (a *Agent) Install(i *Installer) {
|
||||||
|
a.checkExistingAndRemove(i.Silent)
|
||||||
|
|
||||||
|
i.Headers = map[string]string{
|
||||||
|
"content-type": "application/json",
|
||||||
|
"Authorization": fmt.Sprintf("Token %s", i.Token),
|
||||||
|
}
|
||||||
|
a.AgentID = GenerateAgentID()
|
||||||
|
a.Logger.Debugln("Agent ID:", a.AgentID)
|
||||||
|
|
||||||
|
u, err := url.Parse(i.RMM)
|
||||||
|
if err != nil {
|
||||||
|
a.installerMsg(err.Error(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
if u.Scheme != "https" && u.Scheme != "http" {
|
||||||
|
a.installerMsg("Invalid URL (must contain https or http)", "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
// will match either ipv4 , or ipv4:port
|
||||||
|
var ipPort = regexp.MustCompile(`[0-9]+(?:\.[0-9]+){3}(:[0-9]+)?`)
|
||||||
|
|
||||||
|
// if ipv4:port, strip the port to get ip for salt master
|
||||||
|
if ipPort.MatchString(u.Host) && strings.Contains(u.Host, ":") {
|
||||||
|
i.SaltMaster = strings.Split(u.Host, ":")[0]
|
||||||
|
} else if strings.Contains(u.Host, ":") {
|
||||||
|
i.SaltMaster = strings.Split(u.Host, ":")[0]
|
||||||
|
} else {
|
||||||
|
i.SaltMaster = u.Host
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Logger.Debugln("API:", i.SaltMaster)
|
||||||
|
|
||||||
|
terr := TestTCP(fmt.Sprintf("%s:4222", i.SaltMaster))
|
||||||
|
if terr != nil {
|
||||||
|
a.installerMsg(fmt.Sprintf("ERROR: Either port 4222 TCP is not open on your RMM, or nats.service is not running.\n\n%s", terr.Error()), "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
baseURL := u.Scheme + "://" + u.Host
|
||||||
|
a.Logger.Debugln("Base URL:", baseURL)
|
||||||
|
|
||||||
|
iClient := resty.New()
|
||||||
|
iClient.SetCloseConnection(true)
|
||||||
|
iClient.SetTimeout(15 * time.Second)
|
||||||
|
iClient.SetDebug(a.Debug)
|
||||||
|
iClient.SetHeaders(i.Headers)
|
||||||
|
|
||||||
|
// set proxy if applicable
|
||||||
|
if len(i.Proxy) > 0 {
|
||||||
|
a.Logger.Infoln("Using proxy:", i.Proxy)
|
||||||
|
iClient.SetProxy(i.Proxy)
|
||||||
|
}
|
||||||
|
|
||||||
|
creds, cerr := iClient.R().Get(fmt.Sprintf("%s/api/v3/installer/", baseURL))
|
||||||
|
if cerr != nil {
|
||||||
|
a.installerMsg(cerr.Error(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
if creds.StatusCode() == 401 {
|
||||||
|
a.installerMsg("Installer token has expired. Please generate a new one.", "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
verPayload := map[string]string{"version": a.Version}
|
||||||
|
iVersion, ierr := iClient.R().SetBody(verPayload).Post(fmt.Sprintf("%s/api/v3/installer/", baseURL))
|
||||||
|
if ierr != nil {
|
||||||
|
a.installerMsg(ierr.Error(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
if iVersion.StatusCode() != 200 {
|
||||||
|
a.installerMsg(DjangoStringResp(iVersion.String()), "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
rClient := resty.New()
|
||||||
|
rClient.SetCloseConnection(true)
|
||||||
|
rClient.SetTimeout(i.Timeout * time.Second)
|
||||||
|
rClient.SetDebug(a.Debug)
|
||||||
|
// set rest knox headers
|
||||||
|
rClient.SetHeaders(i.Headers)
|
||||||
|
|
||||||
|
// set local cert if applicable
|
||||||
|
if len(i.Cert) > 0 {
|
||||||
|
if !trmm.FileExists(i.Cert) {
|
||||||
|
a.installerMsg(fmt.Sprintf("%s does not exist", i.Cert), "error", i.Silent)
|
||||||
|
}
|
||||||
|
rClient.SetRootCertificate(i.Cert)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(i.Proxy) > 0 {
|
||||||
|
rClient.SetProxy(i.Proxy)
|
||||||
|
}
|
||||||
|
|
||||||
|
var installerMeshSystemEXE string
|
||||||
|
if len(i.MeshDir) > 0 {
|
||||||
|
installerMeshSystemEXE = filepath.Join(i.MeshDir, "MeshAgent.exe")
|
||||||
|
} else {
|
||||||
|
installerMeshSystemEXE = a.MeshSystemBin
|
||||||
|
}
|
||||||
|
|
||||||
|
var meshNodeID string
|
||||||
|
|
||||||
|
mesh := filepath.Join(a.ProgramDir, a.MeshInstaller)
|
||||||
|
if i.LocalMesh == "" {
|
||||||
|
a.Logger.Infoln("Downloading mesh agent...")
|
||||||
|
payload := map[string]string{"goarch": a.GoArch, "plat": a.Platform}
|
||||||
|
r, err := rClient.R().SetBody(payload).SetOutput(mesh).Post(fmt.Sprintf("%s/api/v3/meshexe/", baseURL))
|
||||||
|
if err != nil {
|
||||||
|
a.installerMsg(fmt.Sprintf("Failed to download mesh agent: %s", err.Error()), "error", i.Silent)
|
||||||
|
}
|
||||||
|
if r.StatusCode() != 200 {
|
||||||
|
a.installerMsg(fmt.Sprintf("Unable to download the mesh agent from the RMM. %s", r.String()), "error", i.Silent)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err := copyFile(i.LocalMesh, mesh)
|
||||||
|
if err != nil {
|
||||||
|
a.installerMsg(err.Error(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Logger.Infoln("Installing mesh agent...")
|
||||||
|
a.Logger.Debugln("Mesh agent:", mesh)
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
|
||||||
|
meshNodeID, err = a.installMesh(mesh, installerMeshSystemEXE, i.Proxy)
|
||||||
|
if err != nil {
|
||||||
|
a.installerMsg(fmt.Sprintf("Failed to install mesh agent: %s", err.Error()), "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(i.MeshNodeID) > 0 {
|
||||||
|
meshNodeID = i.MeshNodeID
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Logger.Infoln("Adding agent to dashboard")
|
||||||
|
// add agent
|
||||||
|
type NewAgentResp struct {
|
||||||
|
AgentPK int `json:"pk"`
|
||||||
|
Token string `json:"token"`
|
||||||
|
}
|
||||||
|
agentPayload := map[string]interface{}{
|
||||||
|
"agent_id": a.AgentID,
|
||||||
|
"hostname": a.Hostname,
|
||||||
|
"site": i.SiteID,
|
||||||
|
"monitoring_type": i.AgentType,
|
||||||
|
"mesh_node_id": meshNodeID,
|
||||||
|
"description": i.Description,
|
||||||
|
"goarch": a.GoArch,
|
||||||
|
"plat": a.Platform,
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := rClient.R().SetBody(agentPayload).SetResult(&NewAgentResp{}).Post(fmt.Sprintf("%s/api/v3/newagent/", baseURL))
|
||||||
|
if err != nil {
|
||||||
|
a.installerMsg(err.Error(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
if r.StatusCode() != 200 {
|
||||||
|
a.installerMsg(r.String(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
agentPK := r.Result().(*NewAgentResp).AgentPK
|
||||||
|
agentToken := r.Result().(*NewAgentResp).Token
|
||||||
|
|
||||||
|
a.Logger.Debugln("Agent token:", agentToken)
|
||||||
|
a.Logger.Debugln("Agent PK:", agentPK)
|
||||||
|
|
||||||
|
createAgentConfig(baseURL, a.AgentID, i.SaltMaster, agentToken, strconv.Itoa(agentPK), i.Cert, i.Proxy, i.MeshDir)
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
// refresh our agent with new values
|
||||||
|
a = New(a.Logger, a.Version)
|
||||||
|
a.Logger.Debugf("%+v\n", a)
|
||||||
|
|
||||||
|
// set new headers, no longer knox auth...use agent auth
|
||||||
|
rClient.SetHeaders(a.Headers)
|
||||||
|
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
// check in once
|
||||||
|
a.DoNatsCheckIn()
|
||||||
|
|
||||||
|
// send software api
|
||||||
|
a.SendSoftware()
|
||||||
|
|
||||||
|
a.Logger.Debugln("Creating temp dir")
|
||||||
|
a.CreateTRMMTempDir()
|
||||||
|
|
||||||
|
a.Logger.Debugln("Disabling automatic windows updates")
|
||||||
|
a.PatchMgmnt(true)
|
||||||
|
|
||||||
|
a.Logger.Infoln("Installing service...")
|
||||||
|
err := a.InstallService()
|
||||||
|
if err != nil {
|
||||||
|
a.installerMsg(err.Error(), "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
a.Logger.Infoln("Starting service...")
|
||||||
|
out := a.ControlService(winSvcName, "start")
|
||||||
|
if !out.Success {
|
||||||
|
a.installerMsg(out.ErrorMsg, "error", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Logger.Infoln("Adding windows defender exclusions")
|
||||||
|
a.addDefenderExlusions()
|
||||||
|
|
||||||
|
if i.Power {
|
||||||
|
a.Logger.Infoln("Disabling sleep/hibernate...")
|
||||||
|
DisableSleepHibernate()
|
||||||
|
}
|
||||||
|
|
||||||
|
if i.Ping {
|
||||||
|
a.Logger.Infoln("Enabling ping...")
|
||||||
|
EnablePing()
|
||||||
|
}
|
||||||
|
|
||||||
|
if i.RDP {
|
||||||
|
a.Logger.Infoln("Enabling RDP...")
|
||||||
|
EnableRDP()
|
||||||
|
}
|
||||||
|
|
||||||
|
a.installerMsg("Installation was successfull!\nAllow a few minutes for the agent to properly display in the RMM", "info", i.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
func createAgentConfig(baseurl, agentid, apiurl, token, agentpk, cert, proxy, meshdir string) {
|
func createAgentConfig(baseurl, agentid, apiurl, token, agentpk, cert, proxy, meshdir string) {
|
||||||
k, _, err := registry.CreateKey(registry.LOCAL_MACHINE, `SOFTWARE\TacticalRMM`, registry.ALL_ACCESS)
|
k, _, err := registry.CreateKey(registry.LOCAL_MACHINE, `SOFTWARE\TacticalRMM`, registry.ALL_ACCESS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue