cynfo3000 8116b71b48 feat: Windows Agent v1.0.0
- Windows-Dienst (golang.org/x/sys/windows/svc)
- Collector: CPU (GetSystemTimes), RAM (GlobalMemoryStatusEx), Disks (GetDiskFreeSpaceEx)
- WS-Client: gleiche Verbindungslogik wie Linux/BSD Agent
- Commands: exec, winget list/install/upgrade/upgrade-all, Windows Updates check/install, reboot
- install.ps1: automatische Service-Installation mit Parametern
- make agent-windows VERSION=x.x.x
2026-03-10 01:22:19 +01:00

103 lines
2.7 KiB
Go

package client
import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
)
type Client struct {
baseURL string
apiKey string
httpClient *http.Client
}
func New(baseURL, apiKey string, insecure bool) *Client {
return &Client{
baseURL: baseURL,
apiKey: apiKey,
httpClient: &http.Client{
Timeout: 30 * time.Second,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: insecure},
},
},
}
}
type RegisterRequest struct {
AgentID string `json:"agent_id,omitempty"`
Name string `json:"name"`
Hostname string `json:"hostname"`
IP string `json:"ip"`
AgentVersion string `json:"agent_version,omitempty"`
Platform string `json:"platform"`
}
type RegisterResponse struct {
ID string `json:"id"`
Message string `json:"message"`
}
func (c *Client) Register(req RegisterRequest) (string, error) {
body, _ := json.Marshal(req)
resp, err := c.doRequest("POST", "/api/v1/agent/register", body)
if err != nil {
return "", err
}
defer resp.Body.Close()
data, _ := io.ReadAll(resp.Body)
if resp.StatusCode != http.StatusCreated && resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("Registrierung fehlgeschlagen (HTTP %d): %s", resp.StatusCode, string(data))
}
var r RegisterResponse
if err := json.Unmarshal(data, &r); err != nil {
return "", fmt.Errorf("JSON Parse: %v", err)
}
return r.ID, nil
}
type HeartbeatRequest struct {
AgentID string `json:"agent_id"`
AgentVersion string `json:"agent_version,omitempty"`
Platform string `json:"platform"`
SystemData json.RawMessage `json:"system_data,omitempty"`
}
type HeartbeatResponse struct {
Message string `json:"message"`
UpdateAvailable bool `json:"update_available"`
UpdateVersion string `json:"update_version,omitempty"`
UpdateHash string `json:"update_hash,omitempty"`
}
func (c *Client) Heartbeat(req HeartbeatRequest) (*HeartbeatResponse, error) {
body, _ := json.Marshal(req)
resp, err := c.doRequest("POST", "/api/v1/agent/heartbeat", body)
if err != nil {
return nil, err
}
defer resp.Body.Close()
data, _ := io.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("Heartbeat fehlgeschlagen (HTTP %d): %s", resp.StatusCode, string(data))
}
var r HeartbeatResponse
json.Unmarshal(data, &r)
return &r, nil
}
func (c *Client) doRequest(method, path string, body []byte) (*http.Response, error) {
req, err := http.NewRequest(method, c.baseURL+path, bytes.NewReader(body))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", c.apiKey)
return c.httpClient.Do(req)
}