mirror of https://github.com/wh1te909/rmmagent.git
168 lines
3.5 KiB
Go
168 lines
3.5 KiB
Go
package agent
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"math/rand"
|
|
"net"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
"time"
|
|
|
|
ps "github.com/elastic/go-sysinfo"
|
|
"github.com/go-resty/resty/v2"
|
|
"github.com/shirou/gopsutil/process"
|
|
)
|
|
|
|
var client = resty.New()
|
|
|
|
// APIRequest struct
|
|
type APIRequest struct {
|
|
URL string
|
|
Method string
|
|
Payload interface{}
|
|
Headers map[string]string
|
|
Timeout time.Duration
|
|
LocalCert string
|
|
Debug bool
|
|
}
|
|
|
|
// MakeRequest creates an api request to the RMM
|
|
func (r *APIRequest) MakeRequest() (*resty.Response, error) {
|
|
client.SetCloseConnection(true)
|
|
client.SetHeaders(r.Headers)
|
|
client.SetTimeout(r.Timeout * time.Second)
|
|
client.SetDebug(r.Debug)
|
|
|
|
if len(r.LocalCert) > 0 {
|
|
client.SetRootCertificate(r.LocalCert)
|
|
}
|
|
|
|
var resp *resty.Response
|
|
var err error
|
|
|
|
switch r.Method {
|
|
case "GET":
|
|
resp, err = client.R().Get(r.URL)
|
|
case "POST":
|
|
resp, err = client.R().SetBody(r.Payload).Post(r.URL)
|
|
case "PATCH":
|
|
resp, err = client.R().SetBody(r.Payload).Patch(r.URL)
|
|
case "PUT":
|
|
resp, err = client.R().SetBody(r.Payload).Put(r.URL)
|
|
}
|
|
|
|
if err != nil {
|
|
return &resty.Response{}, err
|
|
}
|
|
return resp, nil
|
|
}
|
|
|
|
// PublicIP returns the agent's public ip
|
|
// Tries 2 times before giving up
|
|
func PublicIP() string {
|
|
client.SetCloseConnection(true)
|
|
client.SetTimeout(7 * time.Second)
|
|
urls := []string{"https://ifconfig.co/ip", "https://icanhazip.com"}
|
|
|
|
for _, url := range urls {
|
|
r, err := client.R().Get(url)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
ip := StripAll(r.String())
|
|
if !IsValidIP(ip) {
|
|
continue
|
|
}
|
|
return ip
|
|
}
|
|
return "error"
|
|
}
|
|
|
|
// GenerateAgentID creates and returns a unique agent id
|
|
func GenerateAgentID(hostname string) string {
|
|
rand.Seed(time.Now().UnixNano())
|
|
letters := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
|
b := make([]rune, 35)
|
|
for i := range b {
|
|
b[i] = letters[rand.Intn(len(letters))]
|
|
}
|
|
return string(b) + "-" + hostname
|
|
}
|
|
|
|
// ShowVersionInfo prints basic debugging info
|
|
func ShowVersionInfo(ver string) {
|
|
fmt.Println("Tactical RMM Agent:", ver)
|
|
fmt.Println("Arch:", runtime.GOARCH)
|
|
fmt.Println("Go version:", runtime.Version())
|
|
if runtime.GOOS == "windows" {
|
|
fmt.Println("Program Directory:", filepath.Join(os.Getenv("ProgramFiles"), "TacticalAgent"))
|
|
}
|
|
}
|
|
|
|
// FileExists checks whether a file exists
|
|
func FileExists(path string) bool {
|
|
if _, err := os.Stat(path); err != nil {
|
|
if os.IsNotExist(err) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// TotalRAM returns total RAM in GB
|
|
func TotalRAM() float64 {
|
|
host, _ := ps.Host()
|
|
mem, _ := host.Memory()
|
|
return math.Ceil(float64(mem.Total) / 1073741824.0)
|
|
}
|
|
|
|
// BootTime returns system boot time as a unix timestamp
|
|
func BootTime() int64 {
|
|
host, _ := ps.Host()
|
|
info := host.Info()
|
|
return info.BootTime.Unix()
|
|
}
|
|
|
|
// IsValidIP checks for a valid ipv4 or ipv6
|
|
func IsValidIP(ip string) bool {
|
|
return net.ParseIP(ip) != nil
|
|
}
|
|
|
|
// StripAll strips all whitespace and newline chars
|
|
func StripAll(s string) string {
|
|
s = strings.TrimSpace(s)
|
|
s = strings.Trim(s, "\n")
|
|
s = strings.Trim(s, "\r")
|
|
return s
|
|
}
|
|
|
|
// KillProc kills a process and its children
|
|
func KillProc(pid int32) error {
|
|
p, err := process.NewProcess(pid)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
children, err := p.Children()
|
|
if err == nil {
|
|
for _, child := range children {
|
|
if err := child.Kill(); err != nil {
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
if err := p.Kill(); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// DjangoStringResp removes double quotes from django rest api resp
|
|
func DjangoStringResp(resp string) string {
|
|
return strings.Trim(resp, `"`)
|
|
}
|