Repository navigation
Add active ACL inspection functions - #37
Merged
Merged
Conversation
glasstiger
commented
Oct 21, 2026
glasstiger
left a comment
Contributor
Author
There was a problem hiding this comment.
Review
No blocking issues. Ready to merge.
Verified
- Correct category. In questdb/questdb-enterprise#1222 (merged), both functions take no arguments and both factories return
isCursor() == true(ActiveGrantsFunctionFactoryextendsActivePermissionsFunctionFactory).functions()reports cursor factories asCURSOR, so theCURSORsection is right. Alphabetical order holds (active_grants<active_permissions<all_permissions). Both are registered automatically by the package scan inEntCairoEngine. - No grammar changes needed. Parse,
toSqlround-trip andformatall work forFROM active_permissions()andFROM active_grants(), including aliases, JOINs, CTEs andWHERE grant_option. - Autocomplete in the right places only. Suggested after FROM, JOIN (including ASOF and CROSS), a comma join, inside CTEs and subqueries, EXPLAIN,
INSERT … SELECTandCREATE TABLE … AS (SELECT …). Not suggested in the SELECT list or WHERE. - The tests are meaningful.
- The positive test (
FROM act|) fails with thefunctions.tschange reverted. - The negative test (
SELECT act|) passes either way, but it's a real guard: about 255 function suggestions come back atSELECT actwithout prefix filtering, so moving these two into the scalar, aggregate or window lists would fail it.
- The positive test (
- Docs examples work. Every new SQL example in questdb/documentation#566 parses, round-trips and formats idempotently, so adding them to the fixtures later won't break anything. The only exception is the syntax-notation line
permissions([entityName]), which isn't SQL. - Local checks.
yarn test(15,106 passed),yarn typecheck,yarn lintandprettier --checkare clean. The branch is up to date withmaster.
Optional nits
- The new tests sit in
"Regression scenarios (bugs that motivated this plan)". That matches the neighbouringgen|andlong|tests, but these aren't really regressions. Fine as is. - Once questdb/documentation#566 merges, consider adding
SELECT * FROM active_permissions()andSELECT * FROM active_grants()totests/fixtures/docs-queries.json, next toall_permissions(). - The PR description still lists questdb/questdb-enterprise#1222 as a dependency, but it has merged. Only the docs PR is still open, and it doesn't block this one.
Out of scope
reload_tick_calendars() (Enterprise, questdb/questdb-enterprise#883) is missing from scalarFunctions. This gap predates this PR and could be a small follow-up.
puzpuzpuz
self-requested a review
October 21, 2026 17:00
puzpuzpuz
approved these changes
Oct 21, 2026
Merged
javier
pushed a commit
to questdb/documentation
that referenced
this pull request
Oct 26, 2026
## Summary Documents the changes from [questdb/questdb-enterprise#1222](questdb/questdb-enterprise#1222) and its OSS tandem [questdb/questdb#7631](questdb/questdb#7631), shipped in QuestDB Enterprise 4.1.0: - New `active_permissions()` and `active_grants()` ACL table functions. - Enterprise administrative functions are rejected in materialized view and live view queries. - A read-only replica's access-list refresh is bounded to 30 seconds and fails closed. ## Access control functions page New reference page, [Access control functions](https://preview-566--questdb-documentation.netlify.app/docs/query/functions/access-control/) (`query/functions/access-control.md`), added to the Functions sidebar. It covers all four Enterprise ACL table functions: | Function | Returns | Required permissions | | --- | --- | --- | | `active_grants()` (new in 4.1.0) | Direct grants of every user, group, and service account | `LIST USERS` and `USER DETAILS` | | `active_permissions()` (new in 4.1.0) | Effective permissions of every user, group, and service account | `LIST USERS` and `USER DETAILS` | | `all_permissions()` | Every permission and the levels it can be granted at | None | | `permissions([entityName])` | Effective permissions of the current user or a named entity | `USER DETAILS` for other entities | The page documents: - **Result columns and scope semantics.** Database-level rows have a `null` `table_name`. Each combination of entity, permission, table, and column appears once. A permission appears on two scopes when its grant option is narrower than the permission. Grants on tables or columns that do not exist yet are included, which `permissions()` omits. - **What `active_permissions()` adds to `active_grants()`.** It adds permissions inherited from groups, the implicit permission on the designated timestamp, and the permissions that `DATABASE ADMIN` includes. - **Required permissions.** Both functions need `LIST USERS` and `USER DETAILS`, even to read your own rows. The page lists the `Access denied` errors a caller gets without them. - **Limitations.** The built-in admin and external (SSO/OIDC) users are not listed, so you audit their mapped groups instead. Group memberships and `ASSUME SERVICE ACCOUNT` grants are not listed. With `acl.enabled=false` the functions return no rows. They cannot be used in materialized or live views, but regular views can call them. - **Verified examples with result tables**, all built on one set of entities and grants: - direct grants compared with effective permissions; - who can read a table, including database-level and column grants; - which entities hold the grant option; - the levels each permission can be granted at; - one entity's permissions, with the `origin` column. ## Materialized views and live views Eight Enterprise administrative functions are rejected in materialized view and live view queries: `active_grants()`, `active_permissions()`, `backup_instance_name()`, `backup_status()`, `backups()`, `permissions()`, `reload_tick_calendars()`, and `reload_tls()`. They check the caller's permissions, and a background refresh has no session to check against. This PR documents: - the restriction in the query constraints of `concepts/materialized-views.md`, `concepts/live-views.md`, `query/sql/create-mat-view.md`, and `query/sql/create-live-view.md`; - the `administrative function cannot be used in materialized view: <function>` error and its live view counterpart, in the `CREATE MATERIALIZED VIEW` and `CREATE LIVE VIEW` error tables. ## Access control on replicas New [Access control on replicas](https://preview-566--questdb-documentation.netlify.app/docs/security/rbac/#replicas) section in `security/rbac.md`: - Access control is managed on the primary. A read-only replica rejects statements such as `CREATE USER` and `GRANT`. - Before it authorizes a statement, the replica reloads its replicated access lists if new changes have arrived. - A statement waits up to 30 seconds for another session's reload. If the lists are still stale after that, the statement fails with `timed out waiting for the access lists to refresh [timeout=30000ms]` rather than being authorized against outdated permissions. ## Related changes - **Enterprise quick start:** corrects the claim that `all_permissions()` lists applied permissions. It now shows an `active_grants()` query for checking grants. - **RBAC:** - adds an audit snippet using `active_permissions()` and `active_grants()`; - notes that they require both `LIST USERS` and `USER DETAILS`; - links the permissions reference to `all_permissions()` and says that it lists the available permissions and their grant levels. - **`SHOW PERMISSIONS`:** links to `permissions()`, which returns the same rows as a table function. Also links to `active_permissions()`, which lists every entity at once. - **`GRANT`:** points to `active_grants()` for grants on tables or columns that do not exist yet, since `SHOW PERMISSIONS` does not show them. - **Changelog:** entries for the new page and for the view, replica, and quick start updates. ## Dependencies All merged and included in QuestDB Enterprise 4.1.0: - [questdb/questdb-enterprise#1222](questdb/questdb-enterprise#1222): ACL functions, view restriction, and replica refresh. - [questdb/questdb#7631](questdb/questdb#7631): OSS side of the view restriction. - [questdb/sql-parser#37](questdb/sql-parser#37): Web Console autocomplete and syntax highlighting for `active_permissions()` and `active_grants()`.
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
Register the new QuestDB Enterprise ACL inspection functions as table-valued functions:
active_permissions()returns effective permissions across persisted users, groups, and service accounts, including group inheritance.active_grants()returns direct grants across those entities.Both functions are added to the
CURSORsection oftableValuedFunctions, in alphabetical order. This makes them available for autocomplete in table-source contexts such asSELECT * FROM active_permissions(), while keeping them out of scalar-expression suggestions.Autocomplete regression tests cover both the positive
FROMcontext and the negativeSELECTexpression context.Dependencies
Verification
corepack yarn test: 15,105 tests passed, 1 skippedcorepack yarn vitest run tests/autocomplete.test.ts -t "active": 2 tests passedcorepack yarn typecheckcorepack yarn lint