Add log collection, script output capture, and timestamp fixes
Log Collector: a new collect_log action reads a plaintext log file from a known path and returns its tail for viewing and download. Rides the existing endpoints.updateapp grant rather than inventing one, since collecting a log is the same trust level as pushing an application. Collected logs land in their own table with per-asset retention of 20 instead of overloading the command audit row, and the agent refuses UNC, traversal, wildcards, directories and non-text content independently of the server check. collect_log is POLICY_EXEMPT. Every existing Configuration Policy predates the action and so cannot name it, and the intersection in ALLOWED_ACTIONS_FOR drops anything unnamed - so every policied endpoint refused log collection outright, including for admins, who saw a permission-shaped error for a grant they held. Exemption from policy is not exemption from permission: the elevated grant still applies, and a regression test asserts both halves so a future edit cannot quietly loosen the grant while "fixing" the policy gate. Script output capture: successful runs can return output, gated per script by captureoutput. Failures always returned it; success never did, which left a green badge as the only evidence a run produced. Timestamps: Activity and Operator Reports rendered date-only because the shared formatter's 'date' branch drops the clock time. Run Scripts additionally labels its timestamp, since a bare time meant "completed" on a terminal row but "queued" on an in-flight one - indistinguishable, and the wrong reading. Agent 1.16.0. Minor: collect_log is a new action name, so an older agent asked for it fails closed on the unknown-action default.
This commit is contained in:
@@ -231,6 +231,29 @@ export const endpointsApi = {
|
||||
listCommands(assetId) {
|
||||
return api.get(`/endpoints/${assetId}/commands`)
|
||||
},
|
||||
// Recent run_script commands only, with the agent-reported detail the plain
|
||||
// command list omits. Feeds the run history under the Run Scripts tab.
|
||||
listScriptRuns(assetId, limit = 5) {
|
||||
return api.get(`/endpoints/${assetId}/scriptruns`, { params: { limit } })
|
||||
},
|
||||
// Collected-log history for one endpoint. Metadata only - the log bodies are
|
||||
// fetched one at a time, because a 20-row history of multi-hundred-KB logs
|
||||
// would make opening the tab far more expensive than reading the one log the
|
||||
// operator actually wants.
|
||||
listLogCollections(assetId) {
|
||||
return api.get(`/endpoints/${assetId}/logcollections`)
|
||||
},
|
||||
// One collected log including its content, for the scrollable pane.
|
||||
getLogCollection(collectionId) {
|
||||
return api.get(`/endpoints/logcollections/${collectionId}`)
|
||||
},
|
||||
// Blob, not JSON: the server sends this as a text/plain attachment, and the
|
||||
// caller turns it into a save dialog.
|
||||
downloadLogCollection(collectionId) {
|
||||
return api.get(`/endpoints/logcollections/${collectionId}/download`, {
|
||||
responseType: 'blob',
|
||||
})
|
||||
},
|
||||
// Active break-glass holds. Readable by any endpoints.view holder, since a
|
||||
// suppressed action is drift an operator must be able to explain.
|
||||
listPolicyHolds(assetId) {
|
||||
|
||||
Reference in New Issue
Block a user