December 7, 2017·4 min read·engineeringrqliteauthorizationdiagnostics

rqlite requires status permission for runtime diagnostics

rqlite 4.2.2 applies the status permission to expvar and pprof endpoints. The change separates a valid login from authorization to inspect the running Go process.

A database account allowed to query application tables does not necessarily need access to the process running those tables. Runtime counters and profiling endpoints expose a different category of information. rqlite 4.2.2, released on 7 December, requires the status permission for Go runtime diagnostics when authorization is configured.

The implementing patch in pull request 384 applies that check to expvar and pprof. It changes the security guide's definition of status from node status information to node status and Go runtime information. The permission vocabulary remains the same, but the runtime endpoints now enforce the intended category.

I consider that a useful distinction in a small database service. An application reader and an operator can both have legitimate accounts while needing different access. Keeping diagnostics behind an explicit permission lets the deployment express those roles without treating every valid password as authority to inspect the process.

Authentication already happens before routing

The released HTTP service first checks Basic Auth when a credential store exists. A missing login or invalid password returns HTTP 401 before endpoint dispatch. The December change therefore should not be described as adding authentication to previously unauthenticated diagnostics in every secured deployment.

The missing distinction was permission after authentication. Before the patch, routing invoked standalone expvar and pprof functions without an endpoint-specific status check. A user who passed the initial credential validation did not encounter the new permission gate at those functions.

Version 4.2.2 moves those functions into service methods. That gives them access to CheckRequestPerm, which accepts the requested permission or the general all permission for the authenticated user. The methods return 401 when the check fails and stop before serving the diagnostic content.

This preserves two separate questions. Credential validation establishes which configured user made the request. The endpoint check determines whether that user may inspect runtime information. The response code is the same for these failures in this implementation, but the checks occur at different stages.

Expvar and pprof share the permission

The expvar handler checks PermStatus before iterating registered variables and writing its JSON object. That prevents the handler from producing the process's diagnostic values for a user lacking the permission. Its serialization mechanism otherwise remains the same.

The pprof handler performs the same check before dispatching to the standard profiling handlers. Its dispatch names command-line information, profiling and symbol endpoints, with the default path handled by the pprof index. Authorization therefore precedes selection of the particular profiling response.

Using one permission for these interfaces fits the updated guide's wording. The runtime endpoints describe the running node, while the query permission concerns SQL access. The change does not grant execute, backup or membership privileges merely because a user can inspect diagnostics.

I find the placement of the check as important as its name. A permission description in documentation is insufficient if a route bypasses the code that enforces it. Moving the handlers onto the service makes the shared policy available where each diagnostic response begins.

Disabled endpoints remain unavailable

The router only selects expvar when the service's Expvar setting is enabled, and only selects pprof when Pprof is enabled. Otherwise those paths reach the not-found response. Availability and authorization therefore remain independent controls.

The patch adds a test for disabled runtime endpoints returning 404. It also extends authorization tests to include /debug/vars and the named pprof paths. Those tests cover missing credentials, incorrect passwords and insufficient permissions when the features are enabled.

This matters because a single denied request does not establish the whole policy. An endpoint can be unavailable because the feature is disabled, or available but inaccessible to a particular user. The tests distinguish the route-level setting from the permission decision made inside the enabled handler.

The implementation also permits requests when no credential store is configured. The new permission check does not automatically create an authentication policy for an otherwise open node. Its effect depends on the deployment using the existing credential and permission configuration.

Permissions stay local to the node

The 4.2.2 security guide describes a JSON file containing users, passwords and permission lists. It states that this configuration controls the local node and must be correct on every member. Replicated relational data does not make those files a replicated authorization policy.

The guide's example gives one user all and another query plus status. Under the updated meaning, the second user can inspect runtime information as well as query the database, while still lacking the separate execution permission. A query-only account expresses a different role and no longer acquires runtime inspection merely by passing login validation.

The release's other changelog entry fixes tests following changes in SQLite's schema catalog. The runtime permission change is the operationally visible correction. It brings expvar and pprof under the status policy while retaining separate feature switches, initial credential validation and node-local permission configuration.