github.com/HXSecurity/DongTai-agent-go@v0.4.2/service/engine.go (about)

     1  package service
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/base64"
     6  	"encoding/json"
     7  	"fmt"
     8  	"os/exec"
     9  	"regexp"
    10  	"strconv"
    11  	"strings"
    12  	"time"
    13  
    14  	"github.com/HXSecurity/DongTai-agent-go/api"
    15  	"github.com/HXSecurity/DongTai-agent-go/global"
    16  	"github.com/HXSecurity/DongTai-agent-go/hook"
    17  	"github.com/HXSecurity/DongTai-agent-go/utils"
    18  	"net"
    19  	"os"
    20  	"runtime"
    21  
    22  	// "github.com/HXSecurity/DongTai-agent-go/api"
    23  	"github.com/HXSecurity/DongTai-agent-go/model/request"
    24  )
    25  
    26  var live bool
    27  
    28  func CreateCircuitBreaker() func() (err error) {
    29  	var count int
    30  	var circuit bool
    31  	return func() (err error) {
    32  		limit := api.Limit()
    33  		cpuLimit, ferr := strconv.ParseFloat(limit["cpu_limit"], 32)
    34  		if ferr != nil || cpuLimit == 0 {
    35  			cpuLimit = 100
    36  			return
    37  		}
    38  		s, err := getServerInfo()
    39  		var cpuNum float64
    40  		cpus := s.Cpu.Cpus
    41  		for _, k := range cpus {
    42  			cpuNum += k
    43  		}
    44  		cpu := cpuNum / float64(len(cpus))
    45  		if cpu > cpuLimit {
    46  			if count >= 5 {
    47  				circuit = true
    48  				count = 0
    49  				StopAgent()
    50  				return
    51  			}
    52  			count++
    53  		}
    54  		if cpu <= cpuLimit {
    55  			count = 0
    56  			if circuit {
    57  				RunAgent()
    58  			}
    59  		}
    60  		return nil
    61  	}
    62  }
    63  
    64  func StopAgent() {
    65  	live = false
    66  	hook.HookAll(global.AllHooks...)
    67  }
    68  
    69  func RunAgent() {
    70  	live = true
    71  	hook.UnHookAll(global.AllHooks...)
    72  }
    73  
    74  func AgentRegister() (err error) {
    75  	max := 6
    76  	breaker := CreateCircuitBreaker()
    77  	live = true
    78  	OS := runtime.GOOS
    79  	hostname, _ := os.Hostname()
    80  	version := "1.0.0"
    81  	packages, agentVersion := GetMod()
    82  	if global.Config.DongtaiGoProjectVersion != "" {
    83  		version = global.Config.DongtaiGoProjectVersion
    84  	}
    85  	projectName := "project Name"
    86  	if global.Config.DongtaiGoProjectVersion != "" {
    87  		projectName = global.Config.DongtaiGoProjectName
    88  	}
    89  	name := OS + "-" + hostname + "-" + version
    90  	interfaces, err := net.Interfaces()
    91  	if err != nil {
    92  		return
    93  	}
    94  
    95  	ips := ""
    96  
    97  	for _, i := range interfaces {
    98  		byName, err := net.InterfaceByName(i.Name)
    99  		if err != nil {
   100  			return err
   101  		}
   102  		addresses, err := byName.Addrs()
   103  		for _, v := range addresses {
   104  			if ips == "" {
   105  				ips = "{\"name\":" + byName.Name + ",\"ip\":" + v.String() + "}"
   106  			} else {
   107  				ips += ",{\"name\":" + byName.Name + ",\"ip\":" + v.String() + "}"
   108  			}
   109  		}
   110  	}
   111  	pid := os.Getpid()
   112  	envMap := make(map[string]string)
   113  	envs := os.Environ()
   114  	for _, v := range envs {
   115  		parts := strings.SplitN(v, "=", 2)
   116  		if len(parts) != 2 {
   117  			continue
   118  		} else {
   119  			envMap[parts[0]] = parts[1]
   120  		}
   121  	}
   122  	envB, err := json.Marshal(envMap)
   123  	if err != nil {
   124  		return err
   125  	}
   126  	encodeEnv := base64.StdEncoding.EncodeToString(envB)
   127  
   128  	filePath, err := getCurrentPath()
   129  	if err != nil {
   130  		return err
   131  	}
   132  	req := request.AgentRegisterReq{
   133  		AutoCreateProject: global.Config.DongtaiGoProjectCreate,
   134  		Name:              name,
   135  		Language:          "GO",
   136  		Version:           agentVersion,
   137  		ProjectVersion:    version,
   138  		ProjectName:       projectName,
   139  		Hostname:          hostname,
   140  		Network:           ips,
   141  		ContainerName:     "GO",
   142  		ContainerVersion:  "GO",
   143  		ServerAddr:        "",
   144  		ServerPort:        "",
   145  		ServerPath:        filePath,
   146  		ServerEnv:         encodeEnv,
   147  		Pid:               strconv.Itoa(pid),
   148  	}
   149  	go func() {
   150  		for {
   151  			max = max - 1
   152  			fmt.Printf("等待当前程序当前程序启动完成,剩余%d次", max)
   153  			time.Sleep(1 * time.Second)
   154  			ip, err := utils.ExternalIP()
   155  			if err != nil {
   156  				fmt.Println(err)
   157  			}
   158  			var cmd *exec.Cmd
   159  			var strErr bytes.Buffer
   160  			var out bytes.Buffer
   161  			if OS == "windows" {
   162  				cmd = exec.Command("netstat", "-ano")
   163  				cmd.Stderr = &strErr
   164  				cmd.Stdout = &out
   165  			} else {
   166  				cmd = exec.Command("netstat", "-antup", "|grep", req.Pid)
   167  				cmd.Stderr = &strErr
   168  				cmd.Stdout = &out
   169  			}
   170  			fmt.Println("等待当前程序端口返回")
   171  			err = cmd.Run()
   172  			fmt.Println("等待当前程序端口返回成功")
   173  			output := out.String()
   174  			if err != nil {
   175  				return
   176  			}
   177  			var matches [][]string
   178  			if OS == "windows" {
   179  				str := ""
   180  				for {
   181  					line, setErr := out.ReadBytes('\n')
   182  					if setErr != nil {
   183  						break
   184  					}
   185  					if strings.Index(string(line), " "+req.Pid) > -1 {
   186  						str += string(line) + "\n"
   187  					}
   188  				}
   189  				r := regexp.MustCompile(`0.0.0.0:\s*(.*?)\s* `)
   190  				matches = r.FindAllStringSubmatch(str, -1)
   191  			} else {
   192  				r := regexp.MustCompile(`:::\s*(.*?)\s* `)
   193  				matches = r.FindAllStringSubmatch(output, -1)
   194  			}
   195  			if matches != nil || max == 0 {
   196  				if matches[0] != nil || max == 0 {
   197  					if matches[0][1] != "" || max == 0 {
   198  						fmt.Println("当前程序启动完成")
   199  						if max == 0 {
   200  							req.ServerPort = ""
   201  						} else {
   202  							req.ServerPort = matches[0][1]
   203  						}
   204  						req.ServerAddr = ip.String()
   205  						agentId, err := api.AgentRegister(req)
   206  						if err != nil {
   207  							fmt.Println(err)
   208  							break
   209  						}
   210  						global.AgentId = agentId
   211  						UploadSca(packages)
   212  						go func() {
   213  							for {
   214  								time.Sleep(10 * time.Second)
   215  								PingPang()
   216  								breaker()
   217  							}
   218  						}()
   219  						break
   220  					}
   221  				}
   222  			}
   223  
   224  		}
   225  	}()
   226  	return nil
   227  }
   228  
   229  func PingPang() {
   230  	s, err := getServerInfo()
   231  	if err != nil {
   232  		return
   233  	}
   234  	var req request.UploadReq
   235  	cpuMap := make(map[string]string)
   236  	memoryMap := make(map[string]string)
   237  	var cpus float64 = 0
   238  	for _, v := range s.Cpu.Cpus {
   239  		cpus += v
   240  	}
   241  	cpuRate := fmt.Sprintf("%.2f", cpus/float64(len(s.Cpu.Cpus)))
   242  	memoryRate := fmt.Sprintf("%.2f", float64(s.Rrm.UsedMB)/float64(s.Rrm.TotalMB))
   243  	total := strconv.Itoa(s.Rrm.TotalMB) + "MB"
   244  	use := strconv.Itoa(s.Rrm.UsedMB) + "MB"
   245  	cpuMap["rate"] = cpuRate
   246  	memoryMap["total"] = total
   247  	memoryMap["use"] = use
   248  	memoryMap["rate"] = memoryRate
   249  	cpuByte, _ := json.Marshal(cpuMap)
   250  	memoryByte, _ := json.Marshal(memoryMap)
   251  
   252  	req.Type = 1
   253  	req.Detail.Pant.Disk = "{}"
   254  	req.Detail.Pant.Cpu = string(cpuByte)
   255  	req.Detail.Pant.Memory = string(memoryByte)
   256  	req.Detail.Pant.IsCoreRunning = 1
   257  	req.Detail.Pant.IsCoreInstalled = 1
   258  	req.Detail.AgentId = global.AgentId
   259  	api.ReportUpload(req)
   260  }
   261  func UploadSca(packages []request.Component) {
   262  	var req request.UploadReq
   263  	req.Type = 18
   264  	req.Detail.AgentId = global.AgentId
   265  	req.Detail.Packages = packages
   266  	api.ReportUpload(req)
   267  }