Add device agent library

Provide enrollment, elevated install, posture checks, keystore, and
system-tray helpers shared by the probo-agent binary.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
This commit is contained in:
Ludovic Vielle
2026-07-14 20:40:05 +02:00
parent e767dd8377
commit b442e1ed76
44 changed files with 2814 additions and 88 deletions

View File

@@ -58,32 +58,17 @@ func NewClient(serverURL, apiKey, userAgent string) *Client {
}
type (
EnrollRequest struct {
EnrollmentToken string `json:"enrollment_token"`
HardwareUUID string `json:"hardware_uuid"`
SerialNumber *string `json:"serial_number,omitempty"`
Hostname string `json:"hostname"`
Platform string `json:"platform"`
OSVersion string `json:"os_version"`
AgentVersion string `json:"agent_version"`
}
EnrollResponse struct {
DeviceID string `json:"device_id"`
APIKey string `json:"api_key"`
HeartbeatSeconds int `json:"heartbeat_interval_seconds"`
PostureSeconds int `json:"posture_interval_seconds"`
ServerTime string `json:"server_time"`
}
HeartbeatRequest struct {
AgentVersion string `json:"agent_version,omitempty"`
Hostname string `json:"hostname,omitempty"`
OSVersion string `json:"os_version,omitempty"`
UptimeSec int64 `json:"uptime_seconds,omitempty"`
HardwareUUID string `json:"hardware_uuid"`
SerialNumber *string `json:"serial_number,omitempty"`
Hostname string `json:"hostname"`
Platform string `json:"platform"`
OSVersion string `json:"os_version"`
AgentVersion string `json:"agent_version"`
}
HeartbeatResponse struct {
DeviceID string `json:"device_id"`
HeartbeatSeconds int `json:"heartbeat_interval_seconds"`
PostureSeconds int `json:"posture_interval_seconds"`
ServerTime string `json:"server_time"`
@@ -101,23 +86,6 @@ type (
}
)
// Enroll exchanges an enrollment token for a device key.
func (c *Client) Enroll(ctx context.Context, req EnrollRequest) (*EnrollResponse, error) {
var resp EnrollResponse
if err := c.do(
ctx,
http.MethodPost,
"/api/agent/v1/enroll",
false,
req,
&resp,
); err != nil {
return nil, err
}
return &resp, nil
}
// Heartbeat sends a periodic device heartbeat.
func (c *Client) Heartbeat(ctx context.Context, req HeartbeatRequest) (*HeartbeatResponse, error) {
var resp HeartbeatResponse
@@ -163,6 +131,35 @@ func (c *Client) Unenroll(ctx context.Context) error {
)
}
type enrollResponse struct {
APIKey string `json:"api_key"`
}
// ExchangeEnrollmentToken redeems a one-shot enrollment token for the
// permanent device API key.
func (c *Client) ExchangeEnrollmentToken(
ctx context.Context,
token string,
) (string, error) {
var resp enrollResponse
if err := c.do(
ctx,
http.MethodPost,
"/api/agent/v1/enroll",
false,
map[string]string{"token": token},
&resp,
); err != nil {
return "", err
}
if resp.APIKey == "" {
return "", errors.New("agent api: empty api key in enroll response")
}
return resp.APIKey, nil
}
// HTTPError captures a non-2xx API response.
type HTTPError struct {
StatusCode int