// Package proto describes the wire messages shared by the server and the agent. // // All agent<->server traffic is plain JSON over HTTP(S) long-polling so it // survives NAT and restrictive egress firewalls: the agent only ever makes // outbound requests. package proto import "encoding/json" // Control poll message types (server -> agent, returned from /api/agent/poll). const ( // CtrlIdle is returned when the long-poll times out with nothing to do. CtrlIdle = "idle" // CtrlOpenTerminal tells the agent to spawn a PTY for the session id. CtrlOpenTerminal = "open_terminal" // CtrlOpenForward tells the agent to dial 127.0.0.1:Port and bridge it to // the session id (reverse TCP port-forward). CtrlOpenForward = "open_forward" // CtrlTask tells the agent to fetch and run the one-shot task TaskID. CtrlTask = "task" ) // EnrollRequest is sent once by a freshly installed agent. type EnrollRequest struct { Name string `json:"name"` Hostname string `json:"hostname"` OS string `json:"os"` Arch string `json:"arch"` Version string `json:"version"` } // EnrollResponse carries the identity the agent persists and uses from then on. type EnrollResponse struct { AgentID string `json:"agent_id"` Token string `json:"token"` } // ControlMessage is the body returned by the control long-poll. type ControlMessage struct { Type string `json:"type"` SessionID string `json:"session_id,omitempty"` Port int `json:"port,omitempty"` // CtrlOpenForward: client-side port to dial TaskID string `json:"task_id,omitempty"` // CtrlTask } // Terminal / stream frame types on the session "in" channel (server -> agent). // Reused for both PTY terminals and raw TCP port-forward streams. const ( FrameStdin = "stdin" // base64 bytes for the PTY / socket FrameResize = "resize" // PTY window size (terminal only) FrameClose = "close" // tear the stream down ) // InFrame is one element of the stream downstream batch (server -> agent). type InFrame struct { Type string `json:"type"` Data string `json:"data,omitempty"` // base64 bytes Cols uint16 `json:"cols,omitempty"` Rows uint16 `json:"rows,omitempty"` } // InBatch is the JSON body returned by GET /api/agent/term/{sid}/in. type InBatch struct { Frames []InFrame `json:"frames"` } // OutMessage is POSTed by the agent to /api/agent/term/{sid}/out. type OutMessage struct { Data string `json:"data,omitempty"` // base64 bytes Exit bool `json:"exit,omitempty"` } // --- one-shot tasks (file manager, native in the agent) --- const ( TaskFSList = "fs.list" // list a directory TaskFSRead = "fs.read" // read file content (for view/edit) TaskFSWrite = "fs.write" // write/overwrite file (edit save, create, upload) TaskFSMkdir = "fs.mkdir" // create directory TaskFSDelete = "fs.delete" // delete a single file or empty dir TaskFSDelTree = "fs.deltree" // recursively delete a directory TaskFSUnzip = "fs.unzip" // unzip an archive (needs `unzip` on the client) TaskFSZip = "fs.zip" // zip selected paths (native archive/zip) TaskFSMove = "fs.move" // move/rename TaskFSDownload = "fs.download" // read a whole file (larger cap) for browser download TaskSysUpdate = "sys.update" // download the latest agent binary and restart ) // TaskEnvelope is what the agent fetches for a task id. type TaskEnvelope struct { Type string `json:"type"` Args json.RawMessage `json:"args"` } // TaskResult is POSTed back by the agent. type TaskResult struct { OK bool `json:"ok"` Error string `json:"error,omitempty"` Data json.RawMessage `json:"data,omitempty"` } // fs task argument shapes. type FSPathArgs struct { Path string `json:"path"` } type FSWriteArgs struct { Path string `json:"path"` Data string `json:"data"` // base64 content } type FSUnzipArgs struct { Path string `json:"path"` Dest string `json:"dest"` } type FSZipArgs struct { Paths []string `json:"paths"` Dest string `json:"dest"` } type FSMoveArgs struct { Src string `json:"src"` Dst string `json:"dst"` } // FSEntry is one directory entry. type FSEntry struct { Name string `json:"name"` IsDir bool `json:"is_dir"` Size int64 `json:"size"` Mode string `json:"mode"` MTime int64 `json:"mtime"` } // FSListResult is returned for TaskFSList. type FSListResult struct { Path string `json:"path"` Entries []FSEntry `json:"entries"` } // FSReadResult is returned for TaskFSRead. type FSReadResult struct { Path string `json:"path"` Size int64 `json:"size"` Content string `json:"content"` // base64 Truncated bool `json:"truncated"` Binary bool `json:"binary"` }