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:
@@ -196,6 +196,26 @@ def test_collect_now_survives_a_policy_that_never_mentions_it():
|
||||
assert elevated_permission_for('collect_now') is None
|
||||
|
||||
|
||||
def test_collect_log_survives_a_policy_that_never_mentions_it():
|
||||
"""Log collection must not be narrowed away by an unrelated policy.
|
||||
|
||||
Same intersection trap as collect_now, but with a sharper failure: every
|
||||
existing policy predates this action and so cannot name it, meaning any
|
||||
endpoint carrying a policy refused log collection outright - including for
|
||||
an admin, who reads "requires permission" and goes looking at a grant they
|
||||
already hold. Logs are also what an operator reaches for when an endpoint
|
||||
is already misbehaving, so a policy gate here withholds the evidence
|
||||
exactly when it is wanted.
|
||||
"""
|
||||
from plugins.endpoints.commands import POLICY_EXEMPT_ACTIONS
|
||||
|
||||
assert 'collect_log' in POLICY_EXEMPT_ACTIONS
|
||||
# Exemption from POLICY is not exemption from PERMISSION. Unlike
|
||||
# collect_now this one DOES carry an elevated grant, so the assertion is
|
||||
# that the grant survived the exemption rather than being loosened by it.
|
||||
assert elevated_permission_for('collect_log') == 'endpoints.updateapp'
|
||||
|
||||
|
||||
def test_run_script_and_update_app_are_allowlisted_delivery_actions():
|
||||
"""The two software-delivery actions are allowlisted with a targetkind so
|
||||
the enqueue route accepts them and carries their subject on the wire:
|
||||
|
||||
Reference in New Issue
Block a user