RFDs/0012

Operational queries

State
published
Authors
Darwin D Wu
Discussion
renga-dcim/renga#149
Labels
rengaagentcontrol-planesecuritysoftware
Implemented
0%Checklist

Goal

Let operators ask a host a specific, read-only question on demand, such as "what is listening on this host" or "which services are failed", and get a typed answer without shell access. RFD 1 requires operational queries to be typed, read-only collector operations and never an alias for arbitrary shell execution. This RFD defines them on RFD 9's jobs.

What a query is

A query is an RFD 9 capability in the observe class named query.<name>@<version>. Its definition fixes:

  • a parameter schema, validated by Renga before the job is stored and again by the agent before it runs;

  • a result schema and a maximum result size;

  • a timeout;

  • a sensitivity: inventory (no more revealing than an observation) or sensitive (reveals software versions, running services, or other detail an attacker would value).

The agent implements each query natively, through procfs, netlink, or systemd’s D-Bus interface. Where a query must run a program, the argument vector is fixed in the agent’s code and never includes text from the request. There is no query that takes a command, a path to execute, or a script.

First queries

Capability Answers Sensitivity

query.listening_sockets@1

Listening TCP and UDP sockets with their process names

sensitive

query.services@1

systemd units and their active, failed, and enabled states

sensitive

query.disk_usage@1

Filesystem capacity and use, beyond the inventory snapshot

inventory

query.routes@1

The routing table per routing domain

inventory

query.time_sync@1

Clock synchronization source, offset, and status

inventory

query.packages@1

Installed packages and versions, bounded and filterable by name

sensitive

These are the prefilled options every host offers with no extra software. They stay native so a plain installation answers the common questions.

osquery backend

Renga does not grow a bespoke query language. For anything beyond the named queries, hosts run osquery, which already models hundreds of tables across Linux, macOS, and Windows.

The agent never runs osquery itself. It talks to a locally managed osqueryd over osquery’s extensions socket, which the operator makes reachable by the agent’s account. osquery keeps its own privileges, the agent’s sandbox does not change, and the agent reports the backend’s status (available, not_permitted, not_present) on the Collectors page like any other source.

When the backend is available, named queries may be answered by fixed SQL that ships with the agent’s version. For example, query.packages@1 reads osquery’s package tables. The result still matches the query’s own schema, and the native implementation is used whenever osquery is absent.

Ad hoc SQL

query.sql@1 runs an operator-written osquery SELECT and is the one query whose text comes from the request. Free-form SQL is not typed in the RFD 1 sense, because some osquery tables read arbitrary files (file, yara, augeas), make network requests (curl, curl_certificate), or copy files off the host (carves). It is therefore bounded differently from the named queries:

  • It is always sensitive, off by default in both the organization and the agent’s [jobs] policy, and limited to owners and admins.

  • Dangerous tables are excluded by osquery itself through its disable_tables flag, not by parsing SQL in Renga or the agent. Before each run the agent reads the daemon’s flags and refuses with a policy reason unless every table on the agent’s deny list is disabled.

  • Results are a bounded table: column names and string values, with row and byte limits and the same timeout as other queries.

The UI offers query.sql@1 only on hosts whose agent reports the backend available, and otherwise explains that installing osquery unlocks it.

Authorization

Queries are off until an organization enables them, and each can be enabled separately. Owners and admins may run enabled queries. An organization may also let members run inventory-sensitivity queries; sensitive queries stay with owners and admins. The agent’s [jobs] policy must also enable each query; the agent default enables only inventory queries.

Sensitivity also governs reading retained parameters, output, results, and events, not just requesting execution. Every job/detail/event endpoint, recent history, batch table, and export checks the reader’s current organization and sensitivity authorization. Sensitive payloads remain owner/admin-only even if a member can see generic job history; inventory results follow the current organization member-query policy. Having requested a job grants no permanent read access after authorization is revoked. Activity exposes only authorized summaries, never sensitive parameters or results through a generic feed.

Results

A query’s result is its job’s final event, bounded by the query’s maximum size and kept for the job retention period. Results are not observations: they never change canonical inventory, freshness, or findings. A question worth answering continuously belongs in the collector’s regular payload, not in a scheduled query.

Fan-out is a first-class use: running query.listening_sockets@1 across a saved view answers "which hosts listen on port 23" as one batch whose results appear as a table.

Decisions from review

  • The agent enables the inventory-sensitivity queries by default, as RFD 9 does for observe capabilities; sensitive queries need an explicit [jobs] entry.

  • query.packages@1 ships in the first set as a sensitive query, so fleet-wide version questions are answerable by owners and admins.

  • Named queries stay native as prefilled options; full query capability comes from osquery, which operators install and run themselves.

  • Ad hoc osquery SQL is a separate sensitive, off-by-default query, with dangerous tables disabled in osquery itself.

User interaction

  • A resource’s Queries tab lists the queries its agent offers, runs one, and shows recent results with who ran them. Where the agent reports osquery available, it also offers an SQL editor for query.sql@1.

  • From a saved view, "Run query" fans out to every matching host and shows the batch’s results as they arrive.

  • Every run appears in activity with an authorized summary; parameters and results are visible only through sensitivity-authorized views.

Later

A natural-language interface may later sit on top of these queries as an LLM integration that drafts a named query or osquery SQL for the operator to review before it runs. It would add no new execution path and is left to its own RFD.

Rollout

  1. Define the query capability shape, the sensitivity rule, and the organization settings.

  2. Implement the first queries in the agent behind [jobs] policy.

  3. Add the Queries tab and fan-out from saved views.

  4. Add the osquery backend, osquery-backed named queries, and query.sql@1.

Implementation

Progress is tracked in the implementation checklist.