Repository navigation
feat(engine-mgmt): StarRocks query log - #849
Merged
Merged
Conversation
Design for package A of the StarRocks follow-ups: the AuditLoader setup, the loader user and Ranger guard, the read API and the Query log tab, with four open questions for the user. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ions Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ETURNING lists Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…icies A StarRocks profile bound to a provisioned engine now gets two IR-owned infrastructure statements, converged like the egret-admin set: - QueryLogLoader: egret_query_log may insert into default_catalog.starrocks_audit_db__.starrocks_audit_tbl__ (egret-query-log-loader); - QueryLogGuard: group public is denied every access on the audit database, one row per hierarchy under database (egret-query-log-guard - <chain>), with the loader's insert excepted on the table row. Engine admins are denied too (open question 2, (a)). The statements need only a bound non-external StarRocks engine, not a delegating one; AdminAllAccess keeps its own condition and Trino output is unchanged. The names are IR infra names and reserved on StarRocks profiles only. Convergence's row query and the boot pass's service list cover the new names and the non-delegating StarRocks profiles. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… test A provisioned StarRocks engine now brings the query-log loader and guard (managed_by = 'infra') onto its profile. The test counts the masks and the hidden-column deny the compiler writes for tagged columns, so it leaves the infra rows out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…only is_ir_infra_name ignored the service type, so a human policy named egret-query-log-loader on a Trino profile (a legal name there) was read by convergence and deleted, and the boot pass pulled the profile in for holding it. The predicate now takes the service type and owns the query-log shapes on starrocks profiles only, the same rule as the reservation. Convergence passes the profile's type; the boot pass reads it with the holding rows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The spec and the fork's measured audit-loader policy have no column level, and insert is a table-leaf access type in the StarRocks def. The guard render test now pins the table and column rows' deny accesses as literals, and the guard arm maps its store error with from_store. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Query log's audit plugin depends on both; an feConfig override must not switch plugins off or move the plugin directory. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ensure_query_log creates the audit database and table (the fork's audit-table.sql at d77446e), the egret_query_log loader user, the native grant on unbound engines and the AuditLoader plugin on egret.4+ images, idempotently. It runs from the post-Ready bootstrap behind its own checkpoint, after a StarRocks update or security upgrade that restarts the FE, and once at start for every provisioned StarRocks engine. The bootstrap's FE-ready and root-login loops move unchanged into wait_for_fe_root_login, shared with the spawned setup. StarRocksDdl gains query_with_header so SHOW PLUGINS is read by its Name column. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Just after an apply the old FE pod still answers, so the first setup can reach the pod that is being replaced: after an upgrade to egret.4 its INSTALL hits an official image without the plugin. spawn_query_log_setup, also used by the boot pass, now tries up to five times a minute apart, each behind the FE waits and checkpoints, and warns only after the last. An INSTALL answered with already-installed (an overlapping setup won) is Ready, not Failed. The update and security-upgrade spawns are now under test, the probe resend has a unit test, the scrub map uses the real secret id, and the taken-name test cannot leave its human behind. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add the four query-log routes on the engines router: the status read from the FE, a keyset-paged list, one entry with its whole statement, and the synchronous setup. Every read starts with the `/* egret-query-log-read */` marker, which the SQL uses to leave egret's own reads out, and carries only validated values through quote_string or instants egret formatted itself (UTC until the FE zone is measured). Statement text needs the new platform permission `engine:audit`, granted by migration 0218 to every platform role holding `engine:update`. Statements and FE errors are redacted of the root and loader passwords and of secret-shaped literals; FE errors leave only through FeError::scrubbed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 1 of the query-log reads:
- Without engine:audit, errorMessage is absent like statement: a
StarRocks error quotes the statement it rejects (user ruling,
2026-11-11, recorded in the spec and the plan).
- The user filter reads authorizedUser as authorized_name does: the
name up to the last '@'<host>', with '' read as one quote (user
ruling, 2026-11-11).
- A password the 2,000-character cut runs through no longer leaves its
prefix at the end of a preview.
- SET PASSWORD ... = PASSWORD('x') and SET PASSWORD = 'x' are redacted.
- A missing table on an FE that then stops answering is a 502 with the
scrubbed message, not a 409 carrying `unreachable`.
- Migration 0218's engine:audit grant has a DB test, and the DTO
comments say null where the field is null.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… FEs Add tests/query_log_live.rs, gated on EGRET_TEST_STARROCKS_URL (egret.4) and EGRET_TEST_STARROCKS_OFFICIAL_URL (official 4.1.7): Ready with events and no second INSTALL, the second-user and EXECUTE AS rows through the list read with the right authorizedUser, user filters, cursor paging, egret's own reads excluded, and PluginNotShipped with the table and user created on the official image. The live suite reaches the setup and the list read through a test-util entry point; the list route's page read is factored into read_page so the test runs the route's own code. Pin the FE texts measured in Task 5 in the unit tests and the fake, and record UTC as measured. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A provisioned StarRocks engine's detail page gets a Query log tab after Monitor (?tab=query-log; a Trino engine falls back to Overview). It shows the status line from /query-log/status (ready, notSetUp with Set up query log, pluginNotShipped naming Upgrade security, unreachable with Retry), filters kept in ?from=&to=&user=&state=, the statements newest first with Load more over nextCursor, and a side panel with one statement whole. Without engine:audit the statement and the error read "Hidden: needs engine:audit". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Show a delivered errorMessage even when the statement is absent; read text as withheld only when both are absent. - Filters and the opened statement push history, so Back walks them (FE-PAGE-2). - URL values the server would refuse (bad from/to, unknown state, a user over 128 characters) fall back to the defaults; "filtered" is read from the parsed values. - Name the row's open button, show Connected as in the panel only when it differs, and give an unknown status state a neutral line. - Load the tab lazily, which keeps it out of the entry chunk (the workflows bundle test marks its module by "Last 24 hours"). - Spec section 6 (en, vi): the notSetUp sentence and both pluginNotShipped variants. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…retry at bootstrap - plugin_step reads the SHOW PLUGINS Status column by header: only an AuditLoader row whose status is INSTALLED is installed. Any other row gets UNINSTALL PLUGIN then INSTALL on an image that ships the plugin, and is NotShipped elsewhere; the status route reads notSetUp. A header without Status keeps the old reading. - The step-6 probe and its poll start with the read marker, so the list and the newest event leave them out; the poll matches the probe's UUID without that exclusion, so it still finds it. - The bootstrap's failed first query-log setup gets the after-apply path's bounded retry (retry_query_log_setup, shared). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…keep the driver preamble out of the log
Two defects found by the live check on kind:
- The bootstrap's setup ran before any compute node had registered, so a
shared-data FE refused CREATE TABLE ("Number of available CN nodes is 0")
and a new engine stayed notSetUp. ensure_query_log now polls SHOW COMPUTE
NODES and SHOW BACKENDS (read-marked, Alive read by header) for up to
about 5 minutes before step 2; a timeout is a scrubbed Failed, so the
bounded retry still applies. The synchronous route checks once. The FE's
"available CN nodes is 0" answer is decided on the raw message and is
Failed, never terminal.
- Every root connection logged mysql_async's unmarked
SELECT @@max_allowed_packet,@@wait_timeout, which drove "Latest event".
The root opts now set both (StarRocks' session defaults), which makes the
vendored driver skip that query.
The spec records the facts measured on kind on 2026-11-11.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…river settings on user connections - The bootstrap now runs the query log setup (its checkpoint, the wait for an alive compute node, and step 6) after the delegation statements, so the node wait can never delay them. The checkpoints are renumbered in order (4-6 delegation, 7 query log); the security-integration checkpoint test now flips on the catalog CREATE again, and a new test pins checkpoint 7 on a delegating engine. Another shows every delegation statement is sent before the first node check while no node is alive. - StarRocksConnector sets max_allowed_packet and wait_timeout too, so user and delegated sessions no longer log the driver's SELECT @@max_allowed_packet,@@wait_timeout. The values live once in egret_query_api::starrocks_session, shared with the root connection. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…'s single check - an_engine_deleted_during_the_node_wait_gets_no_audit_ddl: the engine is flipped to deleting from the first node listing (new FakeStarRocksDdl::on_node_check hook); the post-wait checkpoint answers Failed and no audit DDL is sent. - the_setup_route_checks_once_for_a_node_and_does_not_wait (routes.rs, production bounds): with no node ever alive the route answers a 502 within 20 s after one node check. - Spec (en, vi): fact 2 and fact 3 say only what was measured, the own-reads paragraph covers user connections, vi section 7 matches en. - starrocks_session: note the one behaviour difference of a pinned max_allowed_packet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… rows Every StarRocks service now compiles egret-query-log-loader plus six egret-query-log-guard rows. A semantic comparison shows each fixture keeps every existing policy unchanged (ignoring the positional id) and gains only these seven rows per StarRocks service. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
StarRocks engines get a Query log. egret installs the AuditLoader plugin, which ships in the egret fork image at
/opt/egret/auditloader.zip, and it now loads every statement intostarrocks_audit_db__.starrocks_audit_tbl__, kept for 30 days. Engine detail gets a Query log tab that reads it.Design and plan:
docs/en/specs/2026-11-09-starrocks-audit-platform-design.md, including the rulings of 2026-11-10 and 2026-11-11 and the facts measured on kind;docs/en/plans/2026-11-09-starrocks-audit-platform.md.Changes
Setup (
query_log.rs)egret_query_log.engines.query_log_secret_id). The name is reserved in the username ledger.SHOW PLUGINSis read by header, and onlyStatus = INSTALLEDcounts as installed.setup_query_logs;POST /engines/{id}/query-log/setup.Ranger (IR infra)
egret-query-log-loaderallows onlyinserton the table.egret-query-log-guard - <chain>rows deny grouppublic, engine admins included, everything on the audit database. The one exception is the loader's insert.Read API
status, list, detail andsetup.quote_stringor as an egret-formatted value./* egret-query-log-read */and are excluded.Permission
engine:audit, required to seestatementanderrorMessage.engine:update.feConfigplugin_enableandplugin_dirare now refused.Driver
max_allowed_packetandwait_timeout. The driver therefore no longer sendsSELECT @@max_allowed_packet,@@wait_timeout, which used to show up in the log.Frontend
Test plan
Unit, DB and route tests
egret-engine-mgmtsuite: 626/626, with no DB skips.committed_openapi_json_is_current.npm run buildand the bundle tests. TheQueryLogTabtests pass 36/36.cargo clippy -D warnings --all-targetsandcargo fmt --checkare clean.ScheduleDetail"creates an alert through the real body shape" times out, and it fails the same way on main's tree.Live, against a real FE (
tests/query_log_live.rs, opt-inEGRET_TEST_STARROCKS_URL)Ready, and a second run installs nothing.EXECUTE ASrows show the rightauthorizedUser.pluginNotShipped, with the table and user created.Measured on a real FE
***for passwords inCREATE/ALTER USER,SET PASSWORDandINSTALL PLUGIN.SHOW PLUGINSheader was pinned.Fork e2e with egret's rendered loader and guard policies (egret.4)
eve, and a user with an all-access allow, are deniedSELECTandDROP TABLEon the audit table.Live on kind (in-cluster egret built from this branch, Ranger on)
readyon its own at Running, and delegation statements run firstEXECUTE AS(see below)INTERNAL_ERR; the audit row stores the error code onlyadminandmember-ssoare denied. Root is not subject to RangerINSTALLED(re-extracted from the image) and events resume. About 2 minutes of events are lost, so noplugin_dirmove is neededpluginNotShipped; ready 66 s after Upgrade securityKnown limit: StarRocks checks SELECT per column, so
SELECT count(*)on the audit table gets past the guard. The row count is visible; the contents are not. This is in the spec and the docs.Found on kind, outside this PR (follow-ups)
MYSQL_PWD, so it crash-loops once the initpwd Job has set root's password.Documentation
egret-data/docs#75 (Engine detail, Security, Permissions, Upgrade notes, REST API, screenshots).
Checklist
🤖 Generated with Claude Code